Skip to content

Instantly share code, notes, and snippets.

@gromnitsky
Created Dec 23, 2011
Embed
What would you like to do?
Molloy Problem
#!/usr/bin/env ruby
# -*-ruby-*-
require 'pp'
require 'minitest/autorun'
class Pocket
MAX = 16
attr_reader :stones, :name
def initialize(name, stones = [])
@name = name
@stones = *stones
end
def to_s
"#{name}: #{@stones.to_s}"
end
def <<(s)
return false unless @stones.size < MAX
@stones << s
return true
end
def moveStoneTo(pocket)
return false if @stones.size == 0
idx = (rand @stones.size).to_i
e = @stones[idx]
@stones.delete_at idx
# actual Molloy's sucking of 'e' stone
yield e if block_given?
return pocket << e
end
end
class Molloy # Java style!
def initialize(p1, p2, p3, p4)
@p1 = p1
@p2 = p2
@p3 = p3
@p4 = p4
end
def self.print_pockets(*p)
p.each {|idx| pp idx }
puts ""
end
# must return an array
def rotate
fail "override me"
end
def suckStones(verbose = true)
Molloy.print_pockets @p1, @p2, @p3, @p4 if verbose
q = rotate
if verbose
Molloy.print_pockets @p1, @p2, @p3, @p4
pp q
pp q.size
end
q
end
end
class SeasideMolloy < Molloy
def initialize(p1, p2, p3, p4)
super p1, p2, p3, p4
end
def rotate
q = []
while @p1.moveStoneTo(@p4) {|idx| q << idx }; end
while @p2.moveStoneTo(@p1) {|idx| q << idx }; end
while @p3.moveStoneTo(@p2) {|idx| q << idx }; end
while @p4.moveStoneTo(@p3); end
q
end
end
# [1] ==> [4*]
#
# /\ ||
# || \/
#
# [2] <== [3]
class TestSeasideMolloy < MiniTest::Unit::TestCase
def setup
p1 = Pocket.new 1, [1, 2, 3, 4, 5, 6]
p2 = Pocket.new 2, [7, 8, 9, 10, 11]
p3 = Pocket.new 3, [12, 13, 14, 15, 16]
p4 = Pocket.new 4
@sm = SeasideMolloy.new p1, p2, p3, p4
@sm.suckStones
end
def test_sucking
256.times {
q = @sm.suckStones false
assert_equal Pocket::MAX, q.uniq.size
}
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment