-
Notifications
You must be signed in to change notification settings - Fork 1
/
day-11-part2.rb
157 lines (119 loc) · 2.4 KB
/
day-11-part2.rb
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
require 'benchmark'
path = File.join(__dir__, 'input.txt')
input = *File.readlines(path).map {_1.chomp!}.map{ |row| row.split("").map{_1.to_i}}
class Octopus
attr_reader :x, :y, :energy
# collect all variations but remove duplicates, these are all of our neighbor locations
NEIGHBORS = [-1, 0, 1].repeated_permutation(2).to_a - [[0, 0]]
def initialize(x:, y:, energy:)
@x, @y = x, y
@energy = energy
@flash = false
end
def location
[x,y]
end
def neighbors
NEIGHBORS.map {[@x + _1[0], @y + _1[1]]}
end
def increase
@energy += 1
end
def can_flash?
@energy > 9 && !@flash
end
def just_flashed?
@energy == 0
end
def power_up!
@energy += 1
end
def on!
@flash = true
end
def on?
@flash
end
def off?
@energy.zero?
end
def off!
@flash = false
@energy = 0
end
end
class Cave
def initialize (levels)
@folks = {}
levels.each.with_index do |line, y|
line.each.with_index do |val, x|
@folks[[x, y]] = Octopus.new(x: x, y: y, energy: val)
end
end
end
def everyone
@folks.values
end
def [](location)
@folks[location]
end
def get_neighbors(octopus)
octopus.neighbors.map { self[_1] }.compact
end
def step
everyone.map(&:increase)
while can_flash?
everyone.filter(&:can_flash?).each do |octopus|
octopus.on!
get_neighbors(octopus).map(&:power_up!)
end
end
turn_off
end
def process(count)
count.times.collect do |index|
step
who_flashed?
end.inject(0) {|memo, list| memo + list.size}
end
def run
counter = 0
until everyone.all?(&:off?)
counter += 1
step
end
puts "everyone is on at #{counter}"
end
def turn_off
everyone.filter(&:on?).each do |octopus|
octopus.off!
end
end
def anyone_flashed?
everyone.any(&:just_flashed?)
end
def who_flashed?
everyone.filter(&:just_flashed?)
end
def can_flash?
everyone.any?(&:can_flash?)
end
def print
result = []
@folks.each do |k, v|
result[k[1]] = [] if result[k[1]].nil?
result[k[1]][k[0]] = [] if result[k[1]][k[0]].nil?
result[k[1]][k[0]] = v.energy
end
result.each { puts _1.join("")}
end
end
# part 1
cave = Cave.new(input)
result = cave.process(100)
puts "flashes #{result}"
# part 2
cave = Cave.new(input)
puts Benchmark.measure {
cave.run
}