Advent of Code 2022
Mix.install([
{:req, "~> 0.3.2"}
])
Day 5
input =
"https://adventofcode.com/2022/day/5/input"
|> Req.get!(headers: [cookie: "session=#{System.get_env("AOC_COOKIE")}"])
|> Map.get(:body)
sample = """
[D]
[N] [C]
[Z] [M] [P]
1 2 3
move 1 from 2 to 1
move 3 from 1 to 3
move 2 from 2 to 1
move 1 from 1 to 2
"""
Part 1
%{false: stacks, true: ops} =
input
|> String.split("\n", trim: true)
|> Enum.filter(&(!String.starts_with?(&1, " 1")))
|> Enum.group_by(&String.starts_with?(&1, "move"))
# |> dbg()
stacks =
stacks
|> Enum.map(fn line ->
Regex.scan(~r/( |\[\w]) ?/, line, capture: :all_but_first)
|> Enum.map(fn
[" "] -> nil
[s] -> String.replace(s, ~r"[\[\]]", "")
end)
end)
# transpose
|> Enum.zip_with(& &1)
|> Enum.map(fn stack ->
stack
|> Enum.filter(& &1)
end)
# turn into a map
|> Enum.with_index()
|> Map.new(fn {v, k} -> {k + 1, v} end)
n_stacks = stacks |> Map.keys() |> Enum.count()
ops =
Enum.map(ops, fn line ->
Regex.run(~r/move (\d+) from (\d+) to (\d+)/, line)
|> tl()
|> Enum.map(&String.to_integer/1)
end)
stacks =
Enum.reduce(ops, stacks, fn [n, from, to], acc ->
Enum.reduce(1..n, acc, fn _, stacks ->
to_stack = [hd(stacks[from]) | stacks[to]]
from_stack = tl(stacks[from])
stacks
|> Map.put(from, from_stack)
|> Map.put(to, to_stack)
end)
end)
# list is built in reverse
n_stacks..1
|> Enum.reduce([], fn k, acc ->
[hd(stacks[k]) | acc]
end)
|> Enum.join()
Part 2
%{false: stacks, true: ops} =
input
|> String.split("\n", trim: true)
|> Enum.filter(&(!String.starts_with?(&1, " 1")))
|> Enum.group_by(&String.starts_with?(&1, "move"))
stacks =
stacks
|> Enum.map(fn line ->
Regex.scan(~r/( |\[\w]) ?/, line, capture: :all_but_first)
|> Enum.map(fn
[" "] -> nil
[s] -> String.replace(s, ~r"[\[\]]", "")
end)
end)
# transpose
|> Enum.zip_with(& &1)
|> Enum.map(fn stack ->
stack
|> Enum.filter(& &1)
end)
# turn into a map
|> Enum.with_index()
|> Map.new(fn {v, k} -> {k + 1, v} end)
n_stacks = stacks |> Map.keys() |> Enum.count()
ops =
Enum.map(ops, fn line ->
Regex.run(~r/move (\d+) from (\d+) to (\d+)/, line)
|> tl()
|> Enum.map(&String.to_integer/1)
end)
stacks =
Enum.reduce(ops, stacks, fn [n, from, to], acc ->
crates = acc[from] |> Enum.take(n)
to_stack = crates ++ acc[to]
from_stack = acc[from] -- crates
acc
|> Map.put(from, from_stack)
|> Map.put(to, to_stack)
end)
# list is built in reverse
n_stacks..1
|> Enum.reduce([], fn k, acc ->
[hd(stacks[k]) | acc]
end)
|> Enum.join()