はじめに
Advent of code 2024 の準備として、過去回の Advent of code 2015 を Livebook で楽しみます
本記事では Day 6 の Part 2 を解きます
問題文はこちら
実装したノートブックはこちら
Part 1 はこちら
セットアップ
Kino AOC をインストールします
Mix.install([
{:kino_aoc, "~> 0.1"}
])
Kino AOC の使い方はこちらを参照
入力の取得
"Advent of Code Helper" スマートセルを追加し、 Day 6 の入力を取得します
私の答え
私の答えです。
折りたたんでおきます。
▶を押して開いてください。
回答
正規表現で操作内容を取得する部分は Part 1 と同じです
Regex.named_captures(~r/(?<op>.+) (?<sx>\d+),(?<sy>\d+) through (?<ex>\d+),(?<ey>\d+)/, "turn on 0,0 through 999,999")
-
op
: ライトに対する操作("torn on" | "torn off" | "toggle"
) -
sx
,sy
: 操作開始位置の座標 -
ex
,ey
: 操作終了位置の座標
Part 2 では操作内容が古代エルフ語での解釈に変わっています
- "torn on": 明度を 1 段階上げる
- "torn off": 明度を 1 段階下げる(ただし、下限は 0)
- "toggle": 明度を 2 段階上げる
Part 1 の点灯マップを明度マップとして、論理値ではなく明度の整数を保持します
Enum.reduce
で各行の操作を順に実行して行きます
"torn off" 時には 0 未満にならないよう、 brightness - 1
ではなく max(0, brightness - 1)
という操作にします
最後に全ての明度を合計します
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 ->
brightness = Map.get(y_map, {x, y}, 0)
brightness =
case op do
"turn on" -> brightness + 1
"turn off" -> max(0, brightness - 1)
_ -> brightness + 2
end
Map.put(y_map, {x, y}, brightness)
end)
end)
end)
|> Enum.map(fn {_, brightness} -> brightness end)
|> Enum.sum()
まとめ
問題文から ChatGPT に画像を生成してもらいました
古代エルフ語は興味深いですね