Beefy Boxes and Bandwidth Generously Provided by pair Networks DiBona
XP is just a number
 
PerlMonks  

Generating 2 unique random integers (So I can't pop a list...)

by uG (Scribe)
on Sep 11, 2008 at 04:53 UTC ( #710532=perlquestion: print w/ replies, xml ) Need Help??
uG has asked for the wisdom of the Perl Monks concerning the following question:

use List::Util 'shuffle'; my @numbers = (1..10); my $r1 = pop(shuffle(@numbers)); my $r2 = pop(shuffle(@numbers));
I get a pretty vague error (Unknown error) from the above code, but its from the pop's. I suppose thats because shuffle is returning a list (and therefore cannot be pop'd?). Whats an elegant way to get 2 unique random numbers between 1 and x? It seems like it involves an ugly amount of code to do such a trival task :(

Comment on Generating 2 unique random integers (So I can't pop a list...)
Download Code
Re: Generating 2 unique random integers (So I can't pop a list...)
by BrowserUk (Pope) on Sep 11, 2008 at 04:55 UTC

    Close:

    use List::Util 'shuffle'; my @numbers = shuffle(1..10); my $r1 = pop(@numbers); my $r2 = pop(@numbers);
    It seems like it involves an ugly amount of code to do such a trival task

    If you really want it more compact, and never need to go back for more:

    use List::Util 'shuffle'; my( $r1, $r2 ) = (shuffle 1..10)[ 0, 1 ];

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Generating 2 unique random integers (So I can't pop a list...)
by ikegami (Pope) on Sep 11, 2008 at 05:00 UTC
    ...which can be simplified to
    use List::Util 'shuffle'; my ($r1, $r2) = shuffle(1..10);

    No need for intermediary storage.

    Update: This was meant to be a reply to BrowserUk, whose node originally ended before the quoted text.

Re: Generating 2 unique random integers (So I can't pop a list...)
by salva (Monsignor) on Sep 11, 2008 at 06:56 UTC
    you don't need to shuffle the full array, just splice two random elements:
    # my @numbers = (1..10); oops, thanks RMGir! my @a = (1..10); my $r1 = splice @a, rand(@a), 1; my $r2 = splice @a, rand(@a), 1;
    update: splice can be an expensive operation as it has to move all the elements inside the array from the insertion point upwards (complexity O(N)).

    A more efficient approach is:

    sub pop_any (\@) { my $a = shift; my $r = int rand(@$a); @{$a}[$r, 0] = @{$a}[0, $r] if $r; shift @$a } my @a = (1..10); my $r1 = pop_any @a; my $r2 = pop_any @a;
      Probably OK most of the time, but no guarantee that $r1 and $r2 are different (OP asked for two unique random numbers).
        Not true. They will be unique. splice
      I think you mean:
      my @numbers = (1..10); my $r1 = splice @numbers, rand(@numbers), 1; my $r2 = splice @numbers, rand(@numbers), 1;
      @a was confusing me...

      Mike
Re: Generating 2 unique random integers (So I can't pop a list...)
by AnomalousMonk (Monsignor) on Sep 11, 2008 at 14:32 UTC
    And for even more randelicious shufflating, you can chain shuffles for double, triple, etc., shuffling:
    perl -wMstrict -MList::Util=shuffle -le "my ($r1, $r2) = shuffle shuffle shuffle 1 .. 10; print qq($r1 $r2); " 9 2

      Do you have any reason to believe that shuffling multiple times is better?

        You can't Shuffle Off to Buffalo with just one shuffle.
Re: Generating 2 unique random integers (So I can't pop a list...)
by tilly (Archbishop) on Sep 11, 2008 at 15:34 UTC
    Why create the temporary array?
    my $r1 = 1 + int(rand(10)); my $r2 = 1 + int(rand(10)); $r2 = 1 + int(rand(10)) while $r1 == $r2;

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://710532]
Approved by BrowserUk
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (13)
As of 2014-04-23 20:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (554 votes), past polls