はじめに
Advent of code 2024 Day 11 の Part 1 を解きます
問題文はこちら
実装したノートブックはこちら
セットアップ
Kino AOC をインストールします
Mix.install([
{:kino_aoc, "~> 0.1"}
])
Kino AOC の使い方はこちらを参照
入力の取得
"Advent of Code Helper" スマートセルを追加し、 Day 11 の入力を取得します
私の答え
私の答えです。
折りたたんでおきます。
▶を押して開いてください。
回答
入力例で考えてみます
small_sample_input = "0 1 10 99 999"
まずは石を数値の配列にします
stones =
small_sample_input
|> String.split(" ")
|> Enum.map(&String.to_integer(&1))
実行結果
[0, 1, 10, 99, 999]
問題文の処理を何も考えずに実装します
Integer.digits
は 123
を [1, 2, 3]
にする関数です
Integer.undigits
は [1, 2, 3]
を 123
にする関数です
blink = fn stone ->
cond do
stone == 0 ->
[1]
Integer.digits(stone) |> length() |> rem(2) == 0 ->
digits = Integer.digits(stone)
half_size = digits |> length() |> div(2)
[
digits |> Enum.slice(0, half_size) |> Integer.undigits(),
digits |> Enum.slice(half_size, half_size) |> Integer.undigits(),
]
true ->
[stone * 2024]
end
end
この処理を全ての医師に対して実行します
Enum.flat_map(stones, fn stone -> blink.(stone) end)
実行結果
[1, 2024, 1, 0, 9, 9, 2021976]
次の例を実行してみます
stones =
"125 17"
|> String.split(" ")
|> Enum.map(&String.to_integer(&1))
6回繰り返すので Enum.reduce
で指定回数実行し、最後に長さを取得します
1..6
|> Enum.reduce(stones, fn _, acc_stones ->
Enum.flat_map(acc_stones, fn stone -> blink.(stone) end)
|> IO.inspect()
end)
|> length()
標準出力
[253000, 1, 7]
[253, 0, 2024, 14168]
[512072, 1, 20, 24, 28676032]
[512, 72, 2024, 2, 0, 2, 4, 2867, 6032]
[1036288, 7, 2, 20, 24, 4048, 1, 4048, 8096, 28, 67, 60, 32]
[2097446912, 14168, 4048, 2, 0, 2, 4, 40, 48, 2024, 40, 48, 80, 96, 2, 8, 6, 7,
6, 0, 3, 2]
実行結果
22
25 回繰り返します
1..25
|> Enum.reduce(stones, fn _, acc_stones ->
Enum.flat_map(acc_stones, fn stone -> blink.(stone) end)
end)
|> length()
実行結果
55312
実際の入力に対して実行します
stones =
puzzle_input
|> String.split(" ")
|> Enum.map(&String.to_integer(&1))
1..25
|> Enum.reduce(stones, fn _, acc_stones ->
Enum.flat_map(acc_stones, fn stone -> blink.(stone) end)
end)
|> length()
まとめ
問題文から ChatGPT に画像を生成してもらいました
ここまでは簡単でした
お察しの通り、繰り返す回数が増えるととんでもない計算量になってしまうので、、、
Part 2 はこちら