Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
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 (Abbot) 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 (Abbot) 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 avoiding work at the Monastery: (7)
As of 2015-07-05 05:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (60 votes), past polls