|
|
|
@ -12,51 +12,41 @@ cave = scan.each.with_object({}) {|line, cave|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
x_min, x_max = cave.keys.map(&:first).minmax
|
|
|
|
|
y_min, y_max = cave.keys.map(&:last).minmax
|
|
|
|
|
def cave.to_s
|
|
|
|
|
x_min, x_max = keys.map(&:first).minmax
|
|
|
|
|
y_min, y_max = keys.map(&:last).minmax
|
|
|
|
|
|
|
|
|
|
inspect_cave = -> {
|
|
|
|
|
puts (0..y_max+1).map {|y|
|
|
|
|
|
(0..y_max+1).map {|y|
|
|
|
|
|
(x_min-1..x_max+1).map {|x|
|
|
|
|
|
cave[[x, y]] || ?.
|
|
|
|
|
self.fetch([x, y], ?.)
|
|
|
|
|
}.join
|
|
|
|
|
}.join("\n")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# part one
|
|
|
|
|
# sands = 0
|
|
|
|
|
# loop do
|
|
|
|
|
# inspect_cave.()
|
|
|
|
|
# sands += 1
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# pos = [500, 0]
|
|
|
|
|
# while next_pos = [0, -1, 1].map {|dx| pos.zip([dx, 1]).map { _1 + _2 }}.find { cave[_1].nil? }
|
|
|
|
|
# pos = next_pos
|
|
|
|
|
# break if pos[1] >= y_max
|
|
|
|
|
# end
|
|
|
|
|
# break if pos[1] >= y_max
|
|
|
|
|
def pour_sand(cave, stop:)
|
|
|
|
|
return enum_for(__method__, cave, stop:) unless block_given?
|
|
|
|
|
|
|
|
|
|
# cave[pos] = ?o
|
|
|
|
|
# end
|
|
|
|
|
loop do
|
|
|
|
|
# puts cave
|
|
|
|
|
pos = [500, 0]
|
|
|
|
|
|
|
|
|
|
# inspect_cave.()
|
|
|
|
|
# p sands-1
|
|
|
|
|
while next_pos = [0, -1, 1].map {|dx| pos.zip([dx, 1]).map { _1 + _2 }}.find { cave[_1].nil? }
|
|
|
|
|
pos = next_pos
|
|
|
|
|
break if stop.(*pos)
|
|
|
|
|
end
|
|
|
|
|
break if stop.(*pos)
|
|
|
|
|
|
|
|
|
|
# part two
|
|
|
|
|
cave.default_proc = ->(h,(x,y)) { h[[x, y]] = y == y_max + 2 ? ?# : nil }
|
|
|
|
|
sands = 0
|
|
|
|
|
loop do
|
|
|
|
|
# inspect_cave.()
|
|
|
|
|
sands += 1
|
|
|
|
|
|
|
|
|
|
pos = [500, 0]
|
|
|
|
|
while next_pos = [0, -1, 1].map {|dx| pos.zip([dx, 1]).map { _1 + _2 }}.find { cave[_1].nil? }
|
|
|
|
|
pos = next_pos
|
|
|
|
|
cave[pos] = ?o
|
|
|
|
|
yield pos
|
|
|
|
|
end
|
|
|
|
|
break if pos == [500, 0]
|
|
|
|
|
|
|
|
|
|
cave[pos] = ?o
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
inspect_cave.()
|
|
|
|
|
p sands
|
|
|
|
|
y_max = cave.keys.map(&:last).max
|
|
|
|
|
|
|
|
|
|
# part one
|
|
|
|
|
p pour_sand(cave, stop: ->(_, y) { y >= y_max }).count
|
|
|
|
|
|
|
|
|
|
# part two
|
|
|
|
|
cave.delete_if { _2 == ?o } # reset cave
|
|
|
|
|
cave.default_proc = ->(_,(_,y)) { y == y_max + 2 ? ?# : nil }
|
|
|
|
|
p pour_sand(cave, stop: ->(x, y) { [x, y] == [500, 0] }).count + 1
|
|
|
|
|