-
Notifications
You must be signed in to change notification settings - Fork 0
/
day07.ex
84 lines (76 loc) · 2.28 KB
/
day07.ex
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
defmodule Day07 do
defp ls([row | tail], size) do
unless String.starts_with?(row, "$") do
[head | _] = String.split(row, " ", trim: true)
case head do
"dir" -> ls(tail, size)
_ ->
size = size + String.to_integer(head)
ls(tail, size)
end
else
size
end
end
defp ls([], size) do
size
end
defp exec([_ | tail], cur, dirs) when cur == nil do
cur = %{path: "/", parent: nil, size: 0}
dirs = Map.put(dirs, "/", cur)
exec(tail, cur, dirs)
end
defp exec([row | tail], cur, dirs) do
parts = String.split(row, " ", trim: true)
len = length(parts)
case len do
3 ->
[target | _] = Enum.slice(parts, -1..-1)
case target do
".." ->
next = dirs[cur[:parent]]
next = Map.update!(next, :size, fn x -> x + cur[:size] end)
dirs = Map.put(dirs, next[:path], next)
exec(tail, next, dirs)
_ ->
path = cur[:path]<>target<>"/"
next = %{path: path, parent: cur[:path], size: 0}
dirs = Map.put(dirs, path, next)
exec(tail, next, dirs)
end
_ ->
if row == "$ ls" do
size = ls(tail, 0)
cur = Map.update!(cur, :size, fn x -> x + size end)
dirs = Map.put(dirs, cur[:path], cur)
exec(tail, cur, dirs)
else
exec(tail, cur, dirs)
end
end
end
defp exec([], cur, dirs) do
parent = dirs[cur[:parent]]
if parent == nil do
dirs
else
parent = Map.update!(parent, :size, fn x -> x + cur[:size] end)
dirs = Map.put(dirs, parent[:path], parent)
exec([], parent, dirs)
end
end
def part_one(input) do
String.split(input, "\n", trim: true) |> exec(nil, %{}) |> Map.values |> Enum.map(fn x -> x[:size] end) |> Enum.filter(fn x -> x <= 100000 end) |> Enum.sum
end
def part_two(input) do
dirs = String.split(input, "\n", trim: true) |> exec(nil, %{})
space = 70000000 - dirs["/"][:size]
diff = 30000000 - space
Map.values(dirs) |> Enum.map(fn x -> x[:size] end) |> Enum.filter(fn x -> x >= diff end) |> Enum.sort(:asc) |> hd
end
def run do
{:ok, input} = File.read("lib/day07/input")
IO.puts(part_one(input))
IO.puts(part_two(input))
end
end