class Card { has Str $.suit; has Int $.rank; method gist returns Str { my Str $rankStr = $.rank.Str; if (11 == $.rank) { $rankStr = 'J'; } elsif (12 == $.rank) { $rankStr = 'Q'; } elsif (13 == $.rank) { $rankStr = 'K'; } elsif (1 == $.rank) { $rankStr = 'A'; } return $rankStr ~ substr($.suit, 0, 1); } } class Joker is Card { } my Card @allCards; my Str @suits = 'Spades', 'Hearts', 'Diamonds', 'Clubs'; my @ranks = 1 .. 13; for @suits -> $s { for @ranks -> $r { my $card = Card.new(suit => $s, rank => $r); @allCards.push($card); } } @allCards.push(Joker.new(suit => 'Joker', rank => -1)); @allCards.push(Joker.new(suit => 'Joker', rank => -2)); sub isTwoPair(Card @cards) returns Bool { my Int $numJokers = 0; for @cards -> Card $card { if ($card.rank < 0) { $numJokers++; } } if ($numJokers == 2) { return True; } my Int $pairs = 0; for @ranks -> $r { my $cardsWithRank = 0; for @cards -> Card $card { if ($r == $card.rank) { $cardsWithRank++; } } $pairs += ($cardsWithRank / 2).truncate; } if ($numJokers == 1) { return $pairs >= 1; } return $pairs >= 2; } sub pickThisUp(Card @hand, Card $card) { loop (my $i = 0; $i < @hand.elems; $i++) { my Card @prospectiveHand = @hand.clone; @prospectiveHand.splice($i, 1, $card); if (isTwoPair(@prospectiveHand)) { return $i; } } return -1; } my $totalGames = 1000; my $rounds = 2; my $timesBatmanGotTwoPairEveryRound = 0; loop (my $gameNum = 0; $gameNum < $totalGames; $gameNum++) { my $timesBatmanGotTwoPair = 0; my Card @deck = @allCards.pick(*); my @discardPiles; loop (my $i = 0; $i < 3; $i++) { my Card @discardPile = @deck.pop(); @discardPiles[$i] = @discardPile; } my Card @hand = @deck.splice(@deck.end-5, 5); loop (my $roundNum = 0; $roundNum < $rounds; $roundNum++) { if (isTwoPair(@hand)) { # dealt what we needed @discardPiles.pick.push(@deck.pop()); } else { my Int $pickThisUp = -1; # "AI" determines which card to pick up for @discardPiles -> @discardPile { my Card $top = @discardPile[@discardPile.end]; $pickThisUp = pickThisUp(@hand, $top); if ($pickThisUp >= 0) { @discardPile.pop(); @discardPile.append(@hand.splice($pickThisUp, 1, $top)); last; } } if ($pickThisUp == -1) { my $top = @deck.pop(); $pickThisUp = pickThisUp(@hand, $top); if ($pickThisUp >= 0) { @discardPiles.pick.append(@hand.splice($pickThisUp, 1, $top)); } else { @discardPiles.pick.push($top); } } } if (isTwoPair(@hand)) { $timesBatmanGotTwoPair++; @hand = @deck.splice(@deck.end-5, 5); } } if ($rounds == $timesBatmanGotTwoPair) { $timesBatmanGotTwoPairEveryRound++; } } my $result = 100*($timesBatmanGotTwoPairEveryRound/$totalGames); say 'Batman got two pair ' ~ $timesBatmanGotTwoPairEveryRound ~ ' times or ' ~ $result ~ '%.';