-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday18.cr
64 lines (55 loc) · 1.39 KB
/
day18.cr
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
input = File.read("day18.input")
alias Pos = Tuple(Int32, Int32)
map = input.lines.map &.chars
maxx = map.size - 1
maxy = map[0].size - 1
def adjacent(pos, maxx, maxy)
{ {1, 0}, {0, 1}, {1, 1}, {-1, 0}, {0, -1}, {-1, -1}, {-1, 1}, {1, -1} }
.map { |o| {pos[0] + o[0], pos[1] + o[1]} }
.select { |(x, y)| x >= 0 && x <= maxx && y >= 0 && y <= maxy }
end
precalc_adj = (0..maxx).map do |x|
(0..maxy).map { |y| adjacent({x, y}, maxx, maxy) }
end
def gen(map, adj)
map.map_with_index do |l, x|
l.map_with_index do |c, y|
adjacent = adj[x][y]
trees = adjacent.count { |p| map[p[0]][p[1]] == '|' }
lumberyards = adjacent.count { |p| map[p[0]][p[1]] == '#' }
if c == '.' && trees >= 3
'|'
elsif c == '|' && lumberyards >= 3
'#'
elsif c == '#' && (trees.zero? || lumberyards.zero?)
'.'
else
c
end
end
end
end
maps = Array(typeof(map)).new
maps << map
seen = Hash(typeof(map), Int32).new
seen[map] = 0
loop_start = -1
loop_length = -1
(1..Int32::MAX).each do |i|
map = gen(map, precalc_adj)
if v = seen[map]?
loop_start = v
loop_length = i - v
break
else
seen[map] = i
maps << map
end
end
def count(map)
map.sum(&.count &.==('|')) *
map.sum(&.count &.==('#'))
end
map = maps[loop_start + ((1000000000 - loop_start) % loop_length)]
puts "part1: #{count maps[10]}"
puts "part2: #{count map}"