はじめに
Advent of code 2024 の準備として、過去回の Advent of code 2015 を Livebook で楽しみます
本記事では Day 14 の Part 1 と Part 2 を解きます
問題文はこちら
実装したノートブックはこちら
セットアップ
Kino AOC をインストールします
Mix.install([
{:kino_aoc, "~> 0.1"}
])
Kino AOC の使い方はこちらを参照
入力の取得
"Advent of Code Helper" スマートセルを追加し、 Day 14 の入力を取得します
私の答え
私の答えです。
折りたたんでおきます。
▶を押して開いてください。
Part 1
回答
入力を正規表現でパースします
Regex.named_captures(
~r/(?<reindeer>[a-zA-Z]+) can fly (?<speed>\d+) km\/s for (?<keep>\d+) seconds, but then must rest for (?<rest>\d+)/,
"Comet can fly 14 km/s for 10 seconds, but then must rest for 127 seconds."
)
実行結果
%{"keep" => "10", "reindeer" => "Comet", "rest" => "127", "speed" => "14"}
各トナカイのスピード、持続時間、休憩時間、走行距離のマップ配列にします
reindeer_list =
puzzle_input
|> String.split("\n")
|> Enum.map(fn row ->
Regex.named_captures(
~r/(?<reindeer>[a-zA-Z]+) can fly (?<speed>\d+) km\/s for (?<keep>\d+) seconds, but then must rest for (?<rest>\d+)/,
row
)
|> then(fn %{"speed" => speed, "keep" => keep, "rest" => rest} ->
%{
speed: String.to_integer(speed),
keep: String.to_integer(keep),
rest: String.to_integer(rest),
distance: 0
}
end)
end)
実行結果
[
%{speed: 19, keep: 7, rest: 124, distance: 0},
%{speed: 3, keep: 15, rest: 28, distance: 0},
%{speed: 19, keep: 9, rest: 164, distance: 0},
%{speed: 19, keep: 9, rest: 158, distance: 0},
%{speed: 13, keep: 7, rest: 82, distance: 0},
%{speed: 25, keep: 6, rest: 145, distance: 0},
%{speed: 14, keep: 3, rest: 38, distance: 0},
%{speed: 3, keep: 16, rest: 37, distance: 0},
%{speed: 25, keep: 6, rest: 143, distance: 0}
]
各秒時点で各トナカイの走行距離を計算し、 2503 秒時点での最大値を求めます
1..2503
|> Enum.reduce(reindeer_list, fn sec, acc_reindeer_list ->
acc_reindeer_list
|> Enum.map(fn reindeer ->
remain = rem(sec, reindeer.keep + reindeer.rest)
if remain > 0 and remain <= reindeer.keep do
Map.put(reindeer, :distance, reindeer.distance + reindeer.speed)
else
reindeer
end
end)
end)
|> Enum.map(&(&1.distance))
|> Enum.max()
Part 2
回答
各トナカイに point: 0
を初期値として与えます
reindeer_list =
puzzle_input
|> String.split("\n")
|> Enum.map(fn row ->
Regex.named_captures(
~r/(?<reindeer>[a-zA-Z]+) can fly (?<speed>\d+) km\/s for (?<keep>\d+) seconds, but then must rest for (?<rest>\d+)/,
row
)
|> then(fn %{"speed" => speed, "keep" => keep, "rest" => rest} ->
%{
speed: String.to_integer(speed),
keep: String.to_integer(keep),
rest: String.to_integer(rest),
distance: 0,
point: 0
}
end)
end)
各秒数時点で最も走行距離が長いトナカイにポイントを加算していき、最大ポイントを求めます
1..2503
|> Enum.reduce(reindeer_list, fn sec, acc_reindeer_list ->
acc_reindeer_list =
acc_reindeer_list
|> Enum.map(fn reindeer ->
remain = rem(sec, reindeer.keep + reindeer.rest)
if remain > 0 and remain <= reindeer.keep do
Map.put(reindeer, :distance, reindeer.distance + reindeer.speed)
else
reindeer
end
end)
max_distance =
acc_reindeer_list
|> Enum.map(&(&1.distance))
|> Enum.max()
acc_reindeer_list
|> Enum.map(fn reindeer ->
if reindeer.distance == max_distance do
Map.put(reindeer, :point, reindeer.point + 1)
else
reindeer
end
end)
end)
|> Enum.map(&(&1.point))
|> Enum.max()
まとめ
問題文から ChatGPT に画像を生成してもらいました
繰り返しだけで解ける問題だったので簡単でした
今のところ、 Day 7 で一番苦労しています