```I took the OO approach and implemented a strategy pattern.
To see the game play out, pass in the -v flag, and -d will show the
actual command given for each move.

The output of the test file contains a frequency distribution to show
how each matchup plays out.

Here is some sample output for the second matchup in the test over 200
games:
_____________________________________
Game 2: Aggressive vs Random
3: ---------------------------------33
4:
--------------------------------------------------------------------68
5: -------------------------------------------43
6: ------------------------24
7: ---------------15
8: -----5
9: -------7
10: ----4
11: -1
Player 1: 166 wins
Player 2: 34 wins
______________________________________

In an Aggressive vs Aggressive game, the first player wins in 3 rounds
every time.  Obviously there are better
strategies that I didn't take the time to explore.

Again, I'm happy to receive any comments.  I feel like my solutions
are so clunky compared to what you guys submit.
I am here to learn!

Here's my code:

#file: game.rb
#author: Matt Hulse - www.matt-hulse.com

require 'player'

class Game
attr_reader :p1, :p2, :winner, :rounds

def initialize(p1_strategy = "random", p2_strategy = "random")
@p1 = Player.new(1,p1_strategy, self)
@p2 = Player.new(2,p2_strategy, self)
@rounds = 0
end

def get_opponent(player)
return @p1 if @p2 == player
return @p2 if @p1 == player
end

def loop
#keep going until one person has no hands left
#after 100 rounds we're calling a draw!

puts self if \$VERBOSE
until(game_over) do
@rounds += 1
p1.move
puts self if \$VERBOSE

unless game_over then
p2.move
puts self if \$VERBOSE
end
break if @rounds >= 100
end

if(lost?(p1)) then
@winner = p2
elsif(lost?(p2))
@winner = p1
else
puts "Draw"
end
end

def game_over
lost?(p1) || lost?(p2)
end

def lost?(player)
player.left.finger_count <= 0 and player.right.finger_count <= 0
end

def to_s
"#{p1}\n#{p2}\n"
end
end

#file: hand.rb
#author: Matt Hulse - www.matt-hulse.com

class Hand

def initialize(right_or_left, count = 1)
@right_or_left = right_or_left
@finger_count = count
end

def touch(hand)
end

@finger_count += num
if @finger_count >= 5 then
@finger_count = 0
end
end

def clap(hand,num)
hand.add_fingers(num) #num must be <= self.finger_count
@finger_count -= num
end

def to_s
result = ""
#print left to right
i = 0
(1..5).each{
i += 1
if(i <= @finger_count) then
result += "|"
else
result += "-"
end
}
return result if @right_or_left == :right
return result.reverse
end

end

#file: player.rb
#author: Matt Hulse - www.matt-hulse.com

require 'hand'

class Player
attr_reader :player_num, :right, :left, :strategy, :game
def initialize(player_num, strategy, game)
@player_num = player_num
@strategy = strategy
@game = game
@right = Hand.new(:right,1)
@left = Hand.new(:left,1)
end

def move
begin
eval(@strategy)
rescue NameError => e
random #default to random
end
end

def get_opponent
@game.get_opponent(self)
end

def get_larger_hand
return @right if @right.finger_count > @left.finger_count
return @left
end

def min(a,b)
return a if a <= b
return b
end

def random
#all possible moves, choose randomly among them
opponent = get_opponent

valid_moves = Array.new

opp_rt_count = opponent.right.finger_count
opp_lt_count = opponent.left.finger_count

if(@right.finger_count > 0) then
valid_moves << "@right.touch(opponent.right)" if opp_rt_count >
0
valid_moves << "@right.touch(opponent.left)" if opp_lt_count > 0
#total on hand transferred to cannot be more than 5
#random number is between 1 and the minimum of what left can
receive and right can give
rand_max = min(5- / left.finger_count,@right.finger_count-1)
valid_moves << "@right.clap(@left, #{rand(rand_max) + 1})" if
rand_max > 0
end

if(@left.finger_count > 0) then
valid_moves << "@left.touch(opponent.right)" if opp_rt_count > 0
valid_moves << "@left.touch(opponent.left)" if opp_lt_count > 0
#total on hand transferred to cannot be more than 5
#random number is between 1 and the minimum of what right can
receive and left can give
rand_max = min(5- / right.finger_count,@left.finger_count-1)
valid_moves << "@left.clap(@right, #{rand(rand_max) + 1})" if
rand_max > 0
end

move = valid_moves[rand(valid_moves.size)]
eval(move)
puts "Player #{player_num}: #{move}" if \$DEBUG
end

def aggressive
opponent = get_opponent

#every move is to touch the opponents largest hand with the local
largest hand
move = "get_larger_hand.touch(opponent.get_larger_hand)"

eval(move)
puts "Player #{player_num}: #{move}" if \$DEBUG
end

def to_s
"#{player_num}: #{@left} #{@right}"
end
end

#file: test.rb
#author: Matt Hulse - www.matt-hulse.com

require 'game'

puts "Game 1: Random vs Random"

num_rounds = Hash.new(0)
wins = Hash.new(0)

(1..200).each{
game = Game.new("random","random")
game.loop
if(game.winner) then
puts "Player #{game.winner.player_num} won in #{game.rounds}
rounds using #{game.winner.strategy} strategy." if \$VERBOSE
num_rounds[game.rounds] += 1
wins[game.winner.player_num] +=1
end
}

num_rounds.keys.sort{|a,b| a<=>b}.each{|i|
puts "#{i}: #{'-'*num_rounds[i]}#{num_rounds[i]}"
}

wins.each_pair{|key,value|
puts "Player #{key}: #{value} wins"
}

puts
puts "Game 2: Aggressive vs Random"

num_rounds = Hash.new(0)
wins = Hash.new(0)

(1..200).each{
game = Game.new("aggressive", "random")
game.loop
if(game.winner) then
puts "Player #{game.winner.player_num} won in #{game.rounds}
rounds using #{game.winner.strategy} strategy." if \$VERBOSE
num_rounds[game.rounds] += 1
wins[game.winner.player_num] +=1
end
}

num_rounds.keys.sort{|a,b| a<=>b}.each{|i|
puts "#{i}: #{'-'*num_rounds[i]}#{num_rounds[i]}"
}

wins.each_pair{|key,value|
puts "Player #{key}: #{value} wins"
}

puts
puts "Game 3: Aggressive vs Aggressive"

num_rounds = Hash.new(0)
wins = Hash.new(0)

(1..200).each{
game = Game.new("aggressive","aggressive")
game.loop
if(game.winner) then
puts "Player #{game.winner.player_num} won in #{game.rounds}
rounds using #{game.winner.strategy} strategy." if \$VERBOSE
num_rounds[game.rounds] += 1
wins[game.winner.player_num] +=1
end
}

num_rounds.keys.sort{|a,b| a<=>b}.each{|i|
puts "#{i}: #{'-'*num_rounds[i]}#{num_rounds[i]}"
}

wins.each_pair{|key,value|
puts "Player #{key}: #{value} wins"
}

Thanks,

__________
Matt Hulse
matt.hulse / gmail.com
http://www.matt-hulse.com

On Apr 13, 5:48 am, Ruby Quiz <j... / grayproductions.net> wrote:
> The three rules of Ruby Quiz:
>
> 1.  Please do not post any solutions or spoiler discussion for this quiz until
> 48 hours have passed from the time on this message.
>
> 2.  Support Ruby Quiz by submitting ideas as often as you can:
>
> http://www.rubyquiz.com/
>
> 3.  Enjoy!
>
> Suggestion:  A [QUIZ] in the subject of emails about the problem helps everyone
> on Ruby Talk follow the discussion.  Please reply to the original quiz message,
> if you can.
>
> -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
>
> We have a foreign exchange student from Korea staying with us.  The best part of
> that is the intended exchange of cultures.  For example, to kill time on a
> recent plane trip, the student taught us a common finger game children play in
> Korea.
>
> The rules are very easy:
>
>         1.  Both players start by holding up one finger on each hand.
>         2.  On each turn a player must do one of the following:
>           a.  Touch one of their hands to an opponent's hand, adding the finger
>               count on their hand to the touched hand.  The player keeps the same
>               number of fingers, but the opponent must add the player's finger
>               count in addition to the fingers already on that hand.
>           b.  Clap their hands together to "transfer" one or more fingers from
>               one hand to the other.  You cannot transfer all the fingers off of
>               a hand.
>         3.  A hand with five or more fingers is eliminated, which is shown by
>             making a fist.  An opponent can not add fingers to an eliminated
>             hand and an it cannot be used in touches, but players may transfer
>             fingers to it, "reviving" it.  The first player with two eliminated
>             hands loses the game.
>
> For example, here is how a quick game might play out:
>
>         1:  ----|  |----  Starting fingers.
>         2:  ----|  |----
>
>         1:  ----|  |----  Player 1's left hand touches player 2's right hand.
>         2:  ----|  ||---
>
>         1:  ----|  |||--  2's right touches 1's right hand.
>         2:  ----|  ||---
>
>         1:  ----|  |||--  1's right touches 2's right hand.
>         2:  ----|  -----
>
>         1:  ----|  ||||-  2's left touches 1's right hand.
>         2:  ----|  -----
>
>         1:  ----|  |||--  1's right touches 2's left hand.
>         2:  -----  -----
>
> Of course, as a programmer, I immediately tried to solve this game.  I suck the
> fun right out of everything, but at least it gave us another quiz topic.
>
> This week's Ruby Quiz is to programmatically solve Magic Fingers.  Is it a win
> for the first or second player with perfect play, or can you always force a draw
> with repeating counts?  Have your program print some output that would convince
> anyone beyond the shadow of a doubt what the game's outcome will be.

```