Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?

Nested foreach loops

by peterstriker (Initiate)
on Feb 26, 2011 at 16:41 UTC ( #890316=perlquestion: print w/replies, xml ) Need Help??
peterstriker has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I am completely new to computer programmming. I am working through 'Perl By Example, 4th edition'. I have been stuck for hours on the following end-of-chapter exercise... Could somebody please provide the correct script? I am not going to submit what I have done so far as I do not want to embarass myself :P. 'Write a script that will print 10 random cards from a deck. a. The script will build a deck of 52 cards by using nested foreach loops. b. The outer loop will iterate through a list consisting of cards for each suit: clubs, diamonds, hearts, spades. The inner loop will iterate through a list for each type of card within the suit: ace, 2 through 10, jack, queen, king. A card of each suit will be assigned to an array. c. The rand() function will be used to get a random card from the pack. There should be no duplicates.' Thanks!

Replies are listed 'Best First'.
Re: Nested foreach loops
by CountZero (Bishop) on Feb 26, 2011 at 17:01 UTC
    Hi peterstriker and welcome to our Monastery!

    Know that nobody will be embarassed here by a show of genuine effort and will to learn.

    Just show us what you have tried so far. The Monks will take it from there.

    To get you on your way, try first to build the array with the deck.

    Just follow the steps 'b' and 'c' quite literally. The array with the cards should finally contain entries like "Ace of Hearts", "10 of Spades", ...

    You can build these entries as follows::

    $card = "$type of $suit";
    with the variables $type and $suit being provided by the two foreach loops.


    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: Nested foreach loops
by toolic (Bishop) on Feb 26, 2011 at 16:56 UTC
    I am not going to submit what I have done so far as I do not want to embarass myself :P
    Take a chance... show the code you have tried. I bet you will learn more from a critique of your code than if someone provides a complete solution.

    If you have never seen nested foreach loops, the docs show an example: Foreach Loops

Re: Nested foreach loops
by wazoox (Prior) on Feb 26, 2011 at 17:03 UTC
    If you can't post code, at list post pseudo code, like :
    for each color in hearts, spades, clubs, diamonds, do for each figure in ace, king, queen, jack, 10 ....
    The difficult part in programming is not writing down the code, it's coming up with the correct algorithm.
Re: Nested foreach loops
by davies (Parson) on Feb 26, 2011 at 17:10 UTC

    I described and showed an implementation of a card dealing algorithm in Re: Random data generation.. There is no nesting, so it may not be what you want, since I don't know why you need to nest.


    John Davies

Re: Nested foreach loops
by Marshall (Abbot) on Feb 28, 2011 at 11:26 UTC
    This stuff is hard to pick when you are working through this by yourself. And this exercise manages to cover a lot of points. So I figure some extra hints are ok. Below is some code to get you started with generating the deck. Un-comment the extra print statements to see how the looping works. Looping is fundamental to computer programming and it is very important to be clear on how this works.

    The basic operations for dealing with arrays are: push, pop, shift, unshift and splice. Review how each one of these work. Also you can access each element in the array individually by using an index. $deck [ 0 ] is the first card.

    You will have to pick a card at random from the deck. Read about the rand() function rand() function. The deck has the scalar value of "@deck" number of cards in it. The indicies of all the cards are [ 0..@deck-1]. Note this range starts at zero not one!

    Once you can pick a card at random from the deck and print it, you have to figure out how you will satisfy the requirement that you can't have duplicates. I mean there is only one "2 of clubs" so you have to figure out a way to prevent it being picked twice. suggestion: think about what splice does.

    Have fun and let us know how it goes! Everybody here was a beginner once.

    #!/usr/bin/perl -w use strict; my @deck; foreach my $suit qw(clubs diamonds hearts spades) { #print "Working on the $suit\n"; # un-comment to watch looping foreach my $card_type (2..10,'ace','king','queen','jack') { #print " Now card=$card_type\n"; # un-comment to watch loop push @deck, "$card_type of $suit"; } } print "There are ".@deck." cards in the deck\n"; foreach my $card (@deck) { print "$card\n"; } __END__ Output....uncomment the 2 print statements in the nested loop to see exactly how the looping is done... There are 52 cards in the deck 2 of clubs 3 of clubs 4 of clubs ... etc. then diamonds, then hearts, spades...
Re: Nested foreach loops
by peterstriker (Initiate) on Feb 28, 2011 at 16:43 UTC

    Hey guys thanks for your help, after many hours of toil, I seem to have worked it out. I did all this BEFORE reading Marshall's reply. Feeling quite happy with myself for finally getting it to work :). Could I have some opinions on the way I went about it? Should I have done anything differently/more efficiently?

    #!/usr/bin/perl -w OUTER: @suit=('spades', 'hearts', 'clubs', 'diamonds'); foreach $suit(@suit) { INNER: @types=( "ace","2","3","4","5","6","7","8","9","10","jack"," +queen","king"); foreach $types(@types) { $card="$types of $suit"; print "$card\n"; $cardcounter++; push(@cards,$card,); } } print "\n"x2; print "$cardcounter cards have been created\n"; print "\n"x2; ATTEMPT: for ($counter=1;$counter<11;) { $i = int(rand(@cards)) ; push (@alreadyused,@cards[$i]); $count=grep (/@cards[$i]/i,@alreadyused); if ($count<2) { print "Random card is: @cards[$i]\n"; $counter++; push (@iterations,@cards[$i]); } else {next ATTEMPT;} } print "\n"x2; $number=@iterations; print "$number random cards have been chosen, with no duplicates";

      • Fix these warnings:
        Scalar value @cards[$i] better written as $cards[$i] at
      • Add use strict; then declare all variables with my. See use strict and warnings.
      • Perl has a convenient quoting operator which is handy for constructing lists: qw. It saves you from excessive quotes and commas. Range Operators are nice too:
        foreach $types ( qw(ace jack queen king), (2 .. 10) ) {
      • perltidy is useful for indenting code.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://890316]
Approved by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (4)
As of 2017-11-19 20:04 GMT
Find Nodes?
    Voting Booth?
    In order to be able to say "I know Perl", you must have:

    Results (282 votes). Check out past polls.