Skip to content

Instantly share code, notes, and snippets.

@seifertd
Created February 10, 2012 19:44
Show Gist options
  • Save seifertd/1792137 to your computer and use it in GitHub Desktop.
Save seifertd/1792137 to your computer and use it in GitHub Desktop.
My solution to the Hitting Rock Bottom puzzle (http://puzzlenode.com/puzzles/11-hitting-rock-bottom)
class Cave
WATER = '~'
ROCK = '#'
AIR = ' '
attr_reader :grid, :flow_points
attr_accessor :water
# Create a Cave from the given file.
def initialize(filename)
# Keep track of points where water can flow either down or to the right
@flow_points = []
lines = File.readlines(filename)
# Amount of water that can flow into the cave
@water = lines.shift.to_i - 1
lines.shift
row_count = 0
# Build a grid for the cave. Coordinate 0,0 is the top left
@grid = lines.map do |line|
line.chomp!
row = line.split(//)
if row.first == WATER
# Seed the flow points by grabbing the first water point
@flow_points << [row_count,0]
end
row_count += 1
row
end
end
# Spew the grid to a string
def to_s
ret = "\n"
@grid.each do |row|
ret << row.join('') << "\n"
end
ret
end
# Flow until there is no water left
def run
while water > 0
flow
end
self
end
# Flow 1 unit of water
def flow
fp = @flow_points.last
if blocked_at?(fp.first+1, fp.last)
if @grid[fp.first][fp.last+1] == ROCK
@flow_points.pop
flow
else
new_row = fp.first
new_col = fp.last + 1
fp[0] = new_row
fp[1] = new_col
@grid[new_row][new_col] = WATER
@water -= 1
end
else
new_row = fp.first + 1
new_col = fp.last
@grid[new_row][new_col] = WATER
@water -= 1
@flow_points << [new_row, new_col]
end
self
end
# Return the water levels at each cave column
def levels
num_cols = @grid.first.size
num_rows = @grid.size
(0...num_cols).to_a.map do |col|
sum = 0
(0...num_rows).each do |row|
if sum > 0 && @grid[row][col] == AIR
sum = WATER
break
end
sum += 1 if @grid[row][col] == WATER
end
sum
end.join(" ")
end
private
# Is the water blocked at this point
def blocked_at?(row,col)
[WATER, ROCK].include?(@grid[row][col])
end
end
if __FILE__ == $0
# Command line: ruby cave.rb <cave_input_file>
cave = Cave.new(ARGV[0])
cave.run
puts "Final Cave State:\n#{cave}"
puts "Solution:"
puts cave.levels
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment