How to not print the same random number
Anonymous Monk
created: 2006-03-04 04:17:44
Hello.
Can someone give an exemple on how to write a program that print random number between 1 and 10 and does this.

1. I want the resultat to print 10 random number between 1 and 10.

2. If the first random number is 7. The second random number is between 1 and 10 but not number 7. The third random number is between 1 and 10 but not number 7 and not the same number like the second number.

3. And so on until every 10 random number has been printed.

For example for the resultat.
7
4
10
3
2
6
8
9
1
5

//Clyde
Re: How to not print the same random number
created: 2006-03-04 04:21:17
Sounds like homework. I'll give you a hint. When you want to keep track of things you've seen, a hash is usually what you want.

You'll have a lot better luck getting help if you actually give it a go and post what you've got.

-Lee
"To be civilized is to deny one's nature."
Re: How to not print the same random number
created: 2006-03-04 05:28:12
Here is one way:
perl -MList::Util=shuffle -e 'print "@{[shuffle(1..10)]}"'
Boris
Re^2: How to not print the same random number
created: 2006-03-04 06:01:55
While fine for small ranges, won't that be a hog on larger number ranges?
update I understand that the poster is only looking for 1-10, just seemed the better way to teach. Opinions?

-Lee
"To be civilized is to deny one's nature."
Re^3: How to not print the same random number
created: 2006-03-04 06:05:53
Yes sure, the array with all numbers is build and shuffled. On the other hand, hash solutions require more memory and more cpu power they build the same array but slower. A hash is a better choice, if you use only some number out of a large range. For really really much numbers a database is my best choice.
Boris
Re^4: How to not print the same random number
created: 2006-03-04 06:08:56
That's what I figured. I haven't kept up lately, didn't know if some lazy evaluation had snuck in there ;)

-Lee
"To be civilized is to deny one's nature."
Re^3: How to not print the same random number
created: 2006-03-04 10:30:39

The question becomes "are you going to use all the numbers in that range?" If so, you have to remember them all regardless of your approach. If no, then you could save memory by just tracking what you use... but this then becomes more processor-expensive.

Re^4: How to not print the same random number
created: 2006-03-04 12:36:54
On the plus side, once you've "bought it", the cost is pretty much constant.

-Lee
"To be civilized is to deny one's nature."
Re^3: How to not print the same random number
created: 2006-03-05 02:53:35
Not much of a hog. Storing the numbers already picked in a hash would be about as bad. (I'm not sure how many copies of the list the shuffle approach will end up having.)

But anyway, if you go with what I understand to be your idea of repeatedly generating random numbers until you find one not yet in a hash, you'll end up taking a very very long time finding the last few numbers if the limit is, say, 1000000.

Re^4: How to not print the same random number
created: 2006-03-05 15:43:42
Well, I suppose I should have been more clear. I would think for many applications, the number of numbers picked compared to the number range would be relatively small.

So I guess the proper answer would be, "it depends".

-Lee
"To be civilized is to deny one's nature."
Re: How to not print the same random number
created: 2006-03-04 05:34:44
A more efficient way to achieve what you want, is just to shuffle an array.

To make the concept clear, let me compare to a deck of cards. How do you prevent from drawing the same card twice? By not putting the card back in the deck before you draw another one.

You get the same result by simply shuffling the deck, and picking the next card, one by one.

shuffle is a function you can find in [cpan://List::Util]. You use it like this:

use List::Util 'shuffle';
my @shuffled_deck = shuffle 1 .. 10;
local $\ = "\n";
foreach(@shuffled_deck) {
    print;
}
I get, for example, the following output:
1
2
9
8
7
10
4
5
6
3

It'll be far more efficient than retrying until you get something you haven't seen before, especially near the end, when you've almost seen them all.

Re: How to not print the same random number
created: 2006-03-04 05:39:17
Try this
use Data::Random qw(:all);
my @random_chars = rand_chars( set => 'numeric', min => 10, max => 10 );
foreach (@random_chars)
{print "$_\n";}
--C
Re: How to not print the same random number
created: 2006-03-04 05:39:17
Try this
use Data::Random qw(:all);
my @random_chars = rand_chars( set => 'numeric', min => 10, max => 10 );
foreach (@random_chars)
{print "$_\n";}
--C
Re: How to not print the same random number
created: 2006-03-04 06:02:16

This may give you what you want:

use strict;
use warnings;

print join"\n",grep$_,map{our%s;my$n=1+int rand(10);$s{$n}++?0:$n}1..100;

DWIM is Perl's answer to Gödel
Re^2: How to not print the same random number
created: 2006-03-05 02:56:28
I like the "may" part. Did you calculate the actual odds?
Re^3: How to not print the same random number
created: 2006-03-05 04:41:28

Statistics is not my strong suit. I ran a test version a few times and noticed that about 23-25 itterations sufficed often enough and guessed that 100 would seldom dissapoint. Glad you noticed the "may". :)


DWIM is Perl's answer to Gödel
Re: How to not print the same random number
created: 2006-03-04 06:05:16

or you could just pull numbers out at random then throw them away:

use strict;
use warnings;

my @numbers = 1..10;
print splice (@numbers, rand (@numbers), 1), "\n" while @numbers;

DWIM is Perl's answer to Gödel
Re: How to not print the same random number
created: 2006-03-04 06:46:33

If you're excluding numbers, it's not random. For example, if you've already chosen 9 numbers, the tenth is completely determined. FWIW.

Re: How to not print the same random number
created: 2006-03-04 10:12:29
The following should achieve pretty random results within the constraints you asked for - 10 unique numbers from 1-10 sorted randomly.
@arr = 1..10;
randomize(\@arr);

print "@arr";

sub randomize {
    my ($p, $size, $swap, $key);
    $p = $_[0];

    $size = $#$p;
    for (0..($size-1)) {
        $swap = int rand($size - $_ + 1) + $_;
        $key = $p->[$_];
        $p->[$_] = $p->[$swap];
        $p->[$swap] = $key;
    }
}
Re^2: How to not print the same random number
created: 2006-03-04 10:39:07
Hello.
Thanks for all the example.
If is not to much to ask but could you give me some explanation on what each codeline does?.

//Clyde
Re^3: How to not print the same random number
created: 2006-03-04 12:27:16
Using perlmonks for all your homework is how you expect to graduate?
Seriously, you better start learning because people won't always be this helpful.

/me readies himself for the possible -- to come


acid06
perl -e "print pack('h*', 16369646), scalar reverse $="
Re^2: How to not print the same random number
created: 2006-03-05 16:17:20

You can eliminate the manifest temporary by:

($p->[$_], $p->[$swap]) = ($p->[$swap], $p->[$_]);

Note though that it is slower:

use strict;
use warnings;
use Benchmark qw(cmpthese);

my @arr = 1..2;

cmpthese (-1,
            {
            temp => sub {my $temp = $arr[0]; $arr[0] = $arr[1]; $arr[1] = $temp;},
            swap => sub {($arr[0], $arr[1]) = ($arr[1], $arr[0]);},
            }
         );

          Rate swap temp
swap 1381331/s   -- -43%
temp 2425611/s  76%   --

DWIM is Perl's answer to Gödel
Re: How to not print the same random number
created: 2006-03-04 12:42:51
## Assign the numbers 1-10 to array @arr
@arr = 1..10;

## Pass @arr by reference to function randomize()
randomize(\@arr);

## When used in this context, the array prints
## with space delimiters between items
print "@arr";

sub randomize {
    ## Declare variables inside the scope of
    ## this function
    my ($p, $size, $swap, $key);

    ## Assign the array reference passed to
    ## the function to $p
    $p = $_[0];

    ## Assign the length of the array pointed
    ## to by $p to $size. This is the number
    ## of items in the array - 1
    $size = $#$p;

    ## Randomize all items up to the next to
    ## last item. The last item is randomized
    ## already if the other items are.
    for (0..($size-1)) {

        ## Pick a random item from current
        ## position to end
        $swap = int rand($size - $_ + 1) + $_;

        ## Swap item with current position
        $key = $p->[$_];
        $p->[$_] = $p->[$swap];
        $p->[$swap] = $key;
    }
}
You should probably look up $_ and @_ and read up on references, it will help you understand this a bit.

perlmonks.org content © perlmonks.org and acid06, Anonymous Monk, bart, borisz, cognizant, fishbot_v2, GrandFather, shotgunefx, spiritway, TedPride, ysth

prlmnks.org © 2006 edmund von der burg (eccles & toad)

v 0.03