Day 5
Mix.install([
{:kino, "~> 0.11.0"}
])
Section
input = Kino.Input.textarea("Input")
input
|> Kino.Input.read()
|> String.split("\n\n")
|> then(fn [seeds | maps] ->
maps
|> Enum.map(fn map ->
map
|> String.split("\n")
|> Enum.drop(1)
|> Enum.map(fn mapping ->
mapping
|> String.split(" ", trim: true)
|> Enum.map(&String.to_integer/1)
|> then(fn [dst, src, size] ->
{src..(src + size - 1), dst - src}
end)
end)
end)
|> then(fn maps ->
seeds
|> String.split(" ")
|> Enum.drop(1)
|> Enum.map(&String.to_integer/1)
|> Enum.map(fn seed ->
Enum.reduce(maps, seed, fn map, seed ->
Enum.find_value(map, seed, fn {range, step} ->
if seed in range, do: seed + step
end)
end)
end)
|> Enum.min()
end)
end)
input
|> Kino.Input.read()
|> String.split("\n\n")
|> then(fn [seeds | maps] ->
maps
|> Enum.map(fn map ->
map
|> String.split("\n")
|> Enum.drop(1)
|> Enum.map(fn mapping ->
mapping
|> String.split(" ", trim: true)
|> Enum.map(&String.to_integer/1)
|> then(fn [dst, src, size] ->
{src..(src + size - 1), dst - src}
end)
end)
|> Enum.sort_by(&Enum.min(elem(&1, 0)))
|> then(fn
[{0.._, _} | _] = list -> list
[{n.._, _} | _] = list -> [{0..(n - 1), 0} | list]
end)
|> Enum.chunk_every(2, 1)
|> Enum.flat_map(fn
[{_..max1, _} = head, {min2.._, _}] when max1 + 1 == min2 ->
[head]
[{_..max1, _} = head, {min2.._, _}] ->
[head, {(max1 + 1)..(min2 - 1), 0}]
[{_..max, _} = rest] ->
[rest, {(max + 1)..((max + 1) * 10), 0}]
end)
end)
|> then(fn maps ->
seeds
|> String.split(" ")
|> Enum.drop(1)
|> Enum.map(&String.to_integer/1)
|> Enum.chunk_every(2)
|> Enum.map(fn [start, step] -> start..(start + step - 1) end)
|> then(fn seeds ->
Enum.reduce(maps, seeds, fn map, seeds ->
Enum.flat_map(seeds, fn min..max ->
Enum.reduce(map, [], fn
{lower..upper, _step}, acc when upper < min or lower > max ->
acc
{lower..upper, step}, acc ->
[Range.shift(max(min, lower)..min(max, upper), step) | acc]
end)
end)
end)
end)
end)
|> Enum.min()
end)
|> Enum.min()