Skip to content

Commit 92a8312

Browse files
committed
Day 6 part 2 Ruby solution
1 parent 6b6de86 commit 92a8312

File tree

1 file changed

+154
-0
lines changed

1 file changed

+154
-0
lines changed

06-2.rb

+154
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
#!/usr/bin/env ruby
2+
3+
require 'numo/narray'
4+
require 'parallel'
5+
6+
class Map
7+
attr_reader :height, :width, :map, :init_guard_x, :init_guard_y, :init_guard_dir
8+
9+
def initialize(input)
10+
@height = input.size
11+
@width = input[0].size
12+
@map = Numo::UInt8.zeros(@height, @width)
13+
@height.times do |y|
14+
@width.times do |x|
15+
case input[y][x]
16+
when '.'
17+
@map[y, x] = 0
18+
when '#'
19+
@map[y, x] = 1
20+
when '^'
21+
@map[y, x] = 2
22+
@init_guard_y = @guard_y = y
23+
@init_guard_x = @guard_x = x
24+
@init_guard_dir = @guard_dir = :north
25+
end
26+
end
27+
end
28+
end
29+
30+
def initialize_copy(other)
31+
@height = other.height
32+
@width = other.width
33+
@map = other.map.clone
34+
@init_guard_x = @guard_x = other.init_guard_x
35+
@init_guard_y = @guard_y = other.init_guard_y
36+
@init_guard_dir = @guard_dir = other.init_guard_dir
37+
end
38+
39+
def reset!
40+
@guard_y = @init_guard_y
41+
@guard_x = @init_guard_x
42+
@guard_dir = @init_guard_dir
43+
end
44+
45+
def add_obstacle(y, x)
46+
@map[y, x] = 1
47+
end
48+
49+
def walk!
50+
visited = []
51+
52+
res = :again
53+
while res == :again
54+
case @guard_dir
55+
when :north
56+
dy = -1
57+
dx = 0
58+
when :east
59+
dy = 0
60+
dx = 1
61+
when :south
62+
dy = 1
63+
dx = 0
64+
when :west
65+
dy = 0
66+
dx = -1
67+
end
68+
69+
next_x = @guard_x + dx
70+
next_y = @guard_y + dy
71+
72+
if visited.include? [@guard_y, @guard_x, @guard_dir]
73+
res = :loop
74+
break
75+
end
76+
77+
visited << [@guard_y, @guard_x, @guard_dir]
78+
79+
if next_x < 0 or next_x >= @width or
80+
next_y < 0 or next_y >= @height
81+
@guard_x = next_x
82+
@guard_y = next_y
83+
res = :leave
84+
elsif @map[next_y, next_x] == 1
85+
@guard_dir = case @guard_dir
86+
when :north
87+
:east
88+
when :east
89+
:south
90+
when :south
91+
:west
92+
when :west
93+
:north
94+
end
95+
res = :again
96+
else
97+
@map[next_y, next_x] = 2
98+
@guard_x = next_x
99+
@guard_y = next_y
100+
res = :again
101+
end
102+
end
103+
104+
if res == :loop
105+
1
106+
elsif res == :leave
107+
0
108+
end
109+
end
110+
111+
def route
112+
route = []
113+
@height.times do |y|
114+
@width.times do |x|
115+
route << [y, x] if @map[y, x] == 2
116+
end
117+
end
118+
route
119+
end
120+
121+
def inspect
122+
to_s
123+
end
124+
125+
def to_s
126+
s = "<#{self.class}:\n"
127+
s += "Guard: (#{@guard_y}, #{@guard_x}) #{@guard_dir}\n"
128+
@height.times do |y|
129+
@width.times do |x|
130+
s += case @map[y, x]
131+
when 0
132+
'.'
133+
when 1
134+
'#'
135+
when 2
136+
'X'
137+
end
138+
end
139+
s += "\n"
140+
end
141+
s += ">"
142+
s
143+
end
144+
end
145+
146+
map = Map.new File.read('06.input').lines.map(&:strip)
147+
map.walk!
148+
149+
puts(Parallel.map(map.route) do |candidate_obstacle|
150+
simulation = map.clone
151+
simulation.reset!
152+
simulation.add_obstacle(candidate_obstacle[0], candidate_obstacle[1])
153+
simulation.walk!
154+
end.sum)

0 commit comments

Comments
 (0)