-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday10.cr
88 lines (77 loc) · 2.06 KB
/
day10.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
require "bit_array"
record(Pos, x : Int32, y : Int32) do
macro dir(name, x, y, includes)
def {{name}}?(map)
yield Pos.new({{x}},{{ y }}) if {{ includes }}.includes?(map[{{x}}][{{y}}])
end
end
dir(left, x, y - 1, {'-', 'F', 'L'})
dir(right, x, y + 1, {'-', 'J', '7'})
dir(up, x - 1, y, {'|', 'F', '7'})
dir(down, x + 1, y, {'|', 'J', 'L'})
def neighbours(map, &block)
case map[x][y]
when '|'
up?(map) { |p| yield p }
down?(map) { |p| yield p }
when '-'
right?(map) { |p| yield p }
left?(map) { |p| yield p }
when 'F'
right?(map) { |p| yield p }
down?(map) { |p| yield p }
when '7'
left?(map) { |p| yield p }
down?(map) { |p| yield p }
when 'J'
left?(map) { |p| yield p }
up?(map) { |p| yield p }
when 'L'
right?(map) { |p| yield p }
up?(map) { |p| yield p }
when 'S'
left?(map) { |p| yield p }
right?(map) { |p| yield p }
up?(map) { |p| yield p }
down?(map) { |p| yield p }
else raise "unreachable"
end
end
end
input = File.read("input.day10").lines
start = Pos.new(0, 0)
input.each_with_index do |line, i|
j = line.each_char.index('S')
start = Pos.new(i, j) if j
end
queue = Deque{ {start, 0} }
pipe_loop = Array(BitArray).new(input.size) { BitArray.new(input[0].size) }
furthest = 0
while node = queue.shift?
pos, steps = node
pipe_loop[pos.x][pos.y] = true
furthest = steps
pos.neighbours(input) do |n|
queue << {n, steps + 1} unless pipe_loop[n.x][n.y]
end
end
puts "part1: %s" % furthest
sum = input.size.times.sum do |i|
in_loop = false
bend = nil
input[0].size.times.sum do |j|
next in_loop ? 1 : 0 unless pipe_loop[i][j]
current = input[i][j]
# ugly input dependent hack
current = bend ? '7' : 'F' if current == 'S'
case current
when '-'
when 'F', 'L' then bend = current
when '7' then in_loop = !in_loop if bend == 'L'
when 'J' then in_loop = !in_loop if bend == 'F'
else in_loop = !in_loop
end
0
end
end
puts "part2: %s" % sum