LoginSignup
18
4

More than 3 years have passed since last update.

ElixirでAtCoderのABC123を解いてみる!

Last updated at Posted at 2020-12-02

この記事は、fukuoka.ex Elixir/Phoenix Advent Calendar 2020 3日目です。
前日は、@marocchino さんの優しいエラーメッセージを書きたいでした。

はじめに :christmas_tree::christmas_tree::christmas_tree:

今年のごくワタシ的Elixir活動まとめ

  • 昨年と比べて、1年間の間にずいぶんできることは増えたように感じています
  • 本題に入る前に少しご紹介させてください

ElixirConf EU Virtual

  • 2020/06/18-19に行われたElixirConf EU VirtualにてLightning Talkを行いました
  • :raised_hand: 手をあげる勇気ーー蛮勇さえあれば誰でもLTをさせてくれたようにおもいます
  • リモートで開催されたのでおもいきってやってみました
  • 資料 ツイート

Interface(インターフェース) 2021年 1 月号

Enjoy Elixirシリーズ!

コミット

  • ドキュメントの修正が中心ではありますがプルリク等を採用してもらえました
  • こうして並べてみると、けっこう有名なHexたちが並んでいるようにおもいます

phoenix_live_view

nerves-project/nerves_bootstrap

timex

crawly

問題

AtCoderについて

  • 世界最高峰の競技プログラミングサイトです
  • だいたい毎週土曜や日曜の21時すぎにコンテストが行われているようです
  • 出題された問題の答えを出力するプログラムを書いて提出することで自動的に採点されます
  • 実行時間が長かったり、メモリの使用量が多いとパスできません
  • 競技プログラミングというもの自体に私は馴染みがなかったのですが、今年からはじめました
  • Elixirで解く際に使える初歩的なノウハウはZenn.devにまとめています

準備

  • Elixirをインストールしましょう
  • プロジェクトを作っておきます
$ mix new at_coder
$ cd at_coder

問題A - Five Antennas

  • 問題文はリンク先をご参照くださいませ :bow:
lib/abc_123_a.ex
defmodule Abc123A do
  def main do
    a = IO.read(:line) |> String.trim() |> String.to_integer()
    b = IO.read(:line) |> String.trim() |> String.to_integer()
    c = IO.read(:line) |> String.trim() |> String.to_integer()
    d = IO.read(:line) |> String.trim() |> String.to_integer()
    e = IO.read(:line) |> String.trim() |> String.to_integer()
    k = IO.read(:line) |> String.trim() |> String.to_integer()

    solve(a, b, c, d, e, k)
    |> IO.puts()
  end

  @doc ~S"""
  https://atcoder.jp/contests/abc123/tasks/abc123_a

  ## Examples

      iex> Abc123A.solve(1, 2, 4, 8, 9, 15)
      "Yay!"
      iex> Abc123A.solve(15, 18, 26, 35, 36, 18)
      ":("

  """
  def solve(a, b, c, d, e, k) do
    [b - a, c - a, d - a, e - a, c - b, d - b, e - b, d - c, e - c, e - d]
    |> Enum.filter(&(&1 > k))
    |> Enum.empty?()
    |> if(do: "Yay!", else: ":(")
  end
end
  • ## Examplesのところに書いてあるものは、Doctestsと呼ばれるものでしてテストができます
  • 解答のキモとなる関数について、問題に書いてある入力例をインプットして出力例の通りアウトプットされるかを確かめています
  • test/at_coder_test.exsに設定を足しておきましょう
test/at_coder_test.exs
defmodule AtCoderTest do
  use ExUnit.Case
  doctest Abc123A
$ mix test
..........

Finished in 0.2 seconds
9 doctests, 1 test, 0 failures
  • 提出の際にはモジュール名はMainにしておいてください
  • :tada::tada::tada:
  • この調子で問題を解いていきます

問題B - Five Dishes

  • 問題文はリンク先をご参照くださいませ :bow:
lib/abc_123_b.ex
defmodule Abc123B do
  def main do
    a = IO.read(:line) |> String.trim() |> String.to_integer()
    b = IO.read(:line) |> String.trim() |> String.to_integer()
    c = IO.read(:line) |> String.trim() |> String.to_integer()
    d = IO.read(:line) |> String.trim() |> String.to_integer()
    e = IO.read(:line) |> String.trim() |> String.to_integer()

    solve(a, b, c, d, e)
    |> IO.puts()
  end

  @doc ~S"""
  https://atcoder.jp/contests/abc123/tasks/abc123_b

  ## Examples

      iex> Abc123B.solve(29, 20, 7, 35, 120)
      215
      iex> Abc123B.solve(123, 123, 123, 123, 123)
      643

  """
  def solve(a, b, c, d, e) do
    list = [a, b, c, d, e]

    last_order = last_order(list)

    List.delete(list, last_order)
    |> Enum.map(&ceil_tens_point/1)
    |> Enum.sum()
    |> Kernel.+(last_order)
  end

  defp last_order(list) do
    list
    |> Enum.map(&{rem(&1, 10), &1})
    |> Enum.reject(fn {ones_place, _} -> ones_place == 0 end)
    |> Enum.min_by(fn {ones_place, _} -> ones_place end, fn -> {nil, 0} end)
    |> elem(1)
  end

  defp ceil_tens_point(n) when rem(n, 10) == 0, do: n

  defp ceil_tens_point(n), do: n + 10 - rem(n, 10)
end
  • 提出の際にはモジュール名はMainにしておいてください
  • :tada::tada::tada:

問題C - Five Transportations

問題D - Cake 123

Wrapping Up :qiita-fabicon:

おまけ :lgtm::lgtm::lgtm:

iex> [87, 101, 32, 97, 114, 101, 32, 116, 104, 101, 32, 65, 108, 99, 104, 101, 109,
 105, 115, 116, 115, 44, 32, 109, 121, 32, 102, 114, 105, 101, 110, 100, 115,
 33]
'???????????????????'
  • IExに貼ってご確認ください
  • 作り方は以下の通りです
iex> IEx.configure(inspect: [limit: :infinity, charlists: :as_lists])
:ok

iex> "your string" |> String.to_charlist()                           
[121, 111, 117, 114, 32, 115, 116, 114, 105, 110, 103]
18
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
4