/
05.exs
105 lines (98 loc) · 2.57 KB
/
05.exs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
defmodule Day05 do
defp read_input do
File.read!(Path.expand("../inputs/input05_instructions.txt"))
|> String.split("\n")
|> Enum.map(fn line ->
Regex.scan(~r/move (\d+) from (\d) to (\d)/, line)
|> List.first
|> tl
|> Enum.map(&String.to_integer/1)
end)
end
# Input hand-copied from input05_crates.txt
defp initial_stacks do
%{
1 => "NCRTMZP",
2 => "DNTSBZ",
3 => "MHQRFCTG",
4 => "GRZ",
5 => "ZNRH",
6 => "FHSWPZLD",
7 => "WDZRCGM",
8 => "SJFLHWZQ",
9 => "SQPWN"
}
end
# Move multiple crates from stack to stack by single operations
# Recursive
# Return new stacks
defp execute_instruction_1by1(stacks, 1, from, to) do
execute_move(stacks, from, to)
end
defp execute_instruction_1by1(stacks, amount, from, to) when amount > 1 do
stacks2 = execute_move(stacks, from, to)
execute_instruction_1by1(stacks2, amount - 1, from, to)
end
# Move single crate from stack to stack
# Return new stacks
defp execute_move(stacks, from, to) do
crate = String.last(stacks[from])
# Update both values in the stacks map and return it
Map.update!(
Map.update!(
stacks,
to,
&(&1 <> crate)
),
from,
&(String.slice(&1, 0..-2))
)
end
# Move multiple crates from stack to stack in one shot
# Return new stacks
defp execute_instruction_grouped(stacks, amount, from, to) do
crates = String.slice(stacks[from], -amount, amount)
# Update both values in the stacks map and return it
Map.update!(
Map.update!(
stacks,
to,
&(&1 <> crates)
),
from,
&(String.slice(&1, 0..-(amount + 1)))
)
end
@doc """
Find the top crate of each stack after running the instructions
Crates move 1 by 1
"""
def part1 do
read_input()
|> Enum.reduce(
initial_stacks(),
fn [amount, from, to], stacks -> execute_instruction_1by1(stacks, amount, from, to) end
)
|> Map.values
|> Enum.map(&String.last/1)
|> Enum.join("")
|> IO.inspect(label: "P1")
end
@doc """
Find the top crate of each stack after running the instructions
Crates move together, a whole instruction at a time
"""
def part2 do
read_input()
|> Enum.reduce(
initial_stacks(),
fn [amount, from, to], stacks -> execute_instruction_grouped(stacks, amount, from, to) end
)
|> Map.values
|> Enum.map(&String.last/1)
|> Enum.join("")
|> IO.inspect(label: "P2")
end
end
# P1: RTGWZTHLD
# P2: STHGRZZFR