はじめに
Advent of code 2024 の準備として、過去回の Advent of code 2015 を Livebook で楽しみます
本記事では Day 6 の Part 1 を解きます
問題文はこちら
実装したノートブックはこちら
セットアップ
Kino AOC をインストールします
Mix.install([
{:kino_aoc, "~> 0.1"}
])
Kino AOC の使い方はこちらを参照
入力の取得
"Advent of Code Helper" スマートセルを追加し、 Day 6 の入力を取得します
私の答え
私の答えです。
折りたたんでおきます。
▶を押して開いてください。
回答
各行の指示を正規表現でパースします
Regex.named_captures
を使うことで、正規表現内で ?<キー>
と指定した箇所に該当する文字列が取得できます
Regex.named_captures(~r/(?<op>.+) (?<sx>\d+),(?<sy>\d+) through (?<ex>\d+),(?<ey>\d+)/, "turn on 0,0 through 999,999")
上記コードの実行結果は以下のようになります
%{"ex" => "999", "ey" => "999", "op" => "turn on", "sx" => "0", "sy" => "0"}
-
op
: ライトに対する操作("torn on" | "torn off" | "toggle"
) -
sx
,sy
: 操作開始位置の座標 -
ex
,ey
: 操作終了位置の座標
座標毎に点灯しているかどうかの論理値を点灯マップ保持します
例えば座標 {0, 0}
(x方向0番目、y方向0番目) と {1, 2}
だけが点灯している場合、 %{{0, 0} => true, {1, 2} => true}
にします
Enum.reduce
で空の点灯マップ(全て消灯状態)から順に操作を実行し、最終的に点灯している座標の数を数えます
puzzle_input
|> String.split("\n")
|> Enum.reduce(%{},fn instruction, map ->
%{"op" => op, "sx" => sx, "sy" => sy, "ex" => ex, "ey" => ey} =
Regex.named_captures(
~r/(?<op>.+) (?<sx>\d+),(?<sy>\d+) through (?<ex>\d+),(?<ey>\d+)/,
instruction
)
[sx, sy, ex, ey] = Enum.map([sx, sy, ex, ey], &String.to_integer(&1))
Enum.reduce(sx..ex, map, fn x, x_map ->
Enum.reduce(sy..ey, x_map, fn y, y_map ->
lit = Map.get(y_map, {x, y}, false)
new =
case op do
"turn on" -> true
"turn off" -> false
_ -> !lit
end
Map.put(y_map, {x, y}, new)
end)
end)
end)
|> Enum.count(fn {_, lit} -> lit end)
まとめ
問題文から ChatGPT に画像を生成してもらいました
特に工夫しないで書いたら実行に 90 秒くらい掛かってしまいました
AtCoder だと時間切れになりそうですが、 AOC は時間制限がないのでコレで良しとします
Part 2 はこちら