Skip to content

Instantly share code, notes, and snippets.

@ryanbriones
Created July 6, 2011 06:35
Show Gist options
  • Save ryanbriones/1066683 to your computer and use it in GitHub Desktop.
Save ryanbriones/1066683 to your computer and use it in GitHub Desktop.
Towers of Hanoi
class Tower
attr_reader :name
def initialize(name)
@name = name
@disks = []
end
def stack(disk_number)
raise "Disk too big" unless can_stack?(disk_number)
@disks.unshift(disk_number)
end
def pull
raise "No disks" unless @disks.any?
disk = @disks.shift
disk
end
def to_s
tower = ["|"]
@disks.each do |length|
tower << "-" * length
end
tower << self.name
tower.join("\n")
end
def can_stack?(disk_number)
return true if @disks.none?
return disk_number < @disks.first
end
def top_disk?(disk_number)
@disks.first == disk_number
end
def disk_above(disk_number)
return nil if @disks.index(disk_number) == 0
@disks[@disks.index(disk_number) - 1]
end
end
class Hanoi
def initialize(size)
@tower1 = Tower.new(:tower1)
@tower2 = Tower.new(:tower2)
@tower3 = Tower.new(:tower3)
size.downto(1) do |block|
@tower1.stack(block)
end
@size = size
@move_count = 0
end
def to_s
"#{@tower1}\n\n#{@tower2}\n\n#{@tower3}"
end
def run
debug
move(@size, @tower1, @tower3, @tower2)
@move_count
end
def self.run!(size)
self.new(size).run
end
def move(disk_number, from, to, via)
disk_above = from.disk_above(disk_number)
move(disk_above, from, via, to) if disk_above
to.stack(from.pull)
debug
move(disk_above, via, to, from) if disk_above
@move_count += 1
end
def debug
return unless $VERBOSE
puts self
puts "\n==============\n\n"
end
end
puts Hanoi.run!(4)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment