-
Notifications
You must be signed in to change notification settings - Fork 0
/
day14.jl
100 lines (83 loc) · 2.26 KB
/
day14.jl
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
const Platform = Matrix{Char}
const Vec2 = Tuple{Int64, Int64}
function read_platform(filename::AbstractString)
open(filename) do file
lines = collect.(collect(eachline(file)))
permutedims(hcat(lines...))
end
end
function Base.getindex(m::Platform, p::Vec2)
(x,y) = p
m[y, x]
end
function Base.setindex!(m::Platform, value::Char, p::Vec2)
(x,y) = p
m[y, x] = value
end
function in_bounds(pl::Platform, p::Vec2)
(x,y) = p
checkbounds(Bool, pl, y, x)
end
function tilt!(platform::Platform, v::Vec2)
(height, width) = size(platform)
(dx, dy) = v
xs = (dx < 0) ? (2:width) : (dx > 0) ? (width - 1:-1:1) : (1:width)
ys = (dy < 0) ? (2:height) : (dy > 0) ? (height - 1:-1:1) : (1:height)
for y in ys
for x in xs
p = (x, y)
if platform[p] == 'O'
pp = p .+ v
while in_bounds(platform, pp) && platform[pp] == '.'
pp = pp .+ v
end
platform[p] = '.'
platform[pp .- v] = 'O'
end
end
end
end
function cycle(platform::Platform)
copy = deepcopy(platform)
tilt!.((copy,), [(0, -1), (-1, 0), (0, 1), (1, 0)])
copy
end
function load(platform::Platform)
sum = 0
(height, _) = size(platform)
for (index, row) in enumerate(eachrow(platform))
c = count(x -> x == 'O', row)
multiplier = height - (index - 1)
sum += c * multiplier
end
sum
end
function part1(platform::Platform)
tilt!(platform, [0, -1])
load(platform)
end
function part2(platform::Platform)
seen_indices = Dict()
seen = []
current = platform
i = 0
while true
prefix = get(seen_indices, current, -1)
if prefix != -1
period = i - prefix
index = ((1_000_000_000 - prefix) % period) + prefix
return load(seen[index + 1])
else
push!(seen, current)
seen_indices[current] = i
end
current = cycle(current)
i += 1
end
end
test_data = read_platform("Day14_test.txt")
real_data = read_platform("Day14.txt")
@assert part1(test_data) == 136
@assert part2(test_data) == 64
println("part1 ", part1(real_data))
println("part2 ", part2(real_data))