Finished day 5

This commit is contained in:
Erwin Boskma 2022-12-12 20:11:40 +01:00
parent a426ff5a7c
commit c2fa707d2b
Signed by: erwin
SSH key fingerprint: SHA256:CyeNoWXd3kjX2Nwu6pDxxdS7OqmPVOy0NavA/KU/ntU

235
day5.livemd Normal file
View file

@ -0,0 +1,235 @@
# AOC 2022 - Day 5
```elixir
Mix.install([
{:req, "~> 0.3.3"},
{:nimble_parsec, "~> 1.2.3"}
])
```
## Puzzle description
[Day 5: Supply Stacks](https://adventofcode.com/2022/day/5).
## Input
```elixir
defmodule Load do
def input do
aoc_session = System.fetch_env!("LB_AOC_SESSION")
input_url = "https://adventofcode.com/2022/day/5/input"
Req.get!(input_url, headers: [cookie: "session=#{aoc_session}"]).body
end
end
```
## Solution
```elixir
defmodule Parser do
import NimbleParsec
crate =
ignore(string("["))
|> utf8_char([?A..?Z])
|> ignore(string("]"))
empty_slot = string(" ") |> replace(:empty)
slot = choice([crate, empty_slot])
row =
repeat_while(
concat(
slot,
optional(ignore(string(" ")))
),
:not_newline
)
|> ignore(string("\n"))
|> tag(:row)
rows =
repeat_while(row, :not_index_row)
|> tag(:rows)
indices =
repeat_while(
ignore(string(" "))
|> integer(min: 1)
|> ignore(string(" "))
|> optional(ignore(string(" "))),
:not_newline
)
|> ignore(string("\n"))
|> tag(:indices)
instruction =
ignore(string("move "))
|> unwrap_and_tag(integer(min: 1), :amount)
|> ignore(string(" from "))
|> unwrap_and_tag(integer(min: 1), :from)
|> ignore(string(" to "))
|> unwrap_and_tag(integer(min: 1), :to)
|> ignore(optional(string("\n")))
|> tag(:instruction)
instructions = instruction |> repeat() |> tag(:instructions) |> eos()
defparsec(
:crates,
rows
|> concat(indices)
|> concat(ignore(string("\n")))
|> concat(instructions)
)
defp not_newline(<<?\n, _::binary>>, context, _, _), do: {:halt, context}
defp not_newline(_, context, _, _), do: {:cont, context}
defp not_index_row(<<" 1", _::binary>>, context, _, _), do: {:halt, context}
defp not_index_row(_, context, _, _), do: {:cont, context}
end
# Parser.rows(~s([S] [C]
# [P] [M] [Z]
# 1 2 3)) |> IO.inspect()
# Parser.slot(" ") |> IO.inspect()
# Parser.slot("brt") |> IO.inspect()
```
```elixir
```
```elixir
defmodule Part1 do
def run(input) do
{:ok, data, _, _, _, _} =
input
|> Parser.crates()
stacks =
data
|> Keyword.get(:rows)
|> Keyword.values()
|> List.zip()
|> Enum.map(&Tuple.to_list/1)
|> Enum.map(
&Enum.reject(&1, fn
:empty -> true
_ -> false
end)
)
instructions =
data
|> Keyword.get(:instructions)
|> Keyword.values()
instructions
|> Enum.reduce(stacks, fn [amount: amount, from: from, to: to], acc ->
from = from - 1
to = to - 1
{transfer, from_stack} =
Enum.at(acc, from)
|> Enum.split(amount)
to_stack =
transfer
|> Enum.reverse()
|> Enum.concat(Enum.at(acc, to))
List.replace_at(acc, from, from_stack)
|> List.replace_at(to, to_stack)
end)
|> Enum.map(&Enum.take(&1, 1))
|> Enum.join()
end
end
defmodule Part2 do
def run(input) do
{:ok, data, _, _, _, _} =
input
|> Parser.crates()
stacks =
data
|> Keyword.get(:rows)
|> Keyword.values()
|> List.zip()
|> Enum.map(&Tuple.to_list/1)
|> Enum.map(
&Enum.reject(&1, fn
:empty -> true
_ -> false
end)
)
instructions =
data
|> Keyword.get(:instructions)
|> Keyword.values()
instructions
|> Enum.reduce(stacks, fn [amount: amount, from: from, to: to], acc ->
from = from - 1
to = to - 1
{transfer, from_stack} =
Enum.at(acc, from)
|> Enum.split(amount)
to_stack =
transfer
|> Enum.concat(Enum.at(acc, to))
List.replace_at(acc, from, from_stack)
|> List.replace_at(to, to_stack)
end)
|> Enum.map(&Enum.take(&1, 1))
|> Enum.join()
end
end
ExUnit.start(autorun: false)
defmodule Test do
use ExUnit.Case, async: true
@example_input ~s( [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)
@input Load.input()
test "it loads the input" do
assert String.length(@input) > 0
end
test "part 1 example" do
assert Part1.run(@example_input) === "CMZ"
end
test "part 1" do
assert Part1.run(@input) === "GFTNRBZPF"
end
test "part 2 example" do
assert Part2.run(@example_input) === "MCD"
end
test "part 2" do
assert Part2.run(@input) === "VRQWPDSGP"
end
end
ExUnit.run()
```