boom.roasted has asked for the wisdom of the Perl Monks concerning the following question:

I'm learning perl, and I'm trying to write a subroutine that will shuffle a deck of card, but not getting the whole deck back, why?

#!/usr/bin/perl require 'obj13-lib.pl'; @deck = ("A H","2 H","3 H","4 H","5 H","6 H","7 H","8 H", "9 H","10 H","J H","Q H","K H", "A D","2 D","3 D","4 D","5 D","6 D","7 D","8 D", "9 D","10 D","J D","Q D","K D", "A C","2 C","3 C","4 C","5 C","6 C","7 C","8 C", "9 C","10 C","J C","Q C","K C", "A S","2 S","3 S","4 S","5 S","6 S","7 S","8 S", "9 S","10 S","J S","Q S","K S"); { for(@deck){ s/H/Hearts/; s/D/Diamonds/; s/C/Clubs/; s/S/Spades/; } print"original deck:\n"; print"@deck\n"; @hand = shuf(@deck); print"shuffled deck:\n"; print"@hand\n"; } sub shuf { + + foreach $_ (@deck){ $lastcard = pop(@deck); $firstcard = shift(@deck); push(@newdeck,$firstcard,$lastcard);} @answer = @newdeck; return @answer; + + }

Replies are listed 'Best First'.
Re: array shuffle
by ikegami (Patriarch) on Aug 18, 2011 at 03:25 UTC

    Don't modify an array over which you are iterating using foreach. You actually want while (@deck) here anyway. It will produce a really bad shuffle, though. To shuffle a list or array, one normally uses List::Util's shuffle.

    Use use strict; use warnings;!!! You forgot to limit the scope many variables.

      I'm trying to test my skills without using the shuffle function. I was def using the wrong loop.

      Here's my problem now though, I want to shuffle the "deck" twice.

      using the  while (@deck) I can get the deck shuffled once, but when I use:

      @hand = shuf(@deck); print "deck shuffled once:\n"; print"@hand\n"; @deck = @hand; @newhand = shuf(@deck); print"deck shuffled twice:\n"; print"@newhand\n";

      I don't get the result I'm hoping for, what am I doing wrong now?

        Assuming that shuffling is simple is a mistake, and yet once you see an unbiased algorithm on paper (or screen) you will probably say, "Oooh, I get it." But done wrong, shuffling can introduce bias, and it's easy to do wrong.

        There is a nice article on Wikipedia: Fisher-Yates Shuffle. Implemented as a computer algorithm, it is sometimes known as the Knuth Shuffle. Also looking at the Pure Perl version of List::Util (here: Source for List::Util::PP) you will see a Perlish implementation of Fisher-Yates.

        Another post here pointed you to perlfaq4, which shows another Fisher-Yates implementation that is easier to read than the List::Util::PP version.

        For the masochistic or exceptionally curious: The Art of Computer Programming vol. 2 (3rd ed.), pg 145-146.


        Dave

        You're using a global variable which you empty the first time around instead of passing the deck to your function. You need to properly scope your variables.
Re: array shuffle
by johngg (Canon) on Aug 18, 2011 at 08:54 UTC

    As an aside, you can save yourself a lot of fiddly typing by using maps.

    $ perl -E ' > my @suits = qw{ Hearts Diamonds Clubs Spades }; > my @values = qw{ A 2 3 4 5 6 7 8 9 10 J Q K }; > my @deck = > map { my $suit = $_; map { qq{$_ $suit} } @values } @suits; > say for @deck;' A Hearts 2 Hearts 3 Hearts 4 Hearts 5 Hearts 6 Hearts 7 Hearts 8 Hearts 9 Hearts 10 Hearts J Hearts Q Hearts K Hearts A Diamonds 2 Diamonds 3 Diamonds 4 Diamonds 5 Diamonds 6 Diamonds 7 Diamonds 8 Diamonds 9 Diamonds 10 Diamonds J Diamonds Q Diamonds K Diamonds A Clubs 2 Clubs 3 Clubs 4 Clubs 5 Clubs 6 Clubs 7 Clubs 8 Clubs 9 Clubs 10 Clubs J Clubs Q Clubs K Clubs A Spades 2 Spades 3 Spades 4 Spades 5 Spades 6 Spades 7 Spades 8 Spades 9 Spades 10 Spades J Spades Q Spades K Spades

    I hope this is helpful.

    Cheers,

    JohnGG

Re: array shuffle
by Anonymous Monk on Aug 18, 2011 at 11:29 UTC

    The only thing random about manually shuffling a deck of cards is that we humans do it imperfectly. The ideal shuffle splits a deck in half and then interleaves the two halves. This is the basis of many "magic" card tricks: good shuffling.

    I realize this is just a programming exercise but you still need to decide if you're trying to randomize the deck or modeling an ideal (non-random) shuffle.

    There's a lot of theory surrounding shuffling and random but I fail to see the need to do an in place shuffle for a deck of cards unless you do it a LOT. Same goes for random, perl's would seem to be good enough for your needs but I wouldn't start a real money blackjack web site without something better.