Pathologically Eclectic Rubbish Lister PerlMonks

### Send x% of the users to A, the rest to B

by DreamT (Pilgrim)
 on Oct 26, 2012 at 10:20 UTC Need Help??
DreamT has asked for the wisdom of the Perl Monks concerning the following question:

Hi,
br> I have a task where i'm supposed to send a certain percentage of the users to one location, and the rest to another location.

I have an idea where I want to use the session key and modulus, but I don't know how to implement it. Some pseudocode:

```# 1. Convert every character to a number using ord?

# 2. ???

# 3. use modulus 100 on the converted string to get 1 or 0

if ((\$converted_string % 100) < \$percentage)
{
\$location = "new location";
}
else
{
\$location = "old location";
}

As you can see I'm quite clueless on this, but it's more of a mathematical problem than a code problem. I know that I need to do some calculations on the string before I can use modulus on it, but how?

Replies are listed 'Best First'.
Re: Send x% of the users to A, the rest to B
by BrowserUk (Pope) on Oct 26, 2012 at 10:58 UTC

This one-liner shows that if you use rand() < 0.5 to decide between locations -- even if the rand calls are in different invocations of perl -- the distribution will be fairly split:

```perl -E"{++\$t;\$r=`perl -E\"say rand()\"`;\$r<.5?++\$a:++\$b; printf qq[\r
+%.3f : %.3f], \$a*100/\$t, \$b*100/\$t; redo}"
49.350 : 50.650

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.
Cool snippet! Interesting to see that (at least on my Debian box) it takes a few dozen iterations to actually reach middle ground:
```perl -Mstrict -Mwarnings -E 'my \$WIDTH = 50;
my ( \$try, \$i, \$j ) = (0) x 3;
for ( 1 .. 40 ) {
++\$try;
my \$rand = `perl -E "say rand()"`;
\$rand < .5 ? ++\$i : ++\$j;
printf qq[%\${WIDTH}s : %s\n],
"#" x ( \$i * \$WIDTH / \$try ),
"#" x ( \$j * \$WIDTH / \$try );
}'
Interesting to see that ... it takes a few dozen iterations to actually reach middle ground:

That is the nature of randomness. If it was exactly 50:50, it wouldn't be random.

But the more trials you run, the closer it will tend. This is more evident if you run this version with various different resets:

```C:\test>perl
-E"{++\$t;\$r=`perl -E\"say rand()\"`;\$r<.5?++\$a:++\$b; printf qq[\r%.3f
+: %.3f], \$a*100/\$t, \$b*100/\$t; \$t>\$ARGV[0] and say and \$t=\$a=\$b=0; re
+do}" 10
45.455 : 54.545
27.273 : 72.727
36.364 : 63.636
54.545 : 45.455
72.727 : 27.273
63.636 : 36.364
36.364 : 63.636
45.455 : 54.545
27.273 : 72.727
36.364 : 63.636
72.727 : 27.273
45.455 : 54.545
54.545 : 45.455
63.636 : 36.364

C:\test>perl
-E"{++\$t;\$r=`perl -E\"say rand()\"`;\$r<.5?++\$a:++\$b; printf qq[\r%.3f
+: %.3f], \$a*100/\$t, \$b*100/\$t; \$t>\$ARGV[0] and say and \$t=\$a=\$b=0; re
+do}" 100
52.475 : 47.525
52.475 : 47.525
52.475 : 47.525
46.535 : 53.465
45.545 : 54.455
51.485 : 48.515
41.584 : 58.416
46.535 : 53.465
42.574 : 57.426
40.594 : 59.406

C:\test>perl
-E"{++\$t;\$r=`perl -E\"say rand()\"`;\$r<.5?++\$a:++\$b; printf qq[\r%.3f
+: %.3f], \$a*100/\$t, \$b*100/\$t; \$t>\$ARGV[0] and say and \$t=\$a=\$b=0; re
+do}" 1000
49.750 : 50.250
51.349 : 48.651
48.651 : 51.349
53.047 : 46.953

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.
Re: Send x% of the users to A, the rest to B
by choroba (Bishop) on Oct 26, 2012 at 10:24 UTC
Cannot you just decide based on rand 100 < \$percentage ?
لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
It would work - But I need to remember the choice per user. As I think of it, I could of course store the selection for the current session(user) instead:)

If you have only two locations, you probably don't need to convert the full session ID into an integer, but just a small part or it. I recently had to build a kind of hashing function for splitting my processing of a very large data chunk into 10 sub-processes. One of the mandatory IDs of my data was a telephone number. I simply used the last digit of the phone number to decide to which process to allocate a given record and obtained an excellent load balancing. The advantage is that the simpler the splitting function is, the less performance overhead you get.

Re: Send x% of the users to A, the rest to B
by talexb (Canon) on Oct 26, 2012 at 19:43 UTC

If a user can make multiple requests, and you always want to send a user to the same place, then hashing some user attribute and picking a destination based on that should work. For example, you could hash their username and look at the LSB of the result to decide where to send them.

Alex / talexb / Toronto

"Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds

Re: Send x% of the users to A, the rest to B
by Anonymous Monk on Oct 26, 2012 at 12:43 UTC
Are you simply trying to achieve a load-balancer? That's a device.

Create A New User
Node Status?
node history
Node Type: perlquestion [id://1001034]
Front-paged by Corion
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (4)
As of 2018-04-23 17:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
My travels bear the most uncanny semblance to ...

Results (85 votes). Check out past polls.

Notices?