in reply to 52 Perl Pickup

Your algorithm does not accurately represent how one would achieve grouping of decks in real life. The easiest way to do that would almost certainly be to sort. First by suit, creating 4 individual piles. And the sorting each suit pile by rank. And finally separating the larger sorted pile of cards into individual decks.

The following script represents this algorithmically:
use List::Util qw(shuffle); use strict; # Ordered least to greatest my @suit = qw(C D H S); my @rank = ( 2 .. 10, qw(J Q K A) ); # Construct a standard deck my @card = map { my $suit = $_; map { "$_$suit" } @rank } @suit; # Shuffle 4 piles of cards. my @pile = shuffle( (@card) x 4 ); print "Pile\n\t@pile\n\n"; # Sort my %ord_suit = map { $suit[$_] => $_ } ( 0 .. $#suit ); my %ord_rank = map { $rank[$_] => $_ } ( 0 .. $#rank ); my @pile_sorted = map { $_->[0] } sort { $ord_suit{ $a->[1][1] } <=> $ord_suit{ $b->[1][1] } || $ord_rank{ $a->[1][0] } <=> $ord_rank{ $b->[1][0] } } map { [ $_, [m/(.*)(.)/] ] } @pile; # Group Cards into Decks my @deck; my $lastcard = ''; my $index; for my $card (@pile_sorted) { if ( $card ne $lastcard ) { $index = 0; } else { $index++; } push @{ $deck[$index] }, $card; $lastcard = $card; } print "Decks\n"; foreach (@deck) { print "\t@$_\n"; }
- Miller

Replies are listed 'Best First'.
Re^2: 52 Perl Pickup
by wind (Priest) on Aug 04, 2007 at 01:37 UTC
    And if you want to do this more generically:

    Define an unique order for each object. In this instance that happens to just be the card's value. Then create a list of hashes where a card is only added if one of the same order does not exist.
    use List::Util qw(shuffle first); use strict; # Ordered least to greatest my @suit = qw(C D H S); my @rank = (2..10, qw(J Q K A)); # Construct a standard deck my @card = map { my $suit = $_; map {"$_$suit"} @rank } @suit; # Shuffle 4 piles of cards. my @pile = shuffle( (@card) x 4 ); print "Pile\n\t@pile\n\n"; # Group Cards into Decks my @deck; for my $card (@pile) { # Order of Object my $ord = $card; my $deck = first {! exists $_->{$ord}} @deck; # Start new deck if (! $deck) { $deck = {}; push @deck, $deck; } $deck->{$ord} = $card; } # Results: print "Decks:\n"; for my $deck (@deck) { print "\t" . join(' ', values %$deck) . "\n"; }
    When you view the results, you'll notice that each of the "decks" appear to be near identical. This is because of the internal implementation of hashes and the way that elements are assigned a place in the hash.

    - Miller
Re^2: 52 Perl Pickup
by Upstairs (Novice) on Aug 26, 2007 at 14:57 UTC
    My previous post was a non-sequitur, sorry. It would be easier if the dealer wasn't colour-blind. We could factor in the backs.
    #!/usr/bin/perl -w # Re-sorting a pile of four decks. Unfazed by missing cards. # Using tr to avoid the unfathomable card-sort map. # Mock names for easy sorting my @suit = qw(f g h i); my @rank = (2..9, qw(a b c d e)); my @pile= (); sub shuffle { for (my $i = $#_ ; $i > 0 ; $i--) { @_[$_, $i] = @_[$i, $_] for rand $i+1 } return @_; } sub readable { my $string = join(" ", @_); $string =~ tr/abcdefghi/TJQKACDHS/; return $string; } sub separate { my @cards = sort @_; my @box = (); my $deck = 0; my $prevcard = ""; for my $card (@cards) { if ($card ne $prevcard) {$deck = 0}; push @{$box[$deck++]}, $card; $prevcard = $card; } return @box; } for (1..4) { push (@pile, (map {$rank = $_; map {"$_$rank"} @suit} @rank)); } shuffle @pile; print "\nFour decks shuffled together\n"; print (readable @pile); my @decks = separate @pile; print "\n\nFour decks separated\n"; foreach (@decks) { print (readable @$_); print "\n"; }
      Which can be whittled down to a more useful PNB dealer which would normally be written to a file. I did it to feed the the GIB command-line bridge engine.
      #!/usr/bin/perl ## Dealing cards in PBN (Portable Bridge Notation) ## Using tr to avoid the awesome card-sort map ## mock names for easy sorting my @suit = qw(f g h i); my @rank = (2..9, qw(a b c d e)); my @seps = qw(g. h. i.); sub shuffle { for (my $i = $#_ ; $i > 0 ; $i--) { @_[$_, $i] = @_[$i, $_] for rand $i+1 } return @_; } ## reformats one hand at a time sub pbnFormat { push (@_, @seps) ; local $string = join(``, sort{$b cmp $a}@_); $string =~ tr/abcdefghi/TJQKA/d; return $string; } my @deck = shuffle(map{$rank=$_; map{"$_$rank"}@suit}@rank); for(1..4) { print pbnFormat splice @deck,0,13; print "\n"; }