Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Non-Repetitive Random Numbers

by Anonymous Monk
on Apr 05, 2013 at 05:34 UTC ( #1027065=perlquestion: print w/ replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks

I need to generate non-repetitive random numbers. I have looked into the rand() function but it gives repeating numbers. Searching for answers I came across script which implements it through a hash which is as follows:

sub rand_sam { my ($n,@n) = (shift,@_); return 0 unless ($n < scalar @n); my %seen = (); until (keys %seen == $samples) { $seen{$pop[rand @pop]}=1; } return(keys %seen); }

But could not understand the script. Please suggest ways to efficiently generate non repetitive random numbers(from 0 to 100000)..

THnx..

Comment on Non-Repetitive Random Numbers
Download Code
Re: Non-Repetitive Random Numbers
by 2teez (Priest) on Apr 05, 2013 at 05:42 UTC

    Please take a look at perl function srand.
    This function "seed" the rand function so that rand can produce a different sequence each time you run your program.

    If you tell me, I'll forget.
    If you show me, I'll remember.
    if you involve me, I'll understand.
    --- Author unknown to me
      Please take another look at the documentation you linked to.

      The docs for rand state that it "Automatically calls srand unless srand has already been called." It is not necessary to call srand manually and doing so may actually reduce the randomness of the sequence your receive. (If you call srand repeatedly, it will almost certainly do so.)

Re: Non-Repetitive Random Numbers
by Rahul6990 (Beadle) on Apr 05, 2013 at 05:54 UTC
Re: Non-Repetitive Random Numbers
by kcott (Abbot) on Apr 05, 2013 at 06:00 UTC

    Here's a technique to generate non-repetitive random numbers:

    $ perl -Mstrict -Mwarnings -E ' my @nums = 0 .. 100000; say splice @nums, int(rand @nums), 1 for 1 .. 10; '

    Sample output:

    10228 67730 84390 58034 22572 34234 43334 38920 5934 82290

    Depending on how you want to use this, you may need to check whether @nums becomes exhausted.

    The "script" you provided is only a subroutine. You don't show the context in which it is called; you don't show how the global variable $samples is declared or what sort of value(s) are assigned to it. An explanation of the "script" will actually require the script.

    -- Ken

      The full script is as follows:

      my @pop = (1..100); my $samples = 30; my @sample = rand_samp(30,@pop); print "@sample"; sub rand_samp { my ($n,@n) = (shift,@_); return 0 unless ($n < scalar @n);# see note below my %seen = (); until (keys %seen == $samples) { $seen{$pop[rand @pop]}=1; } return(keys %seen); }
Re: Non-Repetitive Random Numbers
by hdb (Parson) on Apr 05, 2013 at 06:33 UTC

    The List::Util module provides a function to shuffle a list which seems most suitable for the task.

    use strict; use warnings; use List::Util qw( shuffle ); my @random = shuffle 0..99999; print join "\n", @random[0..9];
Re: Non-Repetitive Random Numbers
by AnomalousMonk (Monsignor) on Apr 05, 2013 at 07:28 UTC

    I am by no means an initiate of the Dark Mysteries™ of random numbers (Update: see reply below of BrowserUk), but here's a possibly interesting use of an iterator:

    >perl -wMstrict -le "use List::Util qw(shuffle); ;; sub Iterator (&) { return $_[0]; } ;; sub rand_iter { my $total = shift; ;; my $random = [ shuffle 0 .. $total-1 ]; ;; return Iterator { my $n = shift; return if $n < 0 or $n > @$random; return splice @$random, 0, $n; } } ;; my $iter = rand_iter(9); ;; use Data::Dump; dd [ $iter->(0) ]; dd [ $iter->(5) ]; dd [ $iter->(4) ]; dd [ $iter->(1) ]; dd [ $iter->(2) ]; " [] [5, 4, 0, 2, 8] [7, 3, 6, 1] [] []
Re: Non-Repetitive Random Numbers
by FloydATC (Hermit) on Apr 05, 2013 at 12:45 UTC
    This is semantics, but random numbers may be repetitive or not, or they're not truly random. If what you really want is a sequence 1..100000 in random order then Perl can do that for you:
    use List::Util; @shuffled = List::Util::shuffle(1..100000);

    -- Time flies when you don't know what you're doing
Re: Non-Repetitive Random Numbers
by BrowserUk (Pope) on Apr 05, 2013 at 13:10 UTC

    The problem with most of the solutions offered is that they create a list the size of the range of numbers required (100,000) in order to obtain the sample of 30 values. Many compound that by additionally creating an array and a hash.

    Not so bad whilst the range is in the 100s of thousands but once you need a range in the 10s of millions or more, your going to run out of memory pretty quick in order to create those 30 values.

    This will produce as many unique values (in a random order) as you wish to fetch for any range upto 4 billion, whilst never consuming more than 512MB. (and considerably less for smaller ranges. eg. 0-100,000 will use < 13kB.)

    sub uniqRands { state $vec = ''; $vec = '' if @_ == 2; my $n; 1 while vec( $vec, $n = int( rand $_[0] ), 1 ); vec( $vec, $n, 1 ) = 1; return $n; } my @sample = map uniqRands( 100_000 ), 1 .. 30;

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    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.
      What, you're limited to 0..4294967295, this sucks!

      Just kidding, this solution is awesome :-)

      -- Time flies when you don't know what you're doing
Re: Non-Repetitive Random Numbers
by LanX (Canon) on Apr 05, 2013 at 14:08 UTC
    maybe I'm blind, but I'm missing the simplest approach ...

    DB<109> %seen=(); DB<110> $seen{int rand 10000}=1 while (keys %seen <10) DB<111> keys %seen => (4402, 3312, 9339, 1345, 3461, 9357, 1185, 4646, 6571, 1315)

    ... and I don't think it's less efficient than the others.

    Cheers Rolf

    ( addicted to the Perl Programming Language)

      That doesn't guarantee unique values. With the built-in rand/srand, it produces repeats within 30 picks for seeds:

      seed : no.of picks before repeat 89 : 12 178 : 17 485 : 9 504 : 14 555 : 22 662 : 16 688 : 23 761 : 19 766 : 18 920 : 26 936 : 25 943 : 19 955 : 17 982 : 14 1004 : 27 1032 : 19 1192 : 23 1200 : 9 1385 : 24 1427 : 17 1439 : 29 1459 : 22 1582 : 14 1593 : 22 1602 : 29 1668 : 12 1737 : 22 1924 : 29 1933 : 24 1969 : 18 2186 : 27 2261 : 12 2297 : 12 2380 : 18 2410 : 29 2660 : 25 2690 : 28 2733 : 24 2817 : 13 2863 : 4 2875 : 19 2964 : 28 3023 : 27 3052 : 9 3198 : 24 3208 : 23 3240 : 28 3292 : 16 3415 : 2 3529 : 26 3669 : 22 3692 : 29 3741 : 21 3754 : 13 3791 : 23 3805 : 28 3842 : 24 3854 : 8 3956 : 28 4077 : 27 4202 : 20 -- More --

      Testcase:

      #! perl -slw use strict; for my $i ( 1 .. 100000 ) { my %hash; srand $i; ++$hash{ int rand 100000 } == 2 and print "$i : ", scalar keys %ha +sh while keys %hash < 30; }

      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      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.
        I don't understand your point (and I'm too much in a hurry ATM to investigate your code)

        Keys of a hash are always unique, in my code collisions of random numbers are simply ignored.

        update

        > That doesn't guarantee unique values.

        maybe this is clearer:

        DB<107> $seen{int rand 10}=1 for 1 .. 1000000 => "" DB<108> keys %seen => (6, 3, 7, 9, 2, 8, 1, 4, 0, 5)

        update
        one could argue that the order of hash -keys isn't random but that wasn't part of the question.

        Otherwise thats a good occasion to use shuffle or pushing into an array (but this implies reseeding rand every time)

        Cheers Rolf

        ( addicted to the Perl Programming Language)

Re: Non-Repetitive Random Numbers
by pemungkah (Priest) on Apr 06, 2013 at 10:22 UTC

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (7)
As of 2014-08-27 09:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (235 votes), past polls