gumi Inc. が Erlang & Elixir Fest 2018 の会場で配布しているクイズを掲載しています。
あなたはプログラマーとして、とあるゲーム開発プロジェクトに配属された。 プロジェクトに配属され、はじめに与えられた業務は、次のような ASCII アートで記述された迷路を入力として受け取り、点数を出力するコマンドを作成することだった。 この業務には前任者がいたようだが、現在は連絡がとれない。幸いなことにコードは残されているようだ。
maze.txt:
WWWWWWWWWW
WSWW 1 W
W WWW W
W 1 W
W 1WWWW W
W W 1 W
W 1 W W
W WWW1WWW
W W 1 1GW
WWWWWWWWWW
記号 | 意味 |
---|---|
S | スタート地点 |
G | ゴール地点 |
空白スペース | 通路 |
W | 壁 |
1 | 通過すると得点を得る通路 |
- S から開始する
- G を目指す
- 一度に上下左右いずれかに一マスだけ移動できる
- 一度通過した通路は再び通れない
- W は通過できない
- 1 を通過で一点加算
gumimaze.exs:
defmodule Gumimaze do
def read() do
lines = "maze.txt" |> File.read!() |> String.trim() |> String.split("\n")
for {line, y} <- Enum.with_index(lines), {c, x} <- Enum.with_index(String.to_charlist(line)), into: %{} do
{{x, y}, c}
end
end
def solve(maze) do
{x, y} = elem(Enum.find(maze, fn {_, v} -> v == ?S end), 0)
try do
walk(maze, x, y, %{}, 0)
catch
pt -> pt
end
end
defp walk(maze, x, y, walked, pt) do
walked = Map.put(walked, {x, y}, true)
for {x2, y2} <- [{x + 1, y}, {x, y + 1}, {x - 1, y}, {x, y - 1}] do
case {walked[{x2, y2}], maze[{x2, y2}]} do
{true, _} -> :walked
{_, ?W} -> :wall
{_, ?\s} -> walk(maze, x2, y2, walked, pt)
{_, ?1} -> walk(maze, x2, y2, walked, pt + 1)
{_, ?G} -> throw(pt)
end
end
end
end
Gumimaze.read() |> Gumimaze.solve() |> IO.puts()
あなたは連絡の取れない前任者から業務を引き継ぐため、前任者のコードを読み解く必要がある。 コマンド実行時に何が出力されるか予測せよ。
あなたはコードを読み解き、コマンドの動作確認を終えたが、本件の担当プランナーからコマンドの仕様変更を依頼された。 ルールに従ってゴールした際、最大の点数を獲得するよう前任者のコードを修正せよ。
あなたは本件の担当プランナーから依頼された仕様変更を無事に完遂し空き時間ができた。
暇つぶしに迷路探索を軽量プロセスを用いて平行化せよ。
Mission2 と Mission3 の回答は、次の手順で行ってください。
- 前述のコードを Gist や Wandbox などに記録する
- 前述の URL を本記事のコメント欄か、ハッシュタグ #elixirjp #elixirfestjp #gumimaze を付与し Twitter へ投稿する
Erlang & Elixir Fest 2018 終了後、回答例を本記事に掲載予定です。
- テクニカルコンサルタント 募集要項 主に Elixir を使用
https://gist.github.com/snamiki1212/42646c0b150d948854a040b59163886a
https://gist.github.com/snamiki1212/4abcbbbe3c6da6733af95e4728c94531
もう少しリファクタ余地がありそうですが、ひとまず動いたので