3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ElixirでHHKB プログラミングコンテスト 2020に参加してみる

Posted at

はじめに

  • Elixirでやってみました
  • いつも過去問のA〜Cまでをしかもものすごく時間をかけて解いているだけですが、2020/10/10(土) 21:00〜開催されたHHKB プログラミングコンテスト 2020に出場してみました
  • 初出場です
  • Cまではクリアしたいとおもいましたが、時間内にはBまででした:man:
  • トップの方は30分くらいで全部解いているようでただただすごいなあとおもっています

問題

準備

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

問題A - Keyboard

  • 問題文はリンク先をご参照くださいませ :bow:
  • 時間内に解けました!
lib/hhkb2020_a.ex
defmodule HHKB2020A do
  def main do
    s = IO.read(:line) |> String.trim()
    t = IO.read(:line) |> String.trim()

    solve(s, t)
    |> IO.puts()
  end

  @doc ~S"""
  https://atcoder.jp/contests/hhkb2020/tasks/hhkb2020_a

  ## Examples

      iex> HHKB2020A.solve("Y", "a")
      "A"
      iex> HHKB2020A.solve("N", "b")
      "b"

  """
  def solve(s, t) when s == "Y", do: String.upcase(t)

  def solve(_s, t), do: t
end
  • ## Examplesのところに書いてあるものは、Doctestsと呼ばれるものでしてテストができます
  • 解答のキモとなる関数について、問題に書いてある入力例をインプットして出力例の通りアウトプットされるかを確かめています
  • test/at_coder_test.exsに設定を足しておきましょう
test/at_coder_test.exs
defmodule AtCoderTest do
  use ExUnit.Case
  doctest HHKB2020A
$ mix test
..........

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

問題B - Futon

  • 問題文はリンク先をご参照くださいませ :bow:
  • 時間内に解けました!
lib/hhkb2020_a.ex
defmodule HHKB2020B do
  def main do
    [h, w] =
      IO.read(:line) |> String.trim() |> String.split(" ") |> Enum.map(&String.to_integer/1)

    list_of_lists = for(_ <- 1..h, do: IO.read(:line) |> String.trim() |> String.codepoints())

    transposed =
      for(j <- 0..(w - 1), i <- 0..(h - 1), do: Enum.at(list_of_lists, i) |> Enum.at(j))
      |> Enum.chunk_every(h)

    solve(list_of_lists)
    |> Kernel.+(solve(transposed))
    |> IO.puts()
  end

  @spec solve(any) :: any
  @doc ~S"""
  https://atcoder.jp/contests/hhkb2020/tasks/hhkb2020_b

  ## Examples

      iex> HHKB2020B.solve([~w(. . #), ~w(# . .)])
      2
      iex> HHKB2020B.solve([~w(. #), ~w(. .), ~w(# .)])
      1
      iex> HHKB2020B.solve([~w(. #), ~w(# .)])
      0

  """
  def solve(list_of_lists) do
    Enum.map(list_of_lists, &Enum.chunk_every(&1, 2, 1, :discard))
    |> Enum.reduce(0, fn list_of_lists, acc ->
      list_of_lists
      |> Enum.count(fn [a, b] -> a == "." && b == "." end)
      |> Kernel.+(acc)
    end)
  end
end
  • 提出の際にはモジュール名はMainにしておいてください
  • :tada::tada::tada:
  • ここまで開始から30分くらいたっていました
  • トップの方はもうそろそろF問題が終わりそうな時間だったということです:rocket::rocket::rocket:

問題C - Neq Min

  • 問題文はリンク先をご参照くださいませ :bow:
  • あと残り60分ありましたが時間内には終わりませんでした
  • 居残りで解けました
    • IO.puts/2の呼び出しを1回にしたのが効果が大きかったです
    • もうひとつはacc_rangeってかいてあるところを毎回0..200_001とやるとタイムアウトでパスできませんでした
    • 効果が絶大だったのはIO.puts/2の呼び出しを1回にしたほうです
lib/hhkb2020_c.ex
defmodule HHKB2020C do
  @range 0..200_001

  def main do
    IO.read(:line)

    IO.read(:line)
    |> String.trim()
    |> String.split(" ")
    |> Enum.map(&String.to_integer/1)
    |> solve()
    |> Enum.join("\n")
    |> IO.puts()
  end

  @doc ~S"""
  https://atcoder.jp/contests/hhkb2020/tasks/hhkb2020_c

  ## Examples

      iex> HHKB2020C.solve([1, 1, 0, 2])
      [0, 0, 2, 3]

      iex> HHKB2020C.solve([5, 4, 3, 2, 1, 0, 7, 7, 6, 6])
      [0, 0, 0, 0, 0, 6, 6, 6, 8, 8]

  """
  def solve(list) do
    Enum.reduce(list, {[], %{}, 0, @range}, fn p, {acc_list, acc_map, acc_min, acc_range} ->
      acc_map = Map.put(acc_map, p, true)

      if Map.get(acc_map, acc_min) == nil do
        {[acc_min | acc_list], acc_map, acc_min, acc_range}
      else
        min =
          acc_range
          |> Enum.find(nil, fn i ->
            case Map.fetch(acc_map, i) do
              {:ok, true} -> false
              :error -> true
            end
          end)

        {[min | acc_list], acc_map, min, min..200_001}
      end
    end)
    |> elem(0)
    |> Enum.reverse()
  end
end
  • 提出の際にはモジュール名はMainにしておいてください
  • Rubyでも書いてみました
hash = {}
 
gets.to_i
result = gets.split.map(&:to_i).inject([[], 0]) do |(acc_list, acc_min), item|
  hash[item] = item
  if hash[acc_min].nil?
    [acc_list << acc_min, acc_min]
  else
    value = (acc_min..200001).find { |i| hash[i].nil? }
    [acc_list << value, value]
  end
end
 
result[0].each { |v| puts v }

Wrapping Up :qiita-fabicon:

  • とにかくElixirを書くことを楽しんでいます
  • Enjoy Elixir!!! :fire::rocket::rocket::rocket:
3
0
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
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?