$\huge{元氣ですかーーーーッ!!!}$
$\huge{元氣があればなんでもできる!}$
$\huge{闘魂とは己に打ち克つこと。}$
$\huge{そして闘いを通じて己の魂を磨いていく}$
$\huge{ことだと思います}$
はじめに
@torifukukaiou さんの パク リスペクト記事です
Elixir Livebook で Advent of Code 2023 の問題を解いてみます
実装したノートブックはこちら
問題はこちら
Part 1 はこちら
セットアップ
Kino AOC をインストールします
Mix.install([
{:kino_aoc, "~> 0.1.5"}
])
Kino AOC の使い方はこちらを参照
入力の取得
Day 5 の入力を取得します
私の答え
私の答えです。
折りたたんでおきます。
▶を押して開いてください。
details
回答用のモジュールです
入力を扱いやすい形にするための parse
と、回答を作るための resolve
関数を持っています
defmodule Resolver do
def parse(input) do
input
|> String.split("\n\n")
|> Enum.into(%{}, fn group ->
group
|> String.split("\n")
|> parse_group()
end)
end
defp parse_group(group) when length(group) == 1 do
seeds =
group
|> hd()
|> String.split(" ")
|> tl()
|> Enum.map(&String.to_integer(&1))
|> Enum.chunk_every(2)
|> Enum.map(fn [start, len] ->
%{
start_index: start,
end_index: start + len - 1
}
end)
{:seeds, seeds}
end
defp parse_group(group) do
group_name =
group
|> hd()
|> String.slice(0..-6)
|> String.replace("-", "_")
|> String.to_atom()
mappings =
group
|> tl()
|> Enum.map(fn line ->
[dst, src, len] =
line
|> String.split(" ")
|> Enum.map(&String.to_integer(&1))
%{
src: src,
dst: dst,
len: len
}
end)
{group_name, mappings}
end
def resolve(maps) do
0
|> Stream.iterate(& &1 + 1)
|> Enum.reduce_while(nil, fn location, _acc ->
seed =
location
|> reverse_search(maps.humidity_to_location)
|> reverse_search(maps.temperature_to_humidity)
|> reverse_search(maps.light_to_temperature)
|> reverse_search(maps.water_to_light)
|> reverse_search(maps.fertilizer_to_water)
|> reverse_search(maps.soil_to_fertilizer)
|> reverse_search(maps.seed_to_soil)
maps.seeds
|> Enum.any?(fn %{start_index: start_index, end_index: end_index} ->
seed >= start_index and seed <= end_index
end)
|> if do
{:halt, location}
else
{:cont, nil}
end
end)
end
defp reverse_search(key, mappings) do
target_mapping =
Enum.find(mappings, fn mapping ->
key >= mapping.dst and key <= (mapping.dst + mapping.len - 1)
end)
if is_nil(target_mapping) do
key
else
target_mapping.src + key - target_mapping.dst
end
end
end
parse
は Part 1 では無駄に難しく考えていました
\n\n
で先に区切れば単純に空白行でグループ化できますね
resolve
ではついに計算量を考慮しなければならなくなりました
seeds
が範囲指定になったため、 Part 1 と同じロジックでは、いつまで経っても計算が終わりません
最小値を求める問題なので、 location の方から逆引きするようにして、 0 から順に種 ID が seeds の範囲内に入っているかチェックしていきます
まとめ
いよいよ計算量を考えないといけなくなリました
ここからが本番、という感じですね