cem 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/examples/aoc2018/.gitignore +2 -0
- data/examples/aoc2018/day10.rb +61 -0
- data/examples/aoc2018/day11.rb +66 -0
- data/examples/aoc2018/day12.rb +61 -0
- data/examples/aoc2018/day13.rb +167 -0
- data/examples/aoc2018/day14.rb +31 -0
- data/examples/aoc2018/day14_2.rb +71 -0
- data/examples/aoc2018/day15.rb +271 -0
- data/examples/aoc2018/day16.rb +158 -0
- data/examples/aoc2018/day17.rb +203 -0
- data/examples/aoc2018/day18.rb +113 -0
- data/examples/aoc2018/day18_rspec.rb +131 -0
- data/examples/aoc2018/day19.rb +145 -0
- data/examples/aoc2018/day20.rb +103 -0
- data/examples/aoc2018/day21.rb +158 -0
- data/examples/aoc2018/day21_v2.rb +137 -0
- data/examples/aoc2018/day21_v3.rb +157 -0
- data/examples/aoc2018/day21_v4.rb +141 -0
- data/examples/aoc2018/day22.rb +212 -0
- data/examples/aoc2018/day23.rb +148 -0
- data/examples/aoc2018/day24.rb +156 -0
- data/examples/aoc2018/day25.rb +52 -0
- data/examples/aoc2018/day9.rb +51 -0
- data/examples/aoc2018/day9_circular.rb +125 -0
- data/examples/aoc2018/inputs/day10_input.txt +395 -0
- data/examples/aoc2018/inputs/day11_input.txt +1 -0
- data/examples/aoc2018/inputs/day12_input.txt +34 -0
- data/examples/aoc2018/inputs/day12_input2.txt +16 -0
- data/examples/aoc2018/inputs/day13_input.txt +150 -0
- data/examples/aoc2018/inputs/day13_test.txt +6 -0
- data/examples/aoc2018/inputs/day14_input.txt +1 -0
- data/examples/aoc2018/inputs/day15_input.txt +32 -0
- data/examples/aoc2018/inputs/day15_input10.txt +32 -0
- data/examples/aoc2018/inputs/day15_input11.txt +32 -0
- data/examples/aoc2018/inputs/day15_input12.txt +32 -0
- data/examples/aoc2018/inputs/day15_input13.txt +32 -0
- data/examples/aoc2018/inputs/day15_input14.txt +32 -0
- data/examples/aoc2018/inputs/day15_input2.txt +7 -0
- data/examples/aoc2018/inputs/day15_input3.txt +9 -0
- data/examples/aoc2018/inputs/day15_input4.txt +7 -0
- data/examples/aoc2018/inputs/day15_input5.txt +7 -0
- data/examples/aoc2018/inputs/day15_input6.txt +7 -0
- data/examples/aoc2018/inputs/day15_input7.txt +7 -0
- data/examples/aoc2018/inputs/day15_input8.txt +5 -0
- data/examples/aoc2018/inputs/day15_input9.txt +7 -0
- data/examples/aoc2018/inputs/day15_test.txt +9 -0
- data/examples/aoc2018/inputs/day16_input.txt +3865 -0
- data/examples/aoc2018/inputs/day17_input.txt +2229 -0
- data/examples/aoc2018/inputs/day17_input_test.txt +8 -0
- data/examples/aoc2018/inputs/day18_input.txt +50 -0
- data/examples/aoc2018/inputs/day18_test.txt +10 -0
- data/examples/aoc2018/inputs/day19_input.txt +48 -0
- data/examples/aoc2018/inputs/day20_input.txt +1 -0
- data/examples/aoc2018/inputs/day21_input.txt +32 -0
- data/examples/aoc2018/inputs/day22_input.txt +2 -0
- data/examples/aoc2018/inputs/day23_input.txt +1000 -0
- data/examples/aoc2018/inputs/day23_input2.txt +9 -0
- data/examples/aoc2018/inputs/day24_input.txt +24 -0
- data/examples/aoc2018/inputs/day25_input.txt +1483 -0
- data/examples/aoc2018/inputs/day9_input.txt +1 -0
- data/lib/cem.rb +0 -6
- data/lib/cem/ccommon.rb +45 -0
- data/lib/cem/cruzzles.rb +93 -38
- data/lib/cem/version.rb +1 -1
- metadata +62 -2
@@ -0,0 +1,113 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# https://adventofcode.com/2018/day/18 part 1 and 2
|
4
|
+
#
|
5
|
+
# Demonstrates Grid and Object#peql. For an rspec based variant see day18_rspec.rb
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'cem'
|
9
|
+
require 'set'
|
10
|
+
|
11
|
+
def run(inputFilename, part1, debug)
|
12
|
+
|
13
|
+
lines = []
|
14
|
+
File.readlines(inputFilename, chomp: true).each { |line|
|
15
|
+
lines << line.rstrip
|
16
|
+
}
|
17
|
+
|
18
|
+
maxY = lines.size
|
19
|
+
maxX = lines[0].length
|
20
|
+
|
21
|
+
@m = Grid.new(maxX, maxY, '.')
|
22
|
+
|
23
|
+
@map = []
|
24
|
+
lines.each_with_index { |l, y|
|
25
|
+
result = []
|
26
|
+
|
27
|
+
l.chars.each_with_index { |c, x|
|
28
|
+
result << c
|
29
|
+
@m[y,x] = c
|
30
|
+
}
|
31
|
+
@map << result
|
32
|
+
}
|
33
|
+
|
34
|
+
puts "Initial State" if debug
|
35
|
+
puts @m if debug
|
36
|
+
|
37
|
+
intermediates = Set.new
|
38
|
+
|
39
|
+
startIteration = nil
|
40
|
+
periodicity = nil
|
41
|
+
tickResultCache = nil
|
42
|
+
|
43
|
+
# Read board
|
44
|
+
(1..1000000000).each { |i|
|
45
|
+
|
46
|
+
@m2 = @m.clone
|
47
|
+
|
48
|
+
@map.each_with_index { |l, y|
|
49
|
+
|
50
|
+
l.each_with_index { |c, x|
|
51
|
+
|
52
|
+
# puts "Adja: #{x} #{y}"
|
53
|
+
ajda = @m.adja_index(x,y)
|
54
|
+
case @m[y,x]
|
55
|
+
when '.'
|
56
|
+
@m2[y,x] = ajda.select { |p| @m[p] == '|' }.size >= 3 ? '|' : '.'
|
57
|
+
when '|'
|
58
|
+
@m2[y,x] = ajda.select { |p| @m[p] == '#' }.size >= 3 ? '#' : '|'
|
59
|
+
when '#'
|
60
|
+
@m2[y,x] = ajda.select { |p| @m[p] == '#' }.size >= 1 && ajda.select { |p| @m[p] == '|' }.size >= 1 ? '#' : '.'
|
61
|
+
end
|
62
|
+
|
63
|
+
puts "#{y} #{x} was #{@m[y,x]} is now #{@m2[y,x]}: #{ajda.inspect}" if debug
|
64
|
+
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
@m = @m2
|
69
|
+
|
70
|
+
if part1 && i == 10
|
71
|
+
puts "Part 1: Score after #{i} tick is #{@m.count('#') * @m.count('|')}" # if debug
|
72
|
+
break
|
73
|
+
end
|
74
|
+
|
75
|
+
puts @m if debug if debug
|
76
|
+
gets if debug
|
77
|
+
|
78
|
+
if !part1
|
79
|
+
tickResult = @m.to_a
|
80
|
+
|
81
|
+
if periodicity == nil && tickResultCache == tickResult
|
82
|
+
periodicity = i - startIteration
|
83
|
+
# puts periodicity
|
84
|
+
elsif periodicity
|
85
|
+
if ((1000000000 - i) % periodicity) == 0
|
86
|
+
break
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
if startIteration == nil && intermediates.include?(tickResult)
|
91
|
+
startIteration = i
|
92
|
+
tickResultCache = tickResult
|
93
|
+
elsif startIteration == nil
|
94
|
+
intermediates.add(tickResult)
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
}
|
99
|
+
|
100
|
+
@m.count('#') * @m.count('|')
|
101
|
+
end
|
102
|
+
|
103
|
+
debug = false
|
104
|
+
|
105
|
+
{
|
106
|
+
"inputs/day18_test.txt" => [1147, 0],
|
107
|
+
"inputs/day18_input.txt" => [589931, 222332],
|
108
|
+
}.each_pair { |k,v|
|
109
|
+
|
110
|
+
peql(run(k, true, debug), v[0], "Testing #{k.inspect} part 1")
|
111
|
+
peql(run(k, false, debug), v[1], "Testing #{k.inspect} part 2")
|
112
|
+
|
113
|
+
}
|
@@ -0,0 +1,131 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# https://adventofcode.com/2018/day/18 part 1 and 2
|
4
|
+
#
|
5
|
+
# Demonstrates Grid and Object#peql. For a variant without rspec see day18.rb
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'cem'
|
9
|
+
require 'set'
|
10
|
+
|
11
|
+
def run(inputFilename, part1, debug)
|
12
|
+
|
13
|
+
lines = []
|
14
|
+
File.readlines(inputFilename, chomp: true).each { |line|
|
15
|
+
lines << line.rstrip
|
16
|
+
}
|
17
|
+
|
18
|
+
maxY = lines.size
|
19
|
+
maxX = lines[0].length
|
20
|
+
|
21
|
+
@m = Grid.new(maxX, maxY, '.')
|
22
|
+
|
23
|
+
@map = []
|
24
|
+
lines.each_with_index { |l, y|
|
25
|
+
result = []
|
26
|
+
|
27
|
+
l.chars.each_with_index { |c, x|
|
28
|
+
result << c
|
29
|
+
@m[y,x] = c
|
30
|
+
}
|
31
|
+
@map << result
|
32
|
+
}
|
33
|
+
|
34
|
+
puts "Initial State" if debug
|
35
|
+
puts @m if debug
|
36
|
+
|
37
|
+
intermediates = Set.new
|
38
|
+
|
39
|
+
startIteration = nil
|
40
|
+
periodicity = nil
|
41
|
+
tickResultCache = nil
|
42
|
+
|
43
|
+
# Read board
|
44
|
+
(1..1000000000).each { |i|
|
45
|
+
|
46
|
+
@m2 = @m.clone
|
47
|
+
|
48
|
+
@map.each_with_index { |l, y|
|
49
|
+
|
50
|
+
l.each_with_index { |c, x|
|
51
|
+
|
52
|
+
# puts "Adja: #{x} #{y}"
|
53
|
+
ajda = @m.adja_index(x,y)
|
54
|
+
case @m[y,x]
|
55
|
+
when '.'
|
56
|
+
@m2[y,x] = ajda.select { |p| @m[p] == '|' }.size >= 3 ? '|' : '.'
|
57
|
+
when '|'
|
58
|
+
@m2[y,x] = ajda.select { |p| @m[p] == '#' }.size >= 3 ? '#' : '|'
|
59
|
+
when '#'
|
60
|
+
@m2[y,x] = ajda.select { |p| @m[p] == '#' }.size >= 1 && ajda.select { |p| @m[p] == '|' }.size >= 1 ? '#' : '.'
|
61
|
+
end
|
62
|
+
|
63
|
+
puts "#{y} #{x} was #{@m[y,x]} is now #{@m2[y,x]}: #{ajda.inspect}" if debug
|
64
|
+
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
@m = @m2
|
69
|
+
|
70
|
+
if part1 && i == 10
|
71
|
+
puts "Part 1: Score after #{i} tick is #{@m.count('#') * @m.count('|')}" # if debug
|
72
|
+
break
|
73
|
+
end
|
74
|
+
|
75
|
+
puts @m if debug if debug
|
76
|
+
gets if debug
|
77
|
+
|
78
|
+
if !part1
|
79
|
+
tickResult = @m.to_a
|
80
|
+
|
81
|
+
if periodicity == nil && tickResultCache == tickResult
|
82
|
+
periodicity = i - startIteration
|
83
|
+
# puts periodicity
|
84
|
+
elsif periodicity
|
85
|
+
if ((1000000000 - i) % periodicity) == 0
|
86
|
+
break
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
if startIteration == nil && intermediates.include?(tickResult)
|
91
|
+
startIteration = i
|
92
|
+
tickResultCache = tickResult
|
93
|
+
elsif startIteration == nil
|
94
|
+
intermediates.add(tickResult)
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
}
|
99
|
+
|
100
|
+
@m.count('#') * @m.count('|')
|
101
|
+
end
|
102
|
+
|
103
|
+
debug = false
|
104
|
+
|
105
|
+
require 'rspec'
|
106
|
+
|
107
|
+
RSpec.configure do |config|
|
108
|
+
config.color = true # Use color in STDOUT
|
109
|
+
config.tty = true # Use color not only in STDOUT but also in pagers and files
|
110
|
+
config.formatter = :documentation
|
111
|
+
end
|
112
|
+
|
113
|
+
describe $__FILE__ do
|
114
|
+
|
115
|
+
{
|
116
|
+
"inputs/day18_test.txt" => [1147, 1],
|
117
|
+
"inputs/day18_input.txt" => [589931, 222332],
|
118
|
+
}.each_pair { |k,v|
|
119
|
+
|
120
|
+
it "testing #{k.inspect} part 1" do
|
121
|
+
expect(run(k, true, debug)).to eq(v[0])
|
122
|
+
end
|
123
|
+
|
124
|
+
it "testing #{k.inspect} part 2" do
|
125
|
+
expect(run(k, false, debug)).to eq(v[1])
|
126
|
+
end
|
127
|
+
}
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
RSpec::Core::Runner.run([$__FILE__])
|
@@ -0,0 +1,145 @@
|
|
1
|
+
#
|
2
|
+
# https://adventofcode.com/2018/day/19 part 1 and 2
|
3
|
+
#
|
4
|
+
|
5
|
+
# My code was too slow to handle this problem, so this is really more analytical from observing the state of the machine and figuring out what it does.
|
6
|
+
|
7
|
+
shortcut = true
|
8
|
+
if shortcut
|
9
|
+
|
10
|
+
result = 0
|
11
|
+
(1..930).each { |i|
|
12
|
+
result += i if 930 % i == 0
|
13
|
+
}
|
14
|
+
puts "Part 1: #{result}"
|
15
|
+
|
16
|
+
result = 0
|
17
|
+
(1..10551330).each { |i|
|
18
|
+
result += i if 10551330 % i == 0
|
19
|
+
}
|
20
|
+
puts "Part 2: #{result}"
|
21
|
+
exit
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
[1,2].each { |part|
|
26
|
+
|
27
|
+
lines = File.readlines("inputs/day19_input.txt", chomp: true)
|
28
|
+
|
29
|
+
commandQueue = []
|
30
|
+
|
31
|
+
reg = [part - 1, 0, 0, 0, 0, 0]
|
32
|
+
|
33
|
+
ip = nil
|
34
|
+
lines.each { |line|
|
35
|
+
|
36
|
+
if line =~ /^#ip ([+-]?\d+)$/
|
37
|
+
ip = $1.to_i
|
38
|
+
end
|
39
|
+
|
40
|
+
if line =~ /^(\w+) ([+-]?\d+) ([+-]?\d+) ([+-]?\d+)$/
|
41
|
+
verb = $1
|
42
|
+
v1 = $2.to_i
|
43
|
+
v2 = $3.to_i
|
44
|
+
v3 = $4.to_i
|
45
|
+
|
46
|
+
commandQueue << [verb, v1, v2, v3]
|
47
|
+
end
|
48
|
+
}
|
49
|
+
|
50
|
+
if false
|
51
|
+
puts "Command queue:"
|
52
|
+
commandQueue.each { |x|
|
53
|
+
puts " " + x.inspect
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
ipp = 0
|
58
|
+
i = 0
|
59
|
+
reset = true
|
60
|
+
|
61
|
+
while ipp >= 0 && ipp < commandQueue.size
|
62
|
+
|
63
|
+
reg[ip] = ipp
|
64
|
+
command = commandQueue[ipp]
|
65
|
+
|
66
|
+
puts command.inspect + " " + reg.inspect if i % (256*1024) == 0
|
67
|
+
i += 1
|
68
|
+
|
69
|
+
case command[0]
|
70
|
+
|
71
|
+
when "addr"
|
72
|
+
# addr (add register) stores into register C the result of adding register A and register B.
|
73
|
+
reg[command[3]] = reg[command[1]] + reg[command[2]]
|
74
|
+
|
75
|
+
when "addi"
|
76
|
+
# addi (add immediate) stores into register C the result of adding register A and value B.
|
77
|
+
reg[command[3]] = reg[command[1]] + command[2]
|
78
|
+
|
79
|
+
when "mulr"
|
80
|
+
# mulr (multiply register) stores into register C the result of multiplying register A and register B.
|
81
|
+
reg[command[3]] = reg[command[1]] * reg[command[2]]
|
82
|
+
|
83
|
+
when "muli"
|
84
|
+
# muli (multiply immediate) stores into register C the result of multiplying register A and value B.
|
85
|
+
reg[command[3]] = reg[command[1]] * command[2]
|
86
|
+
|
87
|
+
when "banr"
|
88
|
+
# banr (bitwise AND register) stores into register C the result of the bitwise AND of register A and register B.
|
89
|
+
reg[command[3]] = reg[command[1]] & reg[command[2]]
|
90
|
+
|
91
|
+
when "bani"
|
92
|
+
# bani (bitwise AND immediate) stores into register C the result of the bitwise AND of register A and value B.
|
93
|
+
reg[command[3]] = reg[command[1]] & command[2]
|
94
|
+
|
95
|
+
when "borr"
|
96
|
+
# borr (bitwise OR register) stores into register C the result of the bitwise OR of register A and register B.
|
97
|
+
reg[command[3]] = reg[command[1]] | reg[command[2]]
|
98
|
+
|
99
|
+
when "bori"
|
100
|
+
# bori (bitwise OR immediate) stores into register C the result of the bitwise OR of register A and value B.
|
101
|
+
reg[command[3]] = reg[command[1]] | command[2]
|
102
|
+
|
103
|
+
when "setr"
|
104
|
+
# setr (set register) copies the contents of register A into register C. (Input B is ignored.)
|
105
|
+
reg[command[3]] = reg[command[1]]
|
106
|
+
|
107
|
+
when "seti"
|
108
|
+
# seti (set immediate) stores value A into register C. (Input B is ignored.)
|
109
|
+
reg[command[3]] = command[1]
|
110
|
+
|
111
|
+
when "gtir"
|
112
|
+
# gtir (greater-than immediate/register) sets register C to 1 if value A is greater than register B. Otherwise, register C is set to 0.
|
113
|
+
reg[command[3]] = command[1] > reg[command[2]] ? 1 : 0
|
114
|
+
|
115
|
+
when "gtri"
|
116
|
+
# gtri (greater-than register/immediate) sets register C to 1 if register A is greater than value B. Otherwise, register C is set to 0.
|
117
|
+
reg[command[3]] = reg[command[1]] > command[2] ? 1 : 0
|
118
|
+
|
119
|
+
when "gtrr"
|
120
|
+
# gtrr (greater-than register/register) sets register C to 1 if register A is greater than register B. Otherwise, register C is set to 0.
|
121
|
+
reg[command[3]] = reg[command[1]] > reg[command[2]] ? 1 : 0
|
122
|
+
|
123
|
+
when "eqir"
|
124
|
+
# eqir (equal immediate/register) sets register C to 1 if value A is equal to register B. Otherwise, register C is set to 0.
|
125
|
+
reg[command[3]] = command[1] == reg[command[2]] ? 1 : 0
|
126
|
+
|
127
|
+
when "eqri"
|
128
|
+
# eqri (equal register/immediate) sets register C to 1 if register A is equal to value B. Otherwise, register C is set to 0.
|
129
|
+
reg[command[3]] = reg[command[1]] == command[2] ? 1 : 0
|
130
|
+
|
131
|
+
when "eqrr"
|
132
|
+
# eqrr (equal register/register) sets register C to 1 if register A is equal to register B. Otherwise, register C is set to 0.
|
133
|
+
reg[command[3]] = reg[command[1]] == reg[command[2]] ? 1 : 0
|
134
|
+
|
135
|
+
else
|
136
|
+
raise "Error"
|
137
|
+
end
|
138
|
+
|
139
|
+
ipp = reg[ip]
|
140
|
+
ipp += 1
|
141
|
+
end
|
142
|
+
|
143
|
+
puts reg.inspect
|
144
|
+
puts "Part#{part}: #{reg[0]}"
|
145
|
+
}
|
@@ -0,0 +1,103 @@
|
|
1
|
+
#
|
2
|
+
# https://adventofcode.com/2018/day/20 part 1 and 2
|
3
|
+
#
|
4
|
+
# Took 1:10 min for both parts (not bad!)
|
5
|
+
#
|
6
|
+
# Could have been faster, but ruzzles parts had to be created for this:
|
7
|
+
#
|
8
|
+
# - Grid.minmax
|
9
|
+
# - Point2D.from_s
|
10
|
+
# - Point2D.to_dir_bitmask / from_dir_bitmask
|
11
|
+
# - Dirs2D
|
12
|
+
#
|
13
|
+
|
14
|
+
require 'cem'
|
15
|
+
|
16
|
+
line = File.read("inputs/day20_input.txt")
|
17
|
+
|
18
|
+
stack = [[Point2D.new(500,500)]]
|
19
|
+
|
20
|
+
grid = Grid.new(1000, 1000, 0)
|
21
|
+
|
22
|
+
line.chars.each { |c|
|
23
|
+
case c
|
24
|
+
|
25
|
+
when '$'
|
26
|
+
# ignore
|
27
|
+
when '^'
|
28
|
+
# ignore
|
29
|
+
when "\n"
|
30
|
+
# ignore
|
31
|
+
|
32
|
+
when '('
|
33
|
+
newCurCursor = stack.last.map { |p| p.dup }
|
34
|
+
stack << [] # One below top() are all cursors we collected as part of this opening brace group
|
35
|
+
stack << newCurCursor # Stack.top() is all current cursor position we are tracking
|
36
|
+
|
37
|
+
when ')'
|
38
|
+
lastGroup = stack.pop
|
39
|
+
otherGroupsInBrace = stack.pop
|
40
|
+
replacedGroup = stack.pop
|
41
|
+
stack << (lastGroup + otherGroupsInBrace).uniq
|
42
|
+
|
43
|
+
when 'E', 'N', 'S', 'W'
|
44
|
+
dir = Point2D.from_s(c)
|
45
|
+
|
46
|
+
stack.last.map! { |p|
|
47
|
+
grid[p] |= dir.to_dir_bitmask
|
48
|
+
p += dir
|
49
|
+
grid[p] |= dir.flip.to_dir_bitmask
|
50
|
+
p
|
51
|
+
}
|
52
|
+
when '|'
|
53
|
+
lastGroup = stack.pop
|
54
|
+
stack.last.concat lastGroup
|
55
|
+
stack << stack[-2].map { |p| p.dup }
|
56
|
+
|
57
|
+
else
|
58
|
+
raise "Unknown char '#{c.inspect}'"
|
59
|
+
end
|
60
|
+
}
|
61
|
+
|
62
|
+
if false # Print Grid for debugging
|
63
|
+
|
64
|
+
min, max = grid.minmax(0)
|
65
|
+
count = 0
|
66
|
+
|
67
|
+
(min.y..max.y).each {|y|
|
68
|
+
a = ""
|
69
|
+
b = ""
|
70
|
+
(min.x..max.x).each { |x|
|
71
|
+
count += 1 if grid[y,x] > 0
|
72
|
+
a += "#" + (grid[y,x] & 1 == 1 ? "|" : "#")
|
73
|
+
b += (grid[y,x] & 8 == 8 ? "-" : "#") + (grid[y,x] > 0 ? "." : "#")
|
74
|
+
}
|
75
|
+
puts a + "#"
|
76
|
+
puts b + "#"
|
77
|
+
}
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
# Run BFS search
|
82
|
+
q = [[Point2D.new(500,500), 0]]
|
83
|
+
|
84
|
+
maxSteps = 0
|
85
|
+
rooms = 0
|
86
|
+
while q.size > 0
|
87
|
+
p, maxSteps = q.shift
|
88
|
+
|
89
|
+
if maxSteps >= 1000
|
90
|
+
rooms += 1
|
91
|
+
end
|
92
|
+
|
93
|
+
Point2D.from_dir_bitmask(grid[p]).each { |dir|
|
94
|
+
grid[p+dir] &= ~dir.flip.to_dir_bitmask # Close door we walked through. Due to BFS, we never have to get to it again
|
95
|
+
|
96
|
+
q << [p+dir, maxSteps+1]
|
97
|
+
}
|
98
|
+
grid[p] = 0
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
puts "Part 1: #{maxSteps}"
|
103
|
+
puts "Part 2: #{rooms}"
|