Day 05
Mix.install([
{:kino, "~> 0.7.0"}
])
example_input =
Kino.Input.textarea("example input:")
|> Kino.render()
real_input = Kino.Input.textarea("real input:")
Common
parse = fn input ->
[stack_data, procedure_data] =
input
|> Kino.Input.read()
|> String.split("\n\n", trim: true)
|> Enum.map(&String.split(&1, "\n", trim: true))
stacks =
stack_data
|> Enum.drop(-1)
|> Enum.map(fn line ->
line
|> String.split("", trim: true)
|> tl()
|> Enum.take_every(4)
end)
|> Enum.zip_with(& &1)
|> Enum.map(fn stack ->
stack
|> Enum.reverse()
|> Enum.reduce([], fn
" ", acc -> acc
value, acc -> [value | acc]
end)
end)
procedures =
procedure_data
|> Enum.map(fn line ->
[_, count, _, from, _, to] = String.split(line)
[count, from, to] = [count, from, to] |> Enum.map(&String.to_integer/1)
%{count: count, from: from - 1, to: to - 1}
end)
{stacks, procedures}
end
read_heads = fn stacks ->
stacks
|> Enum.map(&hd/1)
|> Enum.join()
end
Part 1
follow_procedures = fn {stacks, procedures} ->
procedures
|> Enum.reduce(stacks, fn procedure, stacks ->
1..procedure.count
|> Enum.reduce(stacks, fn _, stacks ->
{item, stacks} = get_and_update_in(stacks, [Access.at(procedure.from)], &Enum.split(&1, 1))
update_in(stacks, [Access.at(procedure.to)], &[item | &1])
end)
end)
end
real_input
|> then(parse)
|> then(follow_procedures)
|> then(read_heads)
Part 2
follow_procedures = fn {stacks, procedures} ->
procedures
|> Enum.reduce(stacks, fn procedure, stacks ->
{items, stacks} =
get_and_update_in(stacks, [Access.at(procedure.from)], &Enum.split(&1, procedure.count))
update_in(stacks, [Access.at(procedure.to)], &Enum.concat(items, &1))
end)
end
real_input
|> then(parse)
|> then(follow_procedures)
|> then(read_heads)