はじめに
Advent of code 2024 の準備として、過去回の Advent of code 2015 を Livebook で楽しみます
本記事では Day 17 の Part 1 と Part 2 を解きます
問題文はこちら
実装したノートブックはこちら
セットアップ
Kino AOC をインストールします
Mix.install([
{:kino_aoc, "~> 0.1"}
])
Kino AOC の使い方はこちらを参照
入力の取得
"Advent of Code Helper" スマートセルを追加し、 Day 17 の入力を取得します
私の答え
私の答えです。
折りたたんでおきます。
▶を押して開いてください。
Part 1
回答
入力を数値の配列に変換します
containers =
puzzle_input
|> String.split("\n")
|> Enum.map(&String.to_integer(&1))
|> Enum.sort(:desc)
実行結果
[50, 48, 45, 44, 42, 41, 35, 35, 33, 30, 24, 20, 18, 18, 16, 14, 13, 13, 6, 1]
配列から指定数の全ての組み合わせを取得するモジュールを用意します
defmodule Combinations do
def all(_, 0), do: [[]]
def all([], _), do: []
def all(list, n) when length(list) == n, do: [list]
def all([head | tail], n) do
with_head = for combo <- all(tail, n - 1), do: [head | combo]
without_head = all(tail, n)
with_head ++ without_head
end
end
コンテナの数を 1 個から 20 個まで順に増やしながら、合計が 150 になる組み合わせの数を足していきます
1..20
|> Enum.map(fn length ->
containers
|> Combinations.get(length)
|> Enum.count(fn combination -> Enum.sum(combination) == 150 end)
end)
|> Enum.sum()
Part 2
回答
コンテナの数を 1 個から 20 個まで順に増やしながら、合計が 150 になる組み合わせが 1 つでもあれば、そのときの組み合わせ数を取得します
1..20
|> Enum.reduce_while(nil, fn length, _acc ->
num =
containers
|> Combinations.get(length)
|> Enum.count(fn combination -> Enum.sum(combination) == 150 end)
if num > 0 do
{:halt, num}
else
{:cont, nil}
end
end)
まとめ
問題文から ChatGPT に画像を生成してもらいました
全ての組み合わせさえ取得できれば、そのまま答えに辿り着ける問題でした