-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday_06.ex
69 lines (59 loc) · 1.43 KB
/
day_06.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
defmodule Day06 do
@input File.read!("input/day_06.txt")
def run do
@input
|> parse
|> balance(seen: Map.new)
|> IO.inspect
end
def parse(input) do
input
|> String.trim
|> String.split("\t")
|> Enum.map(&String.to_integer/1)
# [0, 2, 7, 0]
|> Enum.with_index
|> Enum.into(Map.new, fn({number, index}) ->
{index, number}
end)
end
def balance(banks, seen: seen) do
cycles = map_size(seen)
if seen?(seen, banks) do
seen_first_at = Map.fetch!(seen, banks)
cycles - seen_first_at
else
new_seen = seen!(seen, banks, cycles)
new_banks = redistribute(banks)
balance(new_banks, seen: new_seen)
end
end
def redistribute(banks) do
{index, num_blocks} = bank_with_most_blocks(banks)
banks = clear_bank(banks, index)
Enum.reduce(1..num_blocks, banks, fn(offset, memory) ->
inc_bank(memory, index + offset)
end)
end
def bank_with_most_blocks(banks) do
Enum.max_by(banks, fn({i, num}) -> {num, -i} end)
end
def inc_bank(banks, at) do
index = Integer.mod(at, map_size(banks))
{_, new_banks} =
Map.get_and_update(banks, index, fn(value) ->
{value, value + 1}
end)
new_banks
end
def clear_bank(banks, index) do
Map.put(banks, index, 0)
end
def seen?(seen, banks) do
Map.has_key?(seen, banks)
end
def seen!(seen, banks, at) do
Map.put(seen, banks, at)
end
end
Day06.run