Skip to content

Instantly share code, notes, and snippets.

@aamax
Created October 6, 2014 13:51
Show Gist options
  • Save aamax/978d940f765b58e5a203 to your computer and use it in GitHub Desktop.
Save aamax/978d940f765b58e5a203 to your computer and use it in GitHub Desktop.
Towers of Hanoi solution in ruby
require 'minitest/spec'
require 'minitest/autorun'
describe 'Game' do
it 'should have 3 pegs' do
game = Game.new
game.pegs.count.must_equal 3
end
it 'should have 3 discs by default' do
game = Game.new
game.discs.count.must_equal 3
end
it 'should be able to have 4 discs' do
game = Game.new(4)
game.discs.count.must_equal 4
end
it 'should start with all discs on source peg' do
game = Game.new
game.source.discs.count == 3
game.dest.discs.count == 0
game.spare.discs.count == 0
end
it 'should have correct number of moves and be finished' do
(3..10).each do |n|
game = Game.new(n)
game.play
game.number_moves.must_equal (2**n - 1)
game.dest.discs.length.must_equal n
v = 1
game.dest.discs.each do |d|
d.must_equal v
v += 1
end
end
end
it 'should have 0 moves before playing' do
game = Game.new
game.number_moves.must_equal 0
end
it 'should have correct # moves for 3 discs' do
game = Game.new
game.play
game.number_moves.must_equal (2**game.number_discs - 1)
end
it 'should have correct # moves for 4 discs' do
game = Game.new(4)
game.play
game.number_moves.must_equal (2**game.number_discs - 1)
end
end
class Peg
attr_accessor :last_location
def initialize
@discs = []
@last_location = nil
end
def add_discs(arr)
@discs = arr
end
def discs
@discs
end
end
SOURCE_INDEX = 0
SPARE_INDEX = 1
DEST_INDEX = 2
class Game
attr_accessor :pegs, :discs, :number_moves, :number_discs
def initialize(disc_count = 3)
@discs = []
(1..disc_count).each do |n|
@discs << n
end
@pegs = [Peg.new, Peg.new, Peg.new]
@pegs[0].add_discs(@discs)
@number_moves = 0
@number_discs = @discs.length
end
def show
puts "\ngame output:"
@pegs.each_with_index do |p, idx|
puts "Peg: #{idx} ---- discs: #{p.discs}"
end
end
def play
self.show
@number_moves = 0
process_game(@pegs[SOURCE_INDEX], @pegs[DEST_INDEX], @pegs[SPARE_INDEX], @number_discs)
puts "\n\n DONE:"
puts "number moves: #{@number_moves}"
end
def process_game(src_peg, dest_peg, spare_peg, number_left)
if number_left == 1
disc = src_peg.discs.pop
dest_peg.discs.push disc
@number_moves += 1
self.show
else
process_game(src_peg, spare_peg, dest_peg, number_left - 1)
process_game(src_peg, dest_peg, spare_peg, 1)
process_game(spare_peg, dest_peg, src_peg, number_left - 1)
end
end
def source
@pegs[0]
end
def dest
@pegs[2]
end
def spare
@pegs[1]
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment