[32871] in Perl-Users-Digest
Perl-Users Digest, Issue: 4149 Volume: 11
daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Mon Feb 24 14:14:36 2014
Date: Mon, 24 Feb 2014 11:14:13 -0800 (PST)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)
Perl-Users Digest Mon, 24 Feb 2014 Volume: 11 Number: 4149
Today's topics:
Re: use strict; use warnings; <gravitalsun@hotmail.foo>
Re: use strict; use warnings; <mvdwege@gmail.com>
Re: use strict; use warnings; <justin.1401@purestblue.com>
Re: use strict; use warnings; <ben@morrow.me.uk>
Re: use strict; use warnings; <justin.1401@purestblue.com>
Re: use strict; use warnings; <janek_schleicher@yahoo.de>
Re: use strict; use warnings; <marius@ieval.ro>
Re: use strict; use warnings; <justin.1401@purestblue.com>
Re: use strict; use warnings; (Jens Thoms Toerring)
Re: use strict; use warnings; <marius@ieval.ro>
Re: use strict; use warnings; <ben@morrow.me.uk>
Re: use strict; use warnings; <johnblack@nospam.com>
Re: use strict; use warnings; <mach2@hushmail.com>
Re: use strict; use warnings; <mach2@hushmail.com>
Re: use strict; use warnings; <mach2@hushmail.com>
Re: use strict; use warnings; <mach2@hushmail.com>
Re: use strict; use warnings; <mach2@hushmail.com>
Re: use strict; use warnings; <mach2@hushmail.com>
Re: use strict; use warnings; <mach2@hushmail.com>
Re: use strict; use warnings; <mach2@hushmail.com>
Re: use strict; use warnings; <mach2@hushmail.com>
Re: use strict; use warnings; <john@castleamber.com>
Re: use strict; use warnings; <mach2@hushmail.com>
Re: use strict; use warnings; <mach2@hushmail.com>
Re: use strict; use warnings; <john@castleamber.com>
Re: use strict; use warnings; <ben@morrow.me.uk>
Re: use strict; use warnings; <ben@morrow.me.uk>
Re: use strict; use warnings; <rweikusat@mobileactivedefense.com>
Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)
----------------------------------------------------------------------
Date: Mon, 24 Feb 2014 10:16:24 +0200
From: George Mpouras <gravitalsun@hotmail.foo>
Subject: Re: use strict; use warnings;
Message-Id: <leev3h$2abs$1@news.ntua.gr>
here is some shuffle fun
#!/usr/bin/perl
use strict;
use warnings;
my @array = qw/a b c e r/;
for (my $i=0; $i<scalar @array/2; $i++) {
push @array, shift @array}
for (my $i=$#array; $i>0; $i -= 2) {
my $l1 = pop @array;
my $l2 = pop @array;
unshift @array, $l2;
unshift @array, $l1}
print "@array"
------------------------------
Date: Mon, 24 Feb 2014 08:31:47 +0100
From: Mart van de Wege <mvdwege@gmail.com>
Subject: Re: use strict; use warnings;
Message-Id: <8661o5arvg.fsf@bors.avalon.lan>
Marek Novotny <mach2@hushmail.com> writes:
>
> When I started to try to use the use strict and warnings, I got warnings
> such as: Scalar value @diamonds[$i] better written as $diamonds[$i] at ./
> obj10.pl line 55.
>
> But the whole point of what I am doing is loading elements into an
> array... So I wanted it as @diamonds, not $diamonds, and so on.
>
Yeah, this is a common mistake.
Single elements of an @array are scalars themselves, so they are
addressed as $elem[$index]. The @array[$number] syntax is used to take a
*slice* of an array. This might work (it usually does), but can cause
hard to find bugs.
Mart
------------------------------
Date: Mon, 24 Feb 2014 09:20:51 +0000
From: Justin C <justin.1401@purestblue.com>
Subject: Re: use strict; use warnings;
Message-Id: <jgfrta-jsu.ln1@zem.masonsmusic.co.uk>
On 2014-02-24, Marius Gavrilescu <marius@ieval.ro> wrote:
> --=-=-=
> Content-Type: text/plain; charset=utf-8
> Content-Transfer-Encoding: quoted-printable
Marius, this isn't going to help, your reply is full of
> =20
> =20
>> =20
>
...
> warnings are correct =E2=80=94 you should write $diamonds[$i] instead
> my $i =3D 0;
> =2D-=20
> Marius Gavrilescu
>
> --=-=-=
> Content-Type: application/pgp-signature
>
> --=-=-=--
The above could be part of the problem. Plain text works globally.
Justin.
--
Justin C, by the sea.
------------------------------
Date: Mon, 24 Feb 2014 10:49:21 +0000
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: use strict; use warnings;
Message-Id: <hmkrta-bi22.ln1@anubis.morrow.me.uk>
Quoth Marek Novotny <mach2@hushmail.com>:
>
> my $i = 0;
> while ($i < 13){
> @hearts[$i] = shift(@startingdeck);
> $i++;
> }
Perl arrays already know how long they are: you don't need to count for
yourself. You may not have covered this, but using an array in scalar
context, for example by comparing it to a number, will use the length of
the array. So:
while (@hearts < 13) {
push @hearts, shift @startingdeck;
}
> # put the organized cards back in the starting deck
>
> push (@startingdeck, @hearts, @diamonds, @clubs, @spades);
Why did you include this step? What does it do for you?
> # sort the suits in reverse high order stating with ace, kings, etc.
>
> my $i = 0;
> while ($i < 51){
> @sorted[$i] = pop(@hearts); $i++;
> @sorted[$i] = pop(@diamonds); $i++;
> @sorted[$i] = pop(@clubs); $i++;
> @sorted[$i] = pop(@spades); $i++;
> }
Have you learned about 'reverse' yet? If not:
push @sorted, pop @hearts while @hearts;
or if you'd rather
while (@hearts) {
push @sorted, pop @hearts;
}
This isn't exactly 'shuffled', though I suppose you've done quite a bit
of array manipulation, which was maybe the point. If I were given this
assignment I might try to emulate something more like an overhand
shuffle, so:
- Pull some number of cards (say, 15) off the top of the deck into a
new array @hand. Make sure to keep them in order (and don't use
splice, that's presumably cheating :) ).
- Transfer them back onto the bottom of the deck, starting with the
card at the bottom of @hand.
If you're feeling ambitious you might want to try dropping them from
your 'hand' back into the 'deck' in groups of two or three. At the point
you're at now this will mean a third @drop array to temporarily hold the
cards 'in flight' between @hand and @deck.
Ben
------------------------------
Date: Mon, 24 Feb 2014 10:21:30 +0000
From: Justin C <justin.1401@purestblue.com>
Subject: Re: use strict; use warnings;
Message-Id: <a2jrta-ce4.ln1@zem.masonsmusic.co.uk>
On 2014-02-24, Marek Novotny <mach2@hushmail.com> wrote:
> Hi group,
>
> Tonight I finished up another obj for my class. The class has not yet
> started to learn about use strict; and use warnings;
Maybe they haven't taught you yet, but they are best practice, and
will catch most errors, it saves the regulars here from pointing out
the obvious.
Use them, and then strip them out before your tutor sees your code.
I've never heard of removing them breaking any code. [1]
> I was given the following to solve:
[snipped]
Have they taught you about random numbers yet? I can't see how it's
possible to shuffle without random numbers.
However, you've been told to use pop, shift and push. Maybe you could
create a new array, pushing cards into it that you've 'pop'ped and
'shift'ed from the old array in some pseudo random fashion? [2]
[snipped]
> When I started to try to use the use strict and warnings, I got warnings
> such as: Scalar value @diamonds[$i] better written as $diamonds[$i] at ./
> obj10.pl line 55.
>
> But the whole point of what I am doing is loading elements into an
> array... So I wanted it as @diamonds, not $diamonds, and so on.
@diamonds is the whole array, $diamonds[2] refers an array element.
(the same works for hashes, but you probably haven't done those yet:
%coffee is the whole hash, but $coffee{espresso} refers to a portion
of data *in* the %coffee hash).
The @ and % refer to the whole. $ and [suffix] or {suffix} refer to
a part for arrays and hashes respectively.
> I tried to make the code as simple to understand as possible.
>
> Anyone care to take a stab at what it would have to look like with the
> use of strict and warnings so I can understand what I should be doing?
That's a lot of work for grabbing the wrong end of the stick. :(
Justin.
1. except:
no warnings 'uninitialized';
# and similar
but you won't be using that without having been taught about 'use
warnings' anyway).
2. Maybe something like:
for (my $i = 0; $i < $size_of_array; $i++) {
if ($i % 3) {
push @new, shift @array;
}
else {
push @new, pop @array;
}
}
You might want to wrap all of that in another loop and run it a
few times. It should give *the appearance* of a shuffled deck,
but you can see it'll shuffle identically each time, so it's not
a real shuffle - if running it more than once be sure to replace
@array with @new each time or you'll shuffle the first array
each time, and not the partly shuffled one!
--
Justin C, by the sea.
------------------------------
Date: Mon, 24 Feb 2014 12:45:34 +0100
From: Janek Schleicher <janek_schleicher@yahoo.de>
Subject: Re: use strict; use warnings;
Message-Id: <bn0pn5Fj34eU1@mid.individual.net>
Am 24.02.2014 06:31, schrieb Marek Novotny:
> ...
> @startingdeck = ("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");
> ...
Beside your problem you asked,
one important lesson in programming is to avoid to reapeat yourself,
as we are lazy :-) and more important it would be heart to maintain
(change or update your program in future).
Just imagine here, you might also play with a double deck or with jokers
or without deuces (or you'd prefer to have an other starting deck order
of cards), than with this way, you would have to copy+paste and replace
it manually with a lot of keystrokes. Not only is this boring, more
important, it is easy to make a mistake doing so.
Here a nice and simple way that also fits into your course (working with
arrays and loops would be) [untested]:
my @startingdeck = ();
foreach my $rang (2 .. 9, qw/T J Q K A/) {
foreach my $color(qw/H D C S/) {
push @startingdeck, "$rang $color";
}
}
# Starting deck is now filled with a classic 52 card deck
So it's easy to read, short to write and easy to change,
and most important you Don't Repeat Yourself (DRY-principle).
Greetings,
Janek
PS: You problably don't know yet what this qw/../ operator means,
here it's just a short cut for
qw/H D C S/ is the same as ("H", "D", "C", "S").
------------------------------
Date: Mon, 24 Feb 2014 14:00:27 +0200
From: Marius Gavrilescu <marius@ieval.ro>
Subject: Re: use strict; use warnings;
Message-Id: <878ut0iuuc.fsf@ieval.ro>
Justin C <justin.1401@purestblue.com> writes:
> Marius, this isn't going to help, your reply is full of
> ...
> The above could be part of the problem. Plain text works globally.
Sorry, I assumed that every client was able to read MIME messages. I
don't know how to make gnus send non-MIME messages. I've disabled the
PGP signature for this message, maybe it will also disable MIME.
As far as I know, slrn has the ability to process MIME messages with
metamail. This may help you view MIME messages in the future.
My previous article said:
In Perl, the tenth element of array @something is $something[10]. So the
warnings are correct — you should write $diamonds[$i] instead of
@diamonds[$i].
Another problem is that you declare the $i variable multiple times. You
should only declare it once, the first time you use it. You can also
refactor
my $i = 0;
while ($i < 13){
$spades[$i] = shift(@startingdeck);
$i++;
}
to
for (my $i = 0 ; $i < 13 ; $i++) {
$spades[$i] = shift(@startingdeck);
}
Finally, there are several undeclared variables (@hearts, @diamonds,
@spades, @clubs, @sorted, $ace).
After fixing these three problems the code should run without warnings
under use strict; use warnings;
--
Marius Gavrilescu
------------------------------
Date: Mon, 24 Feb 2014 12:39:15 +0000
From: Justin C <justin.1401@purestblue.com>
Subject: Re: use strict; use warnings;
Message-Id: <j4rrta-lj6.ln1@zem.masonsmusic.co.uk>
On 2014-02-24, Marius Gavrilescu <marius@ieval.ro> wrote:
> Justin C <justin.1401@purestblue.com> writes:
>
>> Marius, this isn't going to help, your reply is full of
>> ...
>> The above could be part of the problem. Plain text works globally.
>
> Sorry, I assumed that every client was able to read MIME messages. I
> don't know how to make gnus send non-MIME messages. I've disabled the
> PGP signature for this message, maybe it will also disable MIME.
That's better, thank you! :)
> As far as I know, slrn has the ability to process MIME messages with
> metamail. This may help you view MIME messages in the future.
I don't recall using/needing it in 17 years of slrn usage, but I'll
take a look.
> My previous article said:
[snip]
'tis legible now. We don't know what software the OP is using,
I always prefer to send (and receive) something that everyone
can read than something that relies on having the correct soft-
ware for it to be readable.
Sorry if I came across as a plain-text pedant, I didn't mean
to. Please accept my apologies. I put it down to it being early
Monday morning, and an insufficient quantity of caffein.
Justin.
--
Justin C, by the sea.
------------------------------
Date: 24 Feb 2014 14:23:20 GMT
From: jt@toerring.de (Jens Thoms Toerring)
Subject: Re: use strict; use warnings;
Message-Id: <bn12umFl1ruU1@mid.uni-berlin.de>
Marek Novotny <mach2@hushmail.com> wrote:
> Hi group,
> Tonight I finished up another obj for my class. The class has not yet
> started to learn about use strict; and use warnings;
> I was given the following to solve:
> # Objective 1:
> # The pop function "pops" off the last element of an array
> # and returns it. It works like this:
> #
> # $element = pop(@array);
> #
> # The shift function works the same way, but removes an element
> # from the front of an array.
> #
> # Using pop, shift, push, and the starting code below, write a script
> # that sufficiently "shuffles" a simulated deck of cards before printing
> # the top five cards. Save this script in your home directory as
> # obj10.pl.
> #
> # The goal of this objective is to familiarize yourself
> # with these three functions while using loops and to use them
> # together to rearrange the array but not a randomly shuffled array.
> @startingdeck = ("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");
> And here is my solution, which does not include the use of use strict;
> and use warnings;
This isn't the solution asked for - you're supposed to shuffle
the array, not sort it. What's the most simple way to shuffle
a deck of cards? Just remove a random card from the deck and
put it on a new heap and repeat this until there are no more
cards in the deck you started with. And you can shuffle your
array in exactly the same way when you think about it.
The first question is, of course, how to pick a card at random.
Perl has a nice function called 'rand' for this (if you haven't
yet please read the documentation for it, all you've got to do
is type "perldoc -f rand" in your terminal and you get the do-
cumentation.
rand() returns a floating point number. If called without an
argument (or with 0 or 1) it's a floating point number between
0 and less than 1. If you give it any other argument it returns
a random number between 0 and less than the argument. But what
we need is an integer number we can use as an index into our
array. That's were the int() function comes handy, which strips
of the fractional part of a floating point number.
Now, since you start with 52 cards, you would use
my $rnd_index = int( rand( 52 ) );
rand() will return a number between 0 and less than 52, and
int() will make sure that it's an integer bewteen 0 and 51.
Thus the result is suitable for accessing one of the elements
of your array '@startingdeck' and we can put the value of
that element into a new array named '@shuffled'. But we also
have to remove the "card" from the "deck", i.e. the element
from the array. In a very pedestrian way we could do it like
this
my @shuffled;
my $rnd_index = int( rand( 52 ) );
my @temp;
for my $i ( 0 .. $rnd_index - 1 ) {
push @temp, shift @startingdeck;
}
push @shuffled, shift @startingdeck;
for my $i ( 0 .. $rnd_index - 1 ) {
unshift @startingdeck, pop @temp;
}
As you can see we first move all cards before the one we
randomly selected to a "temporary deck". Then we move the
card we're interested in to our deck of shuffled cards. An
then we put the cards we had stored on the tem,proray deck
back onto the deck we pick cards from.
By the way, if you haven't seen this before: the
for my $i ( 0 .. $rnd_index - 1 ) {
is a for look running from 0 up to '$rnd_index - 1', that's
what the two dots are good for.
Of course, the above code, deals only with the very first card
we remove from the '@startingdeck' array. And it's a bit longish.
Let's first see how we can make this a llop that deals with
all the cards.
When we use
my $rnd_index = int( rand( 52 ) );
we obviously assume that there are 52 cards in the '@startingdeck'
array. But after we've removed on card only 51 one are left. It
probably would make sense to get rid of the '52' and put some-
thing there that is the actual length of '@startingdeck'. And
this is quite simple, just use
my $rnd_index = int( rand( @startingdeck ) );
The trick here is that, when in a number is expected in a certain
place, writing '@arrayname' gives you the number of elements in the
array. And the rand() function expects a number, so we're on the
safe side here. Shouldn't you be certain if a number is expected
than you can always make sure by putting 'scalar' in front of it:
my $rnd_index = int( rand( scalar @startingdeck ) );
With this we now can create a look that deals with all cards:
my @shuffled;
while ( scalar @startingdeck ) {
my $rnd_index = int( rand( scalar @startingdeck) );
my @temp;
for my $i ( 0 .. $rnd_index - 1 ) {
push @temp, shift @startingdeck;
}
push @shuffled, shift @startingdeck;
for my $i ( 0 .. $rnd_index - 1 ) {
unshift @startingdeck, pop @temp;
}
}
Well, that works but is rather long and a bit convoluted.
One way to condense it a bit is to use array slices. When
you write e.g.
@startingdeck[ 6 .. 19 ]
you get a new array containg the elements of '@startingdeck'
starting with index 6 and ending with index 19 (note again the
use of the '..' operator). Another nice feature is that you can
combine two arrays rather easily:
my @a = ( 1, 2, 3 );
my @b = ( 4, 5 );
my @c = ( @a, @b );
After this '@c' will contain 5 elements, first the ones from '@a',
then those from '@b'.
Using that we can write
my @shuffled;
while ( @startingdeck ) {
my $rnd_index = int( rand( @startingdeck) );
push @shuffled, $startingdeck[ $rnd_index ];
@startingdeck = ( @startingdeck[ 0 .. $rnd_index - 1 ],
@startingdeck[ $rnd_index + 1 .. @startingdeck - 1 ] );
}
Now, that's already quite a bit shorter and not really much harder
to understand, isn't it?
But we can make it even shorter. There's another function for
arrays, calles splice(), which allows you to remove (or insert)
elements somewehere within an array. E.g.
splice( @startingdeck, 5, 7 )
removes 7 elements from '@startindeck', starting at index 5, and
it returns the removed elements. We can use this to remove the
random card from '@startingdeck' and, at the same time, put it
onto the '@shuffled' array:
my @shuffled;
while ( @startingdeck ) {
my $rnd_index = int( rand( @startingdeck) );
push @shuffled, splice( @startingdeck, $rnd_index, 1 );
}
And, if you feel like it, you can condense the whole loop down
to a single line of code:
push @shuffled, splice @startingdeck, int rand @startingdeck, 1
while @startingdeck;
(You may notice that a lot of parentheses are optional.)
About printing the first 5 element of '@shuffled': there's
nothing wrong with using
my $i = 0;
while ( $i < 5 ) {
print $shuffled[ i ], " ";
}
print "\n\n";
But there are also ways to shorthen this a bit, e.g.
print join( " ", @shuffled[ 0 .. 4 ] ), "\n\n";
So, taking it all together, your whole assigment can done in
just three lines of code;-)
my @shuffled;
push @shuffled, splice @startingdeck, int rand @startingdeck, 1
while @startingdeck;
print join( "\n", @shuffled[ 0 .. 4 ] ), "\n\n";
But, of course, it doesn't fit the requirement to use just
push, pop and shift...
> # separate the hearts and organize them in order
> my $i = 0;
> while ($i < 13){
> @hearts[$i] = shift(@startingdeck);
> $i++;
> }
> $ace = shift(@hearts);
> push(@hearts, $ace);
> # separate the diamonds and organize them in order
> my $i = 0;
> while ($i < 13){
> @diamonds[$i] = shift(@startingdeck);
> $i++;
> }
> $ace = shift(@diamonds);
> push(@diamonds, $ace);
> # separate the clubs and organize them in order
> my $i = 0;
> while ($i < 13){
> @clubs[$i] = shift(@startingdeck);
> $i++;
> }
> $ace = shift(@clubs);
> push(@clubs, $ace);
> # separate the spades and organize them in order
> my $i = 0;
> while ($i < 13){
> @spades[$i] = shift(@startingdeck);
> $i++;
> }
> $ace = shift(@spades);
> push(@spades, $ace);
You probably have noticed that you do the same thing again
and again. These are the things were it's a good idea to
stop and consider if there's no way to avoid that...
> # put the organized cards back in the starting deck
> push (@startingdeck, @hearts, @diamonds, @clubs, @spades);
> # sort the suits in reverse high order stating with ace, kings, etc.
> my $i = 0;
> while ($i < 51){
> @sorted[$i] = pop(@hearts); $i++;
> @sorted[$i] = pop(@diamonds); $i++;
> @sorted[$i] = pop(@clubs); $i++;
> @sorted[$i] = pop(@spades); $i++;
> }
> # print the top 5 highest cards
> print "\nThe top five cards are: \n\n";
> my $i = 0;
> while ($i < 5){
> print "@sorted[$i], ";
> $i++;
> }
> print "\n\n";
As said there's a lot of redundancy in your code and you
actually don't seem to need the @hearts, @diamonds etc.
arrays except for tempory storage. And there's a clear
sign when a new suite starts, the last character from
the elment of @startingdeck changes from 'H' to 'D' to
'C' and finally 'S'. This can be used:
my @sorted, @temp;
while ( @startingdeck ) {
my @array;
my $char = substr( $startingdeck[ 0 ], -1 );
# Push all elements from @startingdeck that have the same
# character at the end onto an array
push @array, shift @startingdeck
while @startingdeck && substr( $startingdeck[ 0 ] eq $char;
# Move the first element to the end
push @array, shift @array;
# Append the result to @temp and the reversed result to @sorted
push @temp, @array;
push @sorted, reverse @array;
}
# @startingdeck (now empty) is supposed to be just a copy of @temp
@startingdeck = @temp;
print join( " ", @sorted[ 0 .. 4 ] ), "\n\n";
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
------------------------------
Date: Mon, 24 Feb 2014 16:46:15 +0200
From: Marius Gavrilescu <marius@ieval.ro>
Subject: Re: use strict; use warnings;
Message-Id: <871tysin60.fsf@ieval.ro>
Justin C <justin.1401@purestblue.com> writes:
> 'tis legible now. We don't know what software the OP is using,
The OP is using Pan 0.135, which understands MIME.
> I always prefer to send (and receive) something that everyone
> can read than something that relies on having the correct soft-
> ware for it to be readable.
Fortunately, MIME tends to be quite readable even without any extra
software, especially when the encoded text does not contain lines that
end with a space, non-ASCII characters, or = characters (my post
unfortunately contained all of these).
> Sorry if I came across as a plain-text pedant, I didn't mean
> to. Please accept my apologies. I put it down to it being early
> Monday morning, and an insufficient quantity of caffein.
No problem :-)
--
Marius Gavrilescu
------------------------------
Date: Mon, 24 Feb 2014 15:24:08 +0000
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: use strict; use warnings;
Message-Id: <op4sta-6352.ln1@anubis.morrow.me.uk>
Quoth Justin C <justin.1401@purestblue.com>:
> On 2014-02-24, Marek Novotny <mach2@hushmail.com> wrote:
> > Hi group,
> >
> > Tonight I finished up another obj for my class. The class has not yet
> > started to learn about use strict; and use warnings;
>
> Maybe they haven't taught you yet, but they are best practice, and
> will catch most errors, it saves the regulars here from pointing out
> the obvious.
>
> Use them, and then strip them out before your tutor sees your code.
It's likely they also haven't been taught about 'my', so that would have
to go as well.
OTOH, any tutor who penalises a student for using features they haven't
been taught yet is not worth learning from. (Except in the specific case
of something like 'write an implementation of merge sort', where using
sort() would defeat the point of the assignment.)
Ben
------------------------------
Date: Mon, 24 Feb 2014 10:58:00 -0600
From: John Black <johnblack@nospam.com>
Subject: Re: use strict; use warnings;
Message-Id: <MPG.2d7536139f83a8bd9897b6@news.eternal-september.org>
In article <bn0pn5Fj34eU1@mid.individual.net>, janek_schleicher@yahoo.de says...
> my @startingdeck = ();
> foreach my $rang (2 .. 9, qw/T J Q K A/) {
> foreach my $color(qw/H D C S/) {
> push @startingdeck, "$rang $color";
> }
> }
> # Starting deck is now filled with a classic 52 card deck
Nice!
John Black
------------------------------
Date: Mon, 24 Feb 2014 10:58:02 -0600
From: Marek Novotny <mach2@hushmail.com>
Subject: Re: use strict; use warnings;
Message-Id: <NvGdnTfrEciH55bOnZ2dnUVZ_rKdnZ2d@supernews.com>
On Mon, 24 Feb 2014 08:37:06 +0200, Marius Gavrilescu wrote:
> Marek Novotny <mach2@hushmail.com> writes:
>
>> When I started to try to use the use strict and warnings, I got
>> warnings such as: Scalar value @diamonds[$i] better written as
>> $diamonds[$i] at ./
>> obj10.pl line 55.
>>
>> But the whole point of what I am doing is loading elements into an
>> array... So I wanted it as @diamonds, not $diamonds, and so on.
>
> In Perl, the tenth element of array @something is $something[10]. So the
> warnings are correct — you should write $diamonds[$i] instead of
> @diamonds[$i].
>
> Another problem is that you declare the $i variable multiple times. You
> should only declare it once, the first time you use it. You can also
> refactor
>
> my $i = 0;
> while ($i < 13){
> $spades[$i] = shift(@startingdeck);
> $i++;
> }
>
> to
>
> for (my $i = 0 ; $i < 13 ; $i++) {
> $spades[$i] = shift(@startingdeck);
> }
>
> Finally, there are several undeclared variables (@hearts, @diamonds,
> @spades, @clubs, @sorted, $ace).
>
> After fixing these three problems the code should run without warnings
> under use strict; use warnings;
Thank you, Marius.
I made all the changes you suggested and I it taught me something about
declaring @array and using $array[#]. That seems clear now. Thank you. I
had already submitted the code I showed you to the teacher. I have not
yet received comments back. It will be interesting to read what comments
I am given, if any.
Here is the revised code, which now works with use strict; and use
warnings;
#!/usr/bin/perl
# file: obj10.pl
# Objective 1:
# The pop function "pops" off the last element of an array
# and returns it. It works like this:
#
# $element = pop(@array);
#
# The shift function works the same way, but removes an element
# from the front of an array.
#
# Using pop, shift, push, and the starting code below, write a script
# that sufficiently "shuffles" a simulated deck of cards before printing
# the top five cards. Save this script in your home directory as
# obj10.pl.
#
# The goal of this objective is to familiarize yourself
# with these three functions while using loops and to use them
# together to rearrange the array but not a randomly shuffled array.
use strict;
use warnings;
# declared variables
my @startingdeck = 0;
my @hearts = 0;
my @diamonds = 0;
my @spades = 0;
my @clubs = 0;
my @sorted = 0;
my $i = 0;
my $ace = 0;
@startingdeck = ("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");
# separate the hearts and organize them in order
$i = 0;
while ($i < 13){
$hearts[$i] = shift(@startingdeck);
$i++;
}
$ace = shift(@hearts);
push(@hearts, $ace);
# separate the diamonds and organize them in order
$i = 0;
while ($i < 13){
$diamonds[$i] = shift(@startingdeck);
$i++;
}
$ace = shift(@diamonds);
push(@diamonds, $ace);
# separate the clubs and organize them in order
$i = 0;
while ($i < 13){
$clubs[$i] = shift(@startingdeck);
$i++;
}
$ace = shift(@clubs);
push(@clubs, $ace);
# separate the spades and organize them in order
$i = 0;
while ($i < 13){
$spades[$i] = shift(@startingdeck);
$i++;
}
$ace = shift(@spades);
push(@spades, $ace);
# put the organized cards back in the starting deck
push (@startingdeck, @hearts, @diamonds, @clubs, @spades);
# sort the suits in reverse high order stating with ace, kings, etc.
$i = 0;
while ($i < 51){
$sorted[$i] = pop(@hearts); $i++;
$sorted[$i] = pop(@diamonds); $i++;
$sorted[$i] = pop(@clubs); $i++;
$sorted[$i] = pop(@spades); $i++;
}
# print the top 5 highest cards
print "\nThe top five cards are: \n\n";
$i = 0;
while ($i < 5){
print "$sorted[$i], ";
$i++;
}
print "\n\n";
--
Marek Novotny
A member of the Linux Foundation
http://www.linuxfoundation.org
------------------------------
Date: Mon, 24 Feb 2014 11:06:57 -0600
From: Marek Novotny <mach2@hushmail.com>
Subject: Re: use strict; use warnings;
Message-Id: <NvGdnTbrEcis4ZbOnZ2dnUVZ_rIAAAAA@supernews.com>
On Mon, 24 Feb 2014 14:00:27 +0200, Marius Gavrilescu wrote:
> Justin C <justin.1401@purestblue.com> writes:
>
>> Marius, this isn't going to help, your reply is full of ...
>> The above could be part of the problem. Plain text works globally.
>
> Sorry, I assumed that every client was able to read MIME messages. I
> don't know how to make gnus send non-MIME messages. I've disabled the
> PGP signature for this message, maybe it will also disable MIME.
>
> As far as I know, slrn has the ability to process MIME messages with
> metamail. This may help you view MIME messages in the future.
>
> My previous article said:
>
> In Perl, the tenth element of array @something is $something[10]. So the
> warnings are correct — you should write $diamonds[$i] instead of
> @diamonds[$i].
>
> Another problem is that you declare the $i variable multiple times. You
> should only declare it once, the first time you use it. You can also
> refactor
>
> my $i = 0;
> while ($i < 13){
> $spades[$i] = shift(@startingdeck);
> $i++;
> }
>
> to
>
> for (my $i = 0 ; $i < 13 ; $i++) {
> $spades[$i] = shift(@startingdeck);
> }
>
> Finally, there are several undeclared variables (@hearts, @diamonds,
> @spades, @clubs, @sorted, $ace).
>
> After fixing these three problems the code should run without warnings
> under use strict; use warnings;
I really wasn't sure how the whole my thing works. I did a search for use
strict; last night while in bed, I have a kindle, with the learning perl
6th edition book and started to read up on this. It's in chapter 4 where
they introduce it.
The class I am in right now is actually an admin course. There is adm I,
II and III and then one final course on scripting, which is where some
basic perl is introduced. As soon as this is done I am going to take all
the 4 courses offered in Perl as a stand alone.
The first book they suggest as Learning Perl 6th Edition, so I have been
reading that a little as well. It also has a quiz or two at the end of
each chapter and I am just about done with chapter 3, which mentions the
topics of pop, push, shift and unshift. But the course I am in didn't
mention unshift yet. And likely they won't because it's moving so quickly
and just gives us a taste of perl. I really hope to finish this course
within the next week or two so I can move on to full-time perl only.
Thanks again!
--
Marek Novotny
A member of the Linux Foundation
http://www.linuxfoundation.org
------------------------------
Date: Mon, 24 Feb 2014 11:10:52 -0600
From: Marek Novotny <mach2@hushmail.com>
Subject: Re: use strict; use warnings;
Message-Id: <NvGdnTHrEciB4JbOnZ2dnUVZ_rKdnZ2d@supernews.com>
On Mon, 24 Feb 2014 08:31:47 +0100, Mart van de Wege wrote:
> Marek Novotny <mach2@hushmail.com> writes:
>
>
>> When I started to try to use the use strict and warnings, I got
>> warnings such as: Scalar value @diamonds[$i] better written as
>> $diamonds[$i] at ./
>> obj10.pl line 55.
>>
>> But the whole point of what I am doing is loading elements into an
>> array... So I wanted it as @diamonds, not $diamonds, and so on.
>>
> Yeah, this is a common mistake.
>
> Single elements of an @array are scalars themselves, so they are
> addressed as $elem[$index]. The @array[$number] syntax is used to take a
> *slice* of an array. This might work (it usually does), but can cause
> hard to find bugs.
>
> Mart
It's really good to see this. I'm actually glad I ran into this. I'll
remember this lesson for sure.
Thanks!
--
Marek Novotny
A member of the Linux Foundation
http://www.linuxfoundation.org
------------------------------
Date: Mon, 24 Feb 2014 11:14:00 -0600
From: Marek Novotny <mach2@hushmail.com>
Subject: Re: use strict; use warnings;
Message-Id: <NvGdnTDrEchF4JbOnZ2dnUVZ_rIAAAAA@supernews.com>
On Mon, 24 Feb 2014 07:35:31 +0000, Kaz Kylheku wrote:
> On 2014-02-24, Marek Novotny <mach2@hushmail.com> wrote:
>> Hi group,
>>
>> Tonight I finished up another obj for my class. The class has not yet
>> started to learn about use strict; and use warnings;
>>
>> I was given the following to solve:
>>
>> # Using pop, shift, push, and the starting code below, write a script #
>> that sufficiently "shuffles" a simulated deck of cards before printing
> ^^^^^^^^^^
>
> You implemented:
>
>> # sort the suits in reverse high order stating with ace, kings, etc.
> ^^^^
>>
>> my $i = 0;
>> while ($i < 51){
>> @sorted[$i] = pop(@hearts); $i++; @sorted[$i] = pop(@diamonds); $i
++;
>> @sorted[$i] = pop(@clubs); $i++; @sorted[$i] = pop(@spades); $i++;
>> }
>
> Nice as it is, your program doesn't implement the requirement of
> shuffling!
Yes, but just under that description the goal states:
# The goal of this objective is to familiarize yourself
# with these three functions while using loops and to use them
# together to rearrange the array but not a randomly shuffled array.
At first I read it as you did. And I killed an hour trying to think of
how to do this. Then I saw the paragraph here and it made me believe that
what was truly wanted is what I did. I have not received the comments
back at this time. So I don't know for sure. We'll see I guess. Hope I
got it right.
--
Marek Novotny
A member of the Linux Foundation
http://www.linuxfoundation.org
------------------------------
Date: Mon, 24 Feb 2014 11:16:14 -0600
From: Marek Novotny <mach2@hushmail.com>
Subject: Re: use strict; use warnings;
Message-Id: <NvGdnTPrEcjD45bOnZ2dnUVZ_rKdnZ2d@supernews.com>
On Mon, 24 Feb 2014 10:16:24 +0200, George Mpouras wrote:
> here is some shuffle fun
>
>
> #!/usr/bin/perl use strict;
> use warnings;
>
>
> my @array = qw/a b c e r/;
>
> for (my $i=0; $i<scalar @array/2; $i++) {
> push @array, shift @array}
>
> for (my $i=$#array; $i>0; $i -= 2) {
> my $l1 = pop @array;
> my $l2 = pop @array;
> unshift @array, $l2;
> unshift @array, $l1}
>
> print "@array"
A little more advanced than I totally understand but I'll study it. :-)
Thanks!
--
Marek Novotny
A member of the Linux Foundation
http://www.linuxfoundation.org
------------------------------
Date: Mon, 24 Feb 2014 11:32:59 -0600
From: Marek Novotny <mach2@hushmail.com>
Subject: Re: use strict; use warnings;
Message-Id: <NvGdnTLrEcjWH5bOnZ2dnUVZ_rIAAAAA@supernews.com>
On Mon, 24 Feb 2014 10:21:30 +0000, Justin C wrote:
> On 2014-02-24, Marek Novotny <mach2@hushmail.com> wrote:
>> Hi group,
>>
>> Tonight I finished up another obj for my class. The class has not yet
>> started to learn about use strict; and use warnings;
>
> Maybe they haven't taught you yet, but they are best practice, and will
> catch most errors, it saves the regulars here from pointing out the
> obvious.
>
> Use them, and then strip them out before your tutor sees your code. I've
> never heard of removing them breaking any code. [1]
No, they have not mentioned it. In the next set of courses I will be 100%
focused on Perl. I imagine it will then come up, and I am glad to have
this preview into it. There is some overlap as I am in an admin course
which has some introduction into Perl. And I will take a formal Perl
course as soon as I am done, which is actually quite soon. I am at the
very end of the course I am in now.
>> I was given the following to solve:
>
> [snipped]
>
> Have they taught you about random numbers yet? I can't see how it's
> possible to shuffle without random numbers.
No, no mention of random yet and I doubt I see it here. The next course
will start with an Introduction to Perl and I hope all of these issues
will come out in that course. The Learning Perl book at least starts to
mention use strict in chapter 4. I've read much of the prior chapters and
no random is mentioned there at those points either.
> However, you've been told to use pop, shift and push. Maybe you could
> create a new array, pushing cards into it that you've 'pop'ped and
> 'shift'ed from the old array in some pseudo random fashion? [2]
I kind of do that already. Part of this lesson was to print the top 5
cards. So my thought about this was how to assign a value to each card so
I could get the top five. But then as I looked at the array they gave us,
they were already mostly in order. As I read the lesson over and over
again it seemed to me that all they really wanted was for me to take
elements off the left or right of the array to shuffle it, but not in a
random way, and thus obtain my answer that way.
So as a result, I make 4 smaller arrays which are 2 3 4 5 6 7 8 9 10 J Q
K A essentially. And then I thought it would be much easier to get the
top 5 if I just take one from each until 5 are taken, assuming I can
arrange them in this way. So that's what I ended up setting out to do.
I also take the slightly shuffled cards and put them back into the
original deck. At first I thought I should print the reshuffled deck, but
there is no requirement for it. I just left the code there in case.
>> When I started to try to use the use strict and warnings, I got
>> warnings such as: Scalar value @diamonds[$i] better written as
>> $diamonds[$i] at ./
>> obj10.pl line 55.
>>
>> But the whole point of what I am doing is loading elements into an
>> array... So I wanted it as @diamonds, not $diamonds, and so on.
>
> @diamonds is the whole array, $diamonds[2] refers an array element.
>
> (the same works for hashes, but you probably haven't done those yet:
> %coffee is the whole hash, but $coffee{espresso} refers to a portion of
> data *in* the %coffee hash).
They did mention hashes for like one paragraph. And in Learning Perl I
learned use % to determine if a number is odd or even, which was one of
my prior lessons. This is the 12 or 13th obj I have had to do. When I
started posting I was on 8. I didn't count them all but I likely have 20
or less to do in all. Some chapters have multiples. Some don't.
> The @ and % refer to the whole. $ and [suffix] or {suffix} refer to a
> part for arrays and hashes respectively.
Yeah, no good detail like that yet. Likely in the next introduction
lessons which I look forward to.
>> I tried to make the code as simple to understand as possible.
>>
>> Anyone care to take a stab at what it would have to look like with the
>> use of strict and warnings so I can understand what I should be doing?
>
> That's a lot of work for grabbing the wrong end of the stick. :(
>
> Justin.
>
> 1. except:
> no warnings 'uninitialized';
> # and similar
> but you won't be using that without having been taught about 'use
> warnings' anyway).
>
> 2. Maybe something like:
> for (my $i = 0; $i < $size_of_array; $i++) {
> if ($i % 3) {
> push @new, shift @array;
> }
> else {
> push @new, pop @array;
> }
> }
> You might want to wrap all of that in another loop and run it a few
> times. It should give *the appearance* of a shuffled deck, but you
> can see it'll shuffle identically each time, so it's not a real
> shuffle - if running it more than once be sure to replace @array with
> @new each time or you'll shuffle the first array each time, and not
> the partly shuffled one!
I actually think they are using the wrong word in their description. They
say shuffle, but in the next paragraph say, 'not random'. So I'll await
comments and see I got the right or wrong idea. They could improve the
text. The chapter has nothing like this either, which is one thing I very
much dislike about this course. They make a great leap from what is shown
to what is asked of me. In contrast the Learning Perl book seems much
better to me. The quiz(s) at the end are absolutely based on what the
chapter discusses. Harder, but you have the tools to figure it out.
--
Marek Novotny
A member of the Linux Foundation
http://www.linuxfoundation.org
------------------------------
Date: Mon, 24 Feb 2014 11:37:57 -0600
From: Marek Novotny <mach2@hushmail.com>
Subject: Re: use strict; use warnings;
Message-Id: <NvGdnS3rEcjoHpbOnZ2dnUVZ_rKdnZ2d@supernews.com>
On Mon, 24 Feb 2014 15:24:08 +0000, Ben Morrow wrote:
> Quoth Justin C <justin.1401@purestblue.com>:
>> On 2014-02-24, Marek Novotny <mach2@hushmail.com> wrote:
>> > Hi group,
>> >
>> > Tonight I finished up another obj for my class. The class has not yet
>> > started to learn about use strict; and use warnings;
>>
>> Maybe they haven't taught you yet, but they are best practice, and will
>> catch most errors, it saves the regulars here from pointing out the
>> obvious.
>>
>> Use them, and then strip them out before your tutor sees your code.
>
> It's likely they also haven't been taught about 'my', so that would have
> to go as well.
Yeah, no mention of it. But I submitted it as you saw it. Can't wait to
hear comments back.
> OTOH, any tutor who penalises a student for using features they haven't
> been taught yet is not worth learning from. (Except in the specific case
> of something like 'write an implementation of merge sort', where using
> sort() would defeat the point of the assignment.)
>
> Ben
Sometimes they nitpick so I try to do just as instructed. When I was
taking DNS, I got the right answer, but didn't use the process they
described. And they just kept failing me over and over again and didn't
do much to answer my questions. It was so frustrating. I even bought a DNS
book and read it cover to cover and still didn't answer their question
the way they wanted.
--
Marek Novotny
A member of the Linux Foundation
http://www.linuxfoundation.org
------------------------------
Date: Mon, 24 Feb 2014 11:46:27 -0600
From: Marek Novotny <mach2@hushmail.com>
Subject: Re: use strict; use warnings;
Message-Id: <NvGdnSzrEcjuGJbOnZ2dnUVZ_rIAAAAA@supernews.com>
On Mon, 24 Feb 2014 10:49:21 +0000, Ben Morrow wrote:
> Quoth Marek Novotny <mach2@hushmail.com>:
>>
>> my $i = 0;
>> while ($i < 13){
>> @hearts[$i] = shift(@startingdeck);
>> $i++;
>> }
>
> Perl arrays already know how long they are: you don't need to count for
> yourself. You may not have covered this, but using an array in scalar
> context, for example by comparing it to a number, will use the length of
> the array. So:
>
> while (@hearts < 13) {
> push @hearts, shift @startingdeck;
> }
Okay this is very interesting. I'll test this so I can see it with my own
eyes, but this would be great. Thank you!!
>> # put the organized cards back in the starting deck
>>
>> push (@startingdeck, @hearts, @diamonds, @clubs, @spades);
>
> Why did you include this step? What does it do for you?
The first time I read the objective I interpreted it as a reshuffle. Then
reading the second part of it I changed my view of what was being asked.
Originally I thought they wanted to see the reshuffled deck and print the
top 5 cards. I left that code there in case they ask to see the
reshuffled deck.
>> # sort the suits in reverse high order stating with ace, kings, etc.
>>
>> my $i = 0;
>> while ($i < 51){
>> @sorted[$i] = pop(@hearts); $i++; @sorted[$i] = pop(@diamonds); $i
++;
>> @sorted[$i] = pop(@clubs); $i++; @sorted[$i] = pop(@spades); $i++;
>> }
>
> Have you learned about 'reverse' yet? If not:
Yes, they did show a fairly okay example of reverse. We had to take /etc/
passwd and reverse all of the fields. We used split as well.
> push @sorted, pop @hearts while @hearts;
>
> or if you'd rather
>
> while (@hearts) {
> push @sorted, pop @hearts;
> }
>
> This isn't exactly 'shuffled', though I suppose you've done quite a bit
> of array manipulation, which was maybe the point. If I were given this
> assignment I might try to emulate something more like an overhand
> shuffle, so:
>
> - Pull some number of cards (say, 15) off the top of the deck into a
> new array @hand. Make sure to keep them in order (and don't use
> splice, that's presumably cheating :) ).
I read about splice in the Learning Perl book and it was actually my
first thought of how to solve this. But they said to use pop, push and
shift so I threw that idea out.
> - Transfer them back onto the bottom of the deck, starting with the
> card at the bottom of @hand.
They also mention that the shuffle not be random.
> If you're feeling ambitious you might want to try dropping them from
> your 'hand' back into the 'deck' in groups of two or three. At the point
> you're at now this will mean a third @drop array to temporarily hold the
> cards 'in flight' between @hand and @deck.
>
> Ben
Thanks Ben!!
--
Marek Novotny
A member of the Linux Foundation
http://www.linuxfoundation.org
------------------------------
Date: Mon, 24 Feb 2014 11:50:32 -0600
From: Marek Novotny <mach2@hushmail.com>
Subject: Re: use strict; use warnings;
Message-Id: <NvGdnS_rEcj1G5bOnZ2dnUVZ_rKdnZ2d@supernews.com>
On Mon, 24 Feb 2014 12:45:34 +0100, Janek Schleicher wrote:
> Am 24.02.2014 06:31, schrieb Marek Novotny:
>> ...
>> @startingdeck = ("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");
> > ...
>
> Beside your problem you asked,
> one important lesson in programming is to avoid to reapeat yourself,
> as we are lazy :-) and more important it would be heart to maintain
> (change or update your program in future).
> Just imagine here, you might also play with a double deck or with jokers
> or without deuces (or you'd prefer to have an other starting deck order
> of cards), than with this way, you would have to copy+paste and replace
> it manually with a lot of keystrokes. Not only is this boring, more
> important, it is easy to make a mistake doing so.
>
> Here a nice and simple way that also fits into your course (working with
> arrays and loops would be) [untested]:
>
> my @startingdeck = ();
> foreach my $rang (2 .. 9, qw/T J Q K A/) {
> foreach my $color(qw/H D C S/) {
> push @startingdeck, "$rang $color";
> }
> }
> # Starting deck is now filled with a classic 52 card deck
>
> So it's easy to read, short to write and easy to change,
> and most important you Don't Repeat Yourself (DRY-principle).
Thank you! Ideally I wanted to do something like this. I had no idea how.
I'll study your code and I thank you!!
> Greetings,
> Janek
>
> PS: You problably don't know yet what this qw/../ operator means,
> here it's just a short cut for qw/H D C S/ is the same as ("H", "D",
> "C", "S").
That they did cover. For whatever reason I like @array = qw( elem1
elem2 ...) but I see everyone here has adopted qw/elem1 elem2/. I could
easily adapt to this instead. For whatever reason the first is easier for
to remember and think of.
Thank you!
--
Marek Novotny
A member of the Linux Foundation
http://www.linuxfoundation.org
------------------------------
Date: Mon, 24 Feb 2014 11:52:38 -0600
From: John Bokma <john@castleamber.com>
Subject: Re: use strict; use warnings;
Message-Id: <871tys9z4p.fsf@castleamber.com>
Ben Morrow <ben@morrow.me.uk> writes:
> Perl arrays already know how long they are: you don't need to count for
> yourself. You may not have covered this, but using an array in scalar
> context, for example by comparing it to a number, will use the length of
> the array. So:
>
> while (@hearts < 13) {
> push @hearts, shift @startingdeck;
> }
or:
@hearts = splice @startingdeck, 0, 13;
See perldoc -f splice
--
John Bokma j3b
Blog: http://johnbokma.com/ Perl Consultancy: http://castleamber.com/
Perl for books: http://johnbokma.com/perl/help-in-exchange-for-books.html
------------------------------
Date: Mon, 24 Feb 2014 11:58:02 -0600
From: Marek Novotny <mach2@hushmail.com>
Subject: Re: use strict; use warnings;
Message-Id: <NvGdnS7rEci3FZbOnZ2dnUVZ_rIAAAAA@supernews.com>
On Mon, 24 Feb 2014 14:23:20 +0000, Jens Thoms Toerring wrote:
> Marek Novotny <mach2@hushmail.com> wrote:
>> Hi group,
>
>> Tonight I finished up another obj for my class. The class has not yet
>> started to learn about use strict; and use warnings;
>
>> I was given the following to solve:
>
>> # Objective 1:
>> # The pop function "pops" off the last element of an array # and
>> returns it. It works like this:
>> #
>> # $element = pop(@array);
>> #
>> # The shift function works the same way, but removes an element # from
>> the front of an array.
>> #
>> # Using pop, shift, push, and the starting code below, write a script #
>> that sufficiently "shuffles" a simulated deck of cards before printing
>> # the top five cards. Save this script in your home directory as #
>> obj10.pl.
>> #
>> # The goal of this objective is to familiarize yourself # with these
>> three functions while using loops and to use them # together to
>> rearrange the array but not a randomly shuffled array.
>
>> @startingdeck = ("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");
>
>> And here is my solution, which does not include the use of use strict;
>> and use warnings;
>
> This isn't the solution asked for - you're supposed to shuffle the
> array, not sort it. What's the most simple way to shuffle a deck of
> cards? Just remove a random card from the deck and put it on a new heap
> and repeat this until there are no more cards in the deck you started
> with. And you can shuffle your array in exactly the same way when you
> think about it.
I'm actually not so sure at this time. I personally think they just used
poor wording. I am awaiting comments back.
> The first question is, of course, how to pick a card at random. Perl has
> a nice function called 'rand' for this (if you haven't yet please read
> the documentation for it, all you've got to do is type "perldoc -f rand"
> in your terminal and you get the do- cumentation.
They have not yet taught anything about random and specifically state
that this is NOT random.
> rand() returns a floating point number. If called without an argument
> (or with 0 or 1) it's a floating point number between 0 and less than 1.
> If you give it any other argument it returns a random number between 0
> and less than the argument. But what we need is an integer number we can
> use as an index into our array. That's were the int() function comes
> handy, which strips of the fractional part of a floating point number.
>
> Now, since you start with 52 cards, you would use
>
> my $rnd_index = int( rand( 52 ) );
>
> rand() will return a number between 0 and less than 52, and int() will
> make sure that it's an integer bewteen 0 and 51.
> Thus the result is suitable for accessing one of the elements of your
> array '@startingdeck' and we can put the value of that element into a
> new array named '@shuffled'. But we also have to remove the "card" from
> the "deck", i.e. the element from the array. In a very pedestrian way we
> could do it like this
>
> my @shuffled;
>
> my $rnd_index = int( rand( 52 ) );
>
> my @temp;
>
> for my $i ( 0 .. $rnd_index - 1 ) {
> push @temp, shift @startingdeck;
> }
>
> push @shuffled, shift @startingdeck;
>
> for my $i ( 0 .. $rnd_index - 1 ) {
> unshift @startingdeck, pop @temp;
> }
This is also something I wanted to learn to do. I'll have to study your
code.
> As you can see we first move all cards before the one we randomly
> selected to a "temporary deck". Then we move the card we're interested
> in to our deck of shuffled cards. An then we put the cards we had stored
> on the temporary deck back onto the deck we pick cards from.
>
> By the way, if you haven't seen this before: the
>
> for my $i ( 0 .. $rnd_index - 1 ) {
>
> is a for loop running from 0 up to '$rnd_index - 1', that's what the two
> dots are good for.
I've seen them, but not quit this way. I've seen it used like 1..9 for 1
through 9. Yours is more advanced.
> Of course, the above code, deals only with the very first card we remove
> from the '@startingdeck' array. And it's a bit longish. Let's first see
> how we can make this a loop that deals with all the cards.
>
> When we use
>
> my $rnd_index = int( rand( 52 ) );
>
> we obviously assume that there are 52 cards in the '@startingdeck'
> array. But after we've removed on card only 51 one are left. It probably
> would make sense to get rid of the '52' and put some- thing there that
> is the actual length of '@startingdeck'. And this is quite simple, just
> use
>
> my $rnd_index = int( rand( @startingdeck ) );
>
> The trick here is that, when in a number is expected in a certain place,
> writing '@arrayname' gives you the number of elements in the array. And
> the rand() function expects a number, so we're on the safe side here.
> Shouldn't you be certain if a number is expected than you can always
> make sure by putting 'scalar' in front of it:
>
> my $rnd_index = int( rand( scalar @startingdeck ) );
>
> With this we now can create a look that deals with all cards:
>
> my @shuffled;
>
> while ( scalar @startingdeck ) {
> my $rnd_index = int( rand( scalar @startingdeck) );
> my @temp;
>
> for my $i ( 0 .. $rnd_index - 1 ) {
> push @temp, shift @startingdeck;
> }
>
> push @shuffled, shift @startingdeck;
>
> for my $i ( 0 .. $rnd_index - 1 ) {
> unshift @startingdeck, pop @temp;
> }
> }
>
> Well, that works but is rather long and a bit convoluted.
> One way to condense it a bit is to use array slices. When you write e.g.
>
> @startingdeck[ 6 .. 19 ]
>
> you get a new array containg the elements of '@startingdeck' starting
> with index 6 and ending with index 19 (note again the use of the '..'
> operator). Another nice feature is that you can combine two arrays
> rather easily:
>
> my @a = ( 1, 2, 3 );
> my @b = ( 4, 5 );
> my @c = ( @a, @b );
>
> After this '@c' will contain 5 elements, first the ones from '@a', then
> those from '@b'.
>
> Using that we can write
>
> my @shuffled;
>
> while ( @startingdeck ) {
> my $rnd_index = int( rand( @startingdeck) );
>
> push @shuffled, $startingdeck[ $rnd_index ];
> @startingdeck = ( @startingdeck[ 0 .. $rnd_index - 1 ],
> @startingdeck[ $rnd_index + 1 .. @startingdeck -
> 1 ] );
> }
>
> Now, that's already quite a bit shorter and not really much harder to
> understand, isn't it?
>
> But we can make it even shorter. There's another function for arrays,
> calles splice(), which allows you to remove (or insert) elements
> somewehere within an array. E.g.
>
> splice( @startingdeck, 5, 7 )
>
> removes 7 elements from '@startindeck', starting at index 5, and it
> returns the removed elements. We can use this to remove the random card
> from '@startingdeck' and, at the same time, put it onto the '@shuffled'
> array:
>
> my @shuffled;
>
> while ( @startingdeck ) {
> my $rnd_index = int( rand( @startingdeck) );
> push @shuffled, splice( @startingdeck, $rnd_index, 1 );
> }
>
> And, if you feel like it, you can condense the whole loop down to a
> single line of code:
>
> push @shuffled, splice @startingdeck, int rand @startingdeck, 1
> while @startingdeck;
>
> (You may notice that a lot of parentheses are optional.)
>
> About printing the first 5 element of '@shuffled': there's nothing wrong
> with using
>
> my $i = 0;
> while ( $i < 5 ) {
> print $shuffled[ i ], " ";
> }
> print "\n\n";
>
> But there are also ways to shorthen this a bit, e.g.
>
> print join( " ", @shuffled[ 0 .. 4 ] ), "\n\n";
>
> So, taking it all together, your whole assigment can done in just three
> lines of code;-)
>
> my @shuffled;
> push @shuffled, splice @startingdeck, int rand @startingdeck, 1
> while @startingdeck;
> print join( "\n", @shuffled[ 0 .. 4 ] ), "\n\n";
>
> But, of course, it doesn't fit the requirement to use just push, pop and
> shift...
>
>> # separate the hearts and organize them in order
>
>> my $i = 0;
>> while ($i < 13){
>> @hearts[$i] = shift(@startingdeck); $i++;
>> }
>> $ace = shift(@hearts);
>> push(@hearts, $ace);
>
>> # separate the diamonds and organize them in order
>
>> my $i = 0;
>> while ($i < 13){
>> @diamonds[$i] = shift(@startingdeck);
>> $i++;
>> }
>> $ace = shift(@diamonds);
>> push(@diamonds, $ace);
>
>> # separate the clubs and organize them in order
>
>> my $i = 0;
>> while ($i < 13){
>> @clubs[$i] = shift(@startingdeck); $i++;
>> }
>> $ace = shift(@clubs);
>> push(@clubs, $ace);
>
>> # separate the spades and organize them in order
>
>> my $i = 0;
>> while ($i < 13){
>> @spades[$i] = shift(@startingdeck); $i++;
>> }
>> $ace = shift(@spades);
>> push(@spades, $ace);
>
> You probably have noticed that you do the same thing again and again.
> These are the things were it's a good idea to stop and consider if
> there's no way to avoid that...
>
>> # put the organized cards back in the starting deck
>
>> push (@startingdeck, @hearts, @diamonds, @clubs, @spades);
>
>> # sort the suits in reverse high order stating with ace, kings, etc.
>
>> my $i = 0;
>> while ($i < 51){
>> @sorted[$i] = pop(@hearts); $i++; @sorted[$i] = pop(@diamonds);
>> $i++; @sorted[$i] = pop(@clubs); $i++; @sorted[$i] =
>> pop(@spades); $i++;
>> }
>
>> # print the top 5 highest cards
>
>> print "\nThe top five cards are: \n\n";
>
>> my $i = 0;
>> while ($i < 5){
>> print "@sorted[$i], ";
>> $i++;
>> }
>> print "\n\n";
>
> As said there's a lot of redundancy in your code and you actually don't
> seem to need the @hearts, @diamonds etc.
> arrays except for tempory storage. And there's a clear sign when a new
> suite starts, the last character from the elment of @startingdeck
> changes from 'H' to 'D' to 'C' and finally 'S'. This can be used:
>
> my @sorted, @temp;
>
> while ( @startingdeck ) {
> my @array;
> my $char = substr( $startingdeck[ 0 ], -1 );
>
> # Push all elements from @startingdeck that have the same #
> character at the end onto an array
>
> push @array, shift @startingdeck
> while @startingdeck && substr( $startingdeck[ 0 ] eq $char;
>
> # Move the first element to the end
>
> push @array, shift @array;
>
> # Append the result to @temp and the reversed result to @sorted
>
> push @temp, @array;
> push @sorted, reverse @array;
> }
>
> # @startingdeck (now empty) is supposed to be just a copy of @temp
>
> @startingdeck = @temp;
>
> print join( " ", @sorted[ 0 .. 4 ] ), "\n\n";
>
> Regards, Jens
I'll have to work up to this. It is advanced for where I am at this
point. My experience with Perl is roughly a week or 10 days so far. I'm
really just getting started. I need to think really small happy thoughts
for now. That code overwhelms me. :-(
Thanks for sharing it though.
--
Marek Novotny
A member of the Linux Foundation
http://www.linuxfoundation.org
------------------------------
Date: Mon, 24 Feb 2014 12:08:49 -0600
From: Marek Novotny <mach2@hushmail.com>
Subject: Re: use strict; use warnings;
Message-Id: <NvGdnSnrEcgsF5bOnZ2dnUVZ_rKdnZ2d@supernews.com>
On Mon, 24 Feb 2014 11:52:38 -0600, John Bokma wrote:
> Ben Morrow <ben@morrow.me.uk> writes:
>
>> Perl arrays already know how long they are: you don't need to count for
>> yourself. You may not have covered this, but using an array in scalar
>> context, for example by comparing it to a number, will use the length
>> of the array. So:
>>
>> while (@hearts < 13) {
>> push @hearts, shift @startingdeck;
>> }
>
> or:
>
> @hearts = splice @startingdeck, 0, 13;
>
> See perldoc -f splice
Hi John,
The objective asked me to use pop, push and shift. No splice. He who
controls the splice, controls the universe! HA... Oh wait... ;-)
--
Marek Novotny
A member of the Linux Foundation
http://www.linuxfoundation.org
------------------------------
Date: Mon, 24 Feb 2014 12:16:23 -0600
From: John Bokma <john@castleamber.com>
Subject: Re: use strict; use warnings;
Message-Id: <87lhx08jgo.fsf@castleamber.com>
Marek Novotny <mach2@hushmail.com> writes:
> On Mon, 24 Feb 2014 11:52:38 -0600, John Bokma wrote:
>
>> Ben Morrow <ben@morrow.me.uk> writes:
>>
>>> Perl arrays already know how long they are: you don't need to count for
>>> yourself. You may not have covered this, but using an array in scalar
>>> context, for example by comparing it to a number, will use the length
>>> of the array. So:
>>>
>>> while (@hearts < 13) {
>>> push @hearts, shift @startingdeck;
>>> }
>>
>> or:
>>
>> @hearts = splice @startingdeck, 0, 13;
>>
>> See perldoc -f splice
>
> Hi John,
>
> The objective asked me to use pop, push and shift. No splice. He who
> controls the splice, controls the universe! HA... Oh wait... ;-)
Clear. pop, push, and shift (and unshift) are all sugared versions of
splice, which is good to know anyway, IMO
I wouldn't see the use of splice as a violation of the requirements, but
I am not your teacher ;-)
--
John Bokma j3b
Blog: http://johnbokma.com/ Perl Consultancy: http://castleamber.com/
Perl for books: http://johnbokma.com/perl/help-in-exchange-for-books.html
------------------------------
Date: Mon, 24 Feb 2014 18:12:57 +0000
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: use strict; use warnings;
Message-Id: <9mesta-li62.ln1@anubis.morrow.me.uk>
Quoth Marek Novotny <mach2@hushmail.com>:
>
Since you're learning, I will give you some general advice on good Perl
practice.
> # declared variables
>
> my @startingdeck = 0;
> my @hearts = 0;
> my @diamonds = 0;
> my @spades = 0;
> my @clubs = 0;
> my @sorted = 0;
> my $i = 0;
> my $ace = 0;
This sort of predeclaration is not good style in Perl, especially with
those initial values. You should in general not declare a variable until
you need it; usually this means you declare it at the point where you
have a sensible value to put in it, though sometimes you need to declare
a variable a little earlier than that.
0 is not a good initial value for a Perl variable. This is particularly
true of arrays (and hashes, when you get to them); a statement like
my @startingdeck = 0;
creates the array @startingdeck containing a single element with the
value 0, whereas what you want is an empty array. This can be created
with
my @startingdeck;
though, as I said before, it's better style to put the right value in is
straight away, like
my @startingdeck = ("A H", "2 H", ...);
A statement like
my $i = 0;
is less obviously wrong, but the number 0 is not quite 'neutral' in
Perl: if this variable is to be used as a string it now contains a
non-empty string, which is unhelpful. Perl has a special value called
'undef' which numifies as 0 and stringifies as the empty string; a
statement like
my $i;
leaves $i containing undef, which is a good initial value if you haven't
got anything better.
> $i = 0;
> while ($i < 13){
> $hearts[$i] = shift(@startingdeck);
> $i++;
> }
It's already been pointed out that this sort of loop can be better
written as the C-style for loop
for (my $i = 0; $i < 13; $i++) {
$hearts[$i] = shift @startingdeck;
}
This has the advantage that the variable $i doesn't exist outside the
loop, so there is no chance that you will pick it up by mistake later.
However, explicitly iterating over the indices of an array is not
usually necessary in Perl. As I said xthread, Perl arrays know how long
they are, so you can write this loop
my @hearts;
while (@hearts < 13) {
push @hearts, shift @startingdeck;
}
(This is one of the cases where you do need to declare a variable before
you use it, because declaring it inside the loop would not have the
desired effect. In fact, the normal Perl way to write this would be to
use the splice function, like this:
my @hearts = splice @startingdeck, 0, 13;
which grabs all 13 elements in one go without the need for a loop.)
> $i = 0;
This is bad practice. This use of $i is logically distinct from the use
you made of it in the previous loop, so it should be a different
variable. With a C-style for loop as above you would get a different
variable (which happened to also be called $i) every time.
Ben
------------------------------
Date: Mon, 24 Feb 2014 18:18:05 +0000
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: use strict; use warnings;
Message-Id: <tvesta-li62.ln1@anubis.morrow.me.uk>
Quoth Marek Novotny <mach2@hushmail.com>:
>
> They did mention hashes for like one paragraph. And in Learning Perl I
> learned use % to determine if a number is odd or even, which was one of
> my prior lessons.
% meaning 'modulus' is completely different from the % which introduces
a hash. It's important not to confuse the two (though, honestly, I don't
think that's a likely source of confusion for anyone).
Later on you will meet globs, which have a * sigil; again, this is not
related in any way to the use of * to mean multiplication.
Ben
------------------------------
Date: Mon, 24 Feb 2014 19:05:10 +0000
From: Rainer Weikusat <rweikusat@mobileactivedefense.com>
Subject: Re: use strict; use warnings;
Message-Id: <878ut072mx.fsf@sable.mobileactivedefense.com>
Marius Gavrilescu <marius@ieval.ro> writes:
> Marek Novotny <mach2@hushmail.com> writes:
>
>> When I started to try to use the use strict and warnings, I got warnings
>> such as: Scalar value @diamonds[$i] better written as $diamonds[$i] at ./
>> obj10.pl line 55.
>>
>> But the whole point of what I am doing is loading elements into an
>> array... So I wanted it as @diamonds, not $diamonds, and so on.
>
> In Perl, the tenth element of array @something is $something[10].
That would be the eleventh element. The tenth is $something[9].
------------------------------
Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin)
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>
Administrivia:
To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.
Back issues are available via anonymous ftp from
ftp://cil-www.oce.orst.edu/pub/perl/old-digests.
#For other requests pertaining to the digest, send mail to
#perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
#sending perl questions to the -request address, I don't have time to
#answer them even if I did know the answer.
------------------------------
End of Perl-Users Digest V11 Issue 4149
***************************************