106
votes
\$\begingroup\$

As a little joke in the office someone wanted a script that randomly picks a name, and said person will make a round of drinks.

Let's call the people John, Jeff, Emma, Steve and Julie.

I thought it would be funny to make a script that seems random at a quick glance, but actually always gives the same person as the output (Up to you who you choose).

Highest voted answer wins after a week

And the winner is....

Paul R with (currently) 158 votes.

The answers here are great, and if anyone else has any other ideas what haven't been posted yet, please add them, I love reading through them.

\$\endgroup\$
10
  • 44
    \$\begingroup\$ xkcd.com/221 \$\endgroup\$
    – AstroCB
    Jun 16, 2014 at 19:30
  • 6
    \$\begingroup\$ @AstroCB one of my favourites. Right behind bobby tables. \$\endgroup\$
    – Cruncher
    Jun 16, 2014 at 20:08
  • 50
    \$\begingroup\$ It seems like it would be sneakier if it was random, except for never picking one person. \$\endgroup\$ Jun 16, 2014 at 22:52
  • 6
    \$\begingroup\$ @AstroCB this one is also fantastic: dilbert.com/strips/comic/2001-10-25 \$\endgroup\$ Jun 18, 2014 at 10:08
  • 3
    \$\begingroup\$ I went through the first page: most answers always choose John, 2nd highest is Julie, Jeff is chosen rarely and Steve by 1. Even Ray got chosen by one but nobody chose Emma. Moral of the story: when standing in a line to decide randomly who will buy the drinks, name yourself Emma. \$\endgroup\$ Jul 15, 2014 at 19:33

65 Answers 65

4
votes
\$\begingroup\$

Java

Shh, don't tell anyone. Secretly call the second method in your code, then call the first method.

public String randomPerson() {
    String people[] = new String[]
    {"John", "Jeff", "Emma", "Steve", "Julie"};
    return people[Math.random()];
}

@SuppressWarnings("serial")
private void setUpRandomness() {
    try {
        Field field = Math.class.getDeclaredField("randomNumberGenerator"); 
        field.setAccessible(true);
        field.set(null, new Random() { 
            @Override
            public double nextDouble() {
                return 4; // chosen by fair dice roll.
            }             // guaranteed to be random.
        });               // Proof: http://xkcd.com/221/
    }
    catch (final SecurityException | NoSuchFieldException | IllegalArgumentException | IllegalAccessException e)
    { /* Ignore */ }
}
\$\endgroup\$
4
  • 2
    \$\begingroup\$ Cudos on the xkcd reference :) \$\endgroup\$
    – TMH
    Jun 17, 2014 at 7:56
  • 1
    \$\begingroup\$ This "random" number generator is not funny. Plus, Anubian Noob did this about 16 hours before you did. \$\endgroup\$
    – Kyle Kanos
    Jun 17, 2014 at 14:36
  • \$\begingroup\$ @KyleKanos I would argue that his script is not at all random while mine involves Math.random(), a Java standard method for getting a random double. \$\endgroup\$
    – Unihedron
    Jun 18, 2014 at 19:00
  • 1
    \$\begingroup\$ I am by no means even a capable Java programmer, but it seems to me that you are overriding Java's standard method of getting a random double and replacing it with a very tired joke. \$\endgroup\$
    – Kyle Kanos
    Jun 18, 2014 at 19:12
4
votes
\$\begingroup\$

Javascript

In order to make things as fair as possible, we'll simply outsource random-number generation to the random.org API. As you can see from this URL, the API can generate a random number between 0 and 4, inclusive, using extremely powerful entropy sources like atmospheric noise -- vastly superior to whatever your office laptop uses to generate /dev/random.

var xhr = new XMLHttpRequest();
xhr.open("GET",
    "http://www.random.org/integers/?num=1&min=0&max=4&col=1&base=10&format=plain&rnd=new");
xhr.send();

// convert string response to number
var index = +xhr.responseText;
var name = ["John", "Jeff", "Emma", "Steve", "Julie"][index];
alert(name);

There is a misuse of asynchronous Ajax code (a perennial Stack Overflow "favorite"). xhr.responseText is by default the empty string, and is not populated until the load event fires, so +"" is coerced to 0, leaving poor John to get drinks for everyone.

\$\endgroup\$
1
  • \$\begingroup\$ I had thought about doing exactly this, since it's a genuine common error for new programmers, and going to random.org is a perfect excuse. Might I suggest replacing +xhr.responseText with xhr.responseText|0 so that it looks even more like a reliable integer coercion? \$\endgroup\$
    – Keen
    Jun 24, 2014 at 19:57
3
votes
\$\begingroup\$

AWK

BEGIN {
    srand(n=split("John Jeff Emma Steve Julie.",A))
    print A[int(rand()*n+1)]
}

Sorry, Steve!!! :-P

Feeding srand() with a constant shall reproduce the same sequence of rand() values over and over again. On my system gawk and mawk selected Steve but this may not be globally immutable...

But now for something completely different with really seeding srand():

BEGIN {
    srand()
    split("John Jeff Emma Steve Julie.",A)
    print A[int(rand()+1)]
}

Sorry, John!

srand() really seeds the rand() as expected and rand()+1 looks like correctly taking care of the names are stored in A[1] and following indices but because rand() always is smaller than 1, int(rand()+1) always will be 1.

\$\endgroup\$
3
votes
\$\begingroup\$

Kona

> buyer:("john";"jeff";"emma";"steve";"julie")
> *buyer[4 _draw 1]
"john"

x _draw y returns x number of values between 0 and y-1. To the untrained eye, this dyad appears to be pulling 1 value in the range 0 to 4, rather than 4 values in the range 0. Thus, buyer[4 _draw 1] is a vector with 4 elements that are all "john" (who sadly, again, is buying for everyone); the leading * picks the first element of the vector.

\$\endgroup\$
3
votes
\$\begingroup\$

Java

In college, I was told that this would normally distributed.

public static void main(String[] args)
{
    String names = {"John", "Jeff", "Emma", "Steve", "Julie"};
    Random r = new Random();
    double res = Math.abs(r.nextGaussian()) * 0.5;
    int resInt = Math.min(names.length() - 1, (int) res);
    System.out.println(names[resInt]);
}

The nextGuassian() method picks a number from a pseudo normal distribution with mean 0 and standard deviation 1. So, basically the chances that it's not going to be John are 4.56%. Moreover, the chances it's going to be John or Jeff is approximately 100%.

\$\endgroup\$
5
  • \$\begingroup\$ So will it always choose John OR Jeff not only one or did I misunderstand? \$\endgroup\$
    – kitcar2000
    Jun 17, 2014 at 15:03
  • \$\begingroup\$ Yes, it's going to be John or Jeff, it will be 95.44% of the time John and 4.56% of the time is it going to be Jeff. \$\endgroup\$ Jun 17, 2014 at 15:21
  • \$\begingroup\$ Why are you taking the minimum? This looks suspicious. \$\endgroup\$
    – Bergi
    Jun 20, 2014 at 8:20
  • \$\begingroup\$ Because mathematically, a Gaussian random number kan be anything, even 1000000. So that's not what we want. \$\endgroup\$ Jun 25, 2014 at 22:42
  • \$\begingroup\$ I agree that it looks too suspicious. It can be anything, but you can't let people know that, and it will practically never by more than 4. If your code fails once every 20,000 runs, that's fine. So if you remove the min you should be okay. \$\endgroup\$ Aug 8, 2014 at 19:44
3
votes
\$\begingroup\$

Bash

#!/bin/bash
output="";
until [ -n "$output" ];do
output=`echo John Jeff Emma Steve Julie|sed 's/ /\n/'|shuf|head -n1|sed '/[^a-zA-Z]/d;'`;
done
echo $output

Portability

This isn't entirely portable. It works on Ubuntu 14.04 with GNU bash 4.3.11, GNU coreutils 8.21 and GNU sed 4.2.2. In OpenBSD, according to @kernigh, the \n escape in the regex replacements doesn't work properly, and shuf doesn't exist.

Explanation

This makes extra checks to ensure that its output is valid. It initialises a variable to the empty string, then obtains random names for it with a loop. The loop loops until the variable is not empty. Unless the name chosen in any iteration is valid (only contains letters a-z and A-Z), the variable is set to the empty string, causing the loop to run again.

So, if the large command in the loop produces invalid output, it is discarded, until valid output is produced. It is then printed.

The central command echoes the five names separated by spaces to sed 's/ /\n/', which turns the spaces into newlines to be passed to shuf, which shuffles the lines in its input (only operates on lines, hence the sed command is needed, head -n1, which takes the first one, and sed '/[^a-zA-Z]/d;', which discards any invalid input it receives.

The first sed command doesn't have the g switch; only one substitution is made. Then, there are only two options: John and Jeff Emma Steve Julie. The latter is discarded later on. Sorry, John.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ This one is not portable. Here with OpenBSD, sed 's/ /\n/' changes the first space to a literal n, because \n is only a newline in regular expressions, not in replacements. (I wonder if I can exploit this?) Also, there is no shuf command. So $output is always empty and this script enters an infinite loop, which is proof that the [ -n "$output" ] check is an essential part of the script. \$\endgroup\$
    – kernigh
    Jun 16, 2014 at 19:29
  • \$\begingroup\$ @kernigh Works fine on Ubuntu 14.04, GNU bash 4.3.11, GNU coreutils 8.21, GNU sed 4.2.2. shuf is in coreutils on my system. You could use sort -R instead of shuf, but it isn't quite the same (see manpages for details). \$\endgroup\$
    – user16402
    Jun 16, 2014 at 19:53
3
votes
\$\begingroup\$

C++

The idea is pretty simple: we generate n random numbers for each person (their score), add them together to get their total, and the person with the lowest total score has to buy the drinks. To be scrupulously fair, we generate the random numbers in n rounds, with each person taking turns to be the first to roll the dice.

#include <random>
#include <algorithm>
#include <iostream>

int main() {
    const char* names[] = {"John", "Jeff", "Emma", "Steve", "Julie"};
    constexpr unsigned int NumNames = std::extent<decltype(names)>::value;
    unsigned int total[NumNames] = {};

    std::random_device rd;  // Seed with a real random value
    std::default_random_engine e1(rd());
    for (unsigned int i = 0; i != NumNames; ++i) {
        unsigned int score[NumNames];
        std::generate(std::begin(score), std::end(score), e1);
        for (unsigned int j = 0; j != NumNames; ++j)
            total[(i + j) % NumNames] += score[j];  // Eliminate any bias
    }

    auto loser = names[std::distance(std::begin(total),
            std::min_element(std::begin(total), std::end(total)))];
    std::cout << loser << " buys the drinks!\n";
}

Explanation:

Unfortunately, std::generate takes its functor argument by value, not by reference, so modification to the internal state of the engine only affects the copy of e1 inside std::generate. That means that each time round the loop score is filled with the same sequence of values, so after the loop everyone has exactly the same total. When faced with a tie, std::min_element returns the first element with the minimum value, so John always buys the drinks!

This has resulted in real-world bugs: https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/nsGPpmEVOns/overview

\$\endgroup\$
3
votes
\$\begingroup\$

JavaScript

Two different flavors here.

var totallyFairAndRandomPersonPicker = function () {
    var people = ['John','Jeff','Emma','Steve','Julie'];
    var drawnLot = [0, 1, 2, 3, 4][Math.random()*people .length]|0;
    return people[drawnLot];
};

totallyFairAndRandomPersonPicker ();

I think I accidentally put a ] in the wrong place! Sorry, John!

var chooseOne = function (list) {
    // We use double the random calls for double the randomness!
    var  i = Math.random()*Math.random()*list.length|0;
    return list[i];
};

chooseOne(['John','Jeff','Emma','Steve','Julie']);

It's the answer you need, not the answer you want. Everybody has a chance of being selected, but it's still massively unfair to John. I apologize for any dismay it causes Julie to occasionally chip in.

\$\endgroup\$
3
votes
\$\begingroup\$

JavaScript

This answer is obvious but still, im giving a shot at it :

var arrName = ["Jeff", "Emma", "Steve", "Julie"];

randName.call.apply(getName, arrName)

function randName(){
    var names = Array.prototype.slice.call(arguments)

    this.call(names[Math.floor(Math.random() * names.length)]);
}

function getName(){
    alert(this)
}

Poor Jeff, he will always have to buy the drinks.

The trick here is in the call.apply(). The function being called is not the randName, but directly getName where this this will be equal to the first cell in the array.

\$\endgroup\$
2
  • \$\begingroup\$ Very odd code with a good idea :-) But randName on itself should be working, and use its arguments instead of the global arrName variable. \$\endgroup\$
    – Bergi
    Jun 20, 2014 at 8:26
  • \$\begingroup\$ @Bergi what a brain fart, even prepared that array! Thank anyway \$\endgroup\$ Jun 20, 2014 at 12:42
2
votes
\$\begingroup\$

Python

from random import random
names = ['John', 'Jeff', 'Emma', 'Steve', 'Julie']
index = int(random()) * len(names) # Get a random number in range 0-4 (length of the list)
print names[index]

random.random() actually gives a value between 0.0-1.0, excluding 1.

\$\endgroup\$
2
votes
\$\begingroup\$

C#

Okay, one more.

I don't want to make anyone think there's any trickery here with regard to how random my random numbers are.

So I've got to great efforts to avoid passing anything to Random() or Random.Next(). It's a bit slow, but worth it for the extra integrity.

public class RandomDrinks
{
    int buyerIndex;
    string[] names = new string[] { "John", "Jeff", "Emma", "Steve", "Julie" };
    Random random = new Random();

    public string PrintBuyer()
    {
        //Get Random until there is a valid index
        do
        {
            buyerIndex = GiveMeRandoms();
        } while (!IsValueIsInRange(out buyerIndex));

        var text = names[buyerIndex];
        return String.Format("{0} is buying", text);
    }

    public int GiveMeRandoms()
    {
        return random.Next();
    }

    bool IsValueIsInRange(out int index)
    {
        int chosen = buyerIndex; 
        index = names.Length - 1;
        return !(chosen > index);
    }

}

is the effect of the out too obvious?

\$\endgroup\$
2
votes
\$\begingroup\$

Ruby

names = ['John', 'Jeff', 'Emma', 'Steve', 'Julie']
puts names[Time.new.sec % names.length]

It's not random if you run it at a right moment... ;)

\$\endgroup\$
2
  • 1
    \$\begingroup\$ So basically it's not random if you run it in exactly 5 second intervals? \$\endgroup\$
    – seequ
    Jun 16, 2014 at 17:05
  • 1
    \$\begingroup\$ Sure, for example, if you need to get Jeff all the time, just run it at any of these seconds: 1, 6, 11, 16... \$\endgroup\$
    – Tr00rle
    Jun 16, 2014 at 17:23
2
votes
\$\begingroup\$

JavaScript

function pick(names) {
  var r = Math.floor(Math.random * names.length);
  for (var i = 0; i < names.length; i++) { if (i >= r) { break; } }
  return names[i-1];
}
alert(pick(["John", "Jeff", "Emma", "Steve", "Julie"]));

The gods have spoken, Julie. Don't fight destiny.

Like all fearlessly awesome languages, JavaScript not only forgoes an exception and returns a value when you "invoke" a function without parenthesis; but also when you multiply by something that is not a number.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ This is fun, but a lot of languages fall sin to this, as Math.random returns the function itself, and it actually does let you know that the result of the multiplication doesn't make sense by returning NaN. The for loop looks suspect, so maybe you should consider doing this var ix =(Math.random * names.length)|0; This is pretty well known paradigm in javascript to turn a double into a number, and also turns your NaN into zero :) \$\endgroup\$
    – Michael B
    Jun 17, 2014 at 17:47
2
votes
\$\begingroup\$

Atari BASIC

It generates a random number R, and then READs the appropriate number of names from the DATA statement until it reaches the buyer.

10 DIM NAME$(10)
20 R=RND(5)
30 FOR I=0 TO R
40 READ NAME$
50 NEXT I
60 PRINT NAME$
70 END
99 DATA John,Jeff,Emma,Steve,Julie

RND(x) always returns a floating-point number between 0 and 1; the parameter is ignored (but required because the BASIC parser can't deal with zero-arg functions). So, the loop always executes exactly once, and John is the buyer. The correct way to generate a random number between 0 and 4 is R=INT(5*RND(0)).

\$\endgroup\$
0
2
votes
\$\begingroup\$

C++

#include <string>
#include <algorithm>
#include <iostream>

int main(){
    using namespace std;
    const char *names[] = { "John", "Jeff", "Emma", "Steve", "Julie"};
    random_shuffle(begin(names), end(names));
    cout << names[0] << '\n';
}

This one fools even me. Why does it print out Julie every time?

\$\endgroup\$
1
  • \$\begingroup\$ missing srand, glorious c++ ;) \$\endgroup\$
    – tomasz
    Jun 25, 2014 at 10:27
1
vote
\$\begingroup\$

C#

using System;
using ExtensionMethods;

namespace RandomBeerDrinker
{
    class Program
    {
        static void Main()
        {
            var generator = new Random();
            int person = generator.NextValue();
            var names = new[] {"John", "Jeff", "Emma", "Steve", "Julie"};
            Console.WriteLine(names[person]);
            Console.ReadLine();
        }
    }
}

Everyone's using extension methods nowadays, so it's not suspicious to have a class called ExtensionMethods, is it?

using System;
 namespace ExtensionMethods
    {
        public static class ExtensionMethods
        {
            public static int NextValue(this Random x)
            {
                return x.Next()%4; // Quite random, but excludes Julie
            }
        }
    }
 

\$\endgroup\$
1
vote
\$\begingroup\$

In order to be reusable, it is best to use generic functions with single purposes only, to assemble the complete program.

#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <string>

// generic function to randomize elements of any passed container
template<class C>
void randomize_container( C elements )
{
    std::random_shuffle(elements.begin(), elements.end() );
}

std::string pick_one( std::vector<std::string> names )
{
    randomize_container( names );
    return names[0];
}

int main(int argc, const char *argv[])
{
    // Do not forget to seed the rng, but only once!
    srand(time(nullptr));

    auto ret = pick_one( { "John", "Jeff", "Emma", "Steve", "Julie" } );
    std::cout << ret << " has to pay the next round\n";
}

It should just simply have been C& instead of C to pass the container per reference.

\$\endgroup\$
2
  • \$\begingroup\$ Saw this one immediately, but still laughed because it would be easy to miss, especially if your coworkers aren't familiar with C or C++. \$\endgroup\$ Jun 17, 2014 at 18:03
  • \$\begingroup\$ @BrendanLong: It is such a common mistake as you can see from the numerous questions on SO, that could be real world code ;) \$\endgroup\$
    – PlasmaHH
    Jun 17, 2014 at 19:33
1
vote
\$\begingroup\$

Sinclair BASIC

 10 LET r=INT RND*8
 20 LET n$=""
 30 IF r=0 THEN LET n$="John"
 40 IF r=1 THEN LET n$="Jeff"
 50 IF r=2 THEN LET n$="Jmma"
 60 IF r=3 THEN LET n$="Steve"
 70 IF r=4 THEN LET n$="Julie"
 80 PRINT "The person buying the drinks today is..."
 90 FOR d=0 TO 16 : REM Drum roll...
100 OUT 254,31
110 PAUSE 6-(d/4)
120 OUT 245,15
130 PAUSE 6-(d/4)
140 NEXT d
150 PRINT n$;"!"

Explanation:

The INT function only evaluates the item immediately after it so it performs (INT RND)*8 rather than INT (RND*8) so John will always buy the drinks.

\$\endgroup\$
1
  • \$\begingroup\$ "IF r=0 THEN" for all names is what you really intended? It looks like the last "IF" will set the name... so Julie will have to pay... \$\endgroup\$
    – user19214
    Jun 16, 2014 at 19:57
1
vote
\$\begingroup\$

Fortran 95

character(LEN=5), dimension(5) :: name=(/"John ","Jeff ","Emma ","Steve","Julie"/)
real :: ReallyReallyReallyRandomNumber = 0.

call RANDOM_NUMBER(ReallyReallyReallyRamdomNumber)

do i=1,5
    if (myReallyReallyRandomNumber <= real(i)/5.) then
        write(*,"(A,A)") "Selected name is: ", name(i)
        exit
    endif
enddo

end

I am assuming that your compiler generates a random seed which is different for every run. If not (which is the case of gfortran on my Windows machine), then you may like to add some code that generates a random seed before every run by using, for instance, the system's clock (see this link)

The variable that receives the random value is named ReallyReallyReallyRamdomNumber while the variable that is used in the loop is named ReallyReallyReallyRandomNumber (note that the first one is misspelled). This last variable is given an "initial" value of 0., which never changes, thus being the same regardless of the RANDOM_NUMBER subroutine. So, unfortunately for John, he will be selected every single time on every single machine.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ Obviously doing the safe thing of opening with implicit none would defeat this. I think this might be the first code to abuse variable names rather than the RNG seed. +1 \$\endgroup\$
    – Kyle Kanos
    Jun 18, 2014 at 2:18
  • 1
    \$\begingroup\$ @KyleKanos Thanks! Indeed this sort of code shows one more reason why implciit none should ALWAYS be present on a Fortran program. \$\endgroup\$ Jun 18, 2014 at 10:04
1
vote
\$\begingroup\$

C

#include <stdio.h>
#include <stdlib.h>
int main()
{
    char *names[] = {"John", "Jeff", "Emma", "Steve", "Julie"};
    printf("%s\n", names[random() % 5]);
    return 0;
}

Always outputs Steve on my computer. (It might vary by computer, but will likely be consistent on one machine.)

This works because random() is usually a pseudo-random number generator; you must seed it with some randomness, or it will always give the same numbers in the same order.

\$\endgroup\$
1
vote
\$\begingroup\$

Python

#!/usr/bin/env python3

import random

# Create list of names.
names = ['John', 'Jeff', 'Emma', 'Steve', 'Julie']

# Define start and end of range, just in case we want to change it in the future.
start = names.index(names[-1]) - len(names)
end = len(names)

# Randomly choose name from list, using range specified above.
print(random.choice(names[start:end]))

names[start:end] should be the same as names, but allows us to easily change the range in the future. However, instead of starting at 0, as we should, we sneakily start at -1. So, we actually pass names[-1:5] to random.choice, rather than names[0:5]. Thus, we always choose the last name in the list.

\$\endgroup\$
1
vote
\$\begingroup\$

JAVA

public class RandomBuyer{
    static String[] names = {"John", "Jeff", "Emma", "Steeve", "Julie"};

    public static void main(String[] args){
        String buyer = names[0]; //Initialize buyer 
        setRandomBuyer(buyer);   //Set buyer to random
        System.out.println(buyer);
    }
    static void setRandomBuyer(String buyer){
        int random = new java.util.Random().nextInt(5);
        buyer = names[random];
    }
}

Explanation

Why this doesn't work!

\$\endgroup\$
1
vote
\$\begingroup\$

Perl

While playing code golf, I tested this simple shuffle algorithm. It always picks Steve.

use strict;
use warnings;

# Randomness test for 0.5 - rand:
# perl -e 'for(1..10000){$x=0.5 - rand;$x<0&&$n++;$x>0&&$p++}' \
#      -e 'print "negative: $n, positive: $p\n"'

# Shuffle from alphabetical order to random order.
my @shuffled = sort { 0.5 - rand } qw(Emma Jeff John Julie Steve);
print "$shuffled[-1]\n";

Perl expects the sort block to return an integer, not a float. My block { 0.5 - rand } returns a random float from -0.5 exclusive to 0.5 inclusive, but Perl truncates this float toward 0 before checking its sign. Every float from -0.5 to 0.5 becomes integer 0, so all names compare equal and stay in alphabetical order.

If we fix the bug, this program would perform a "Microsoft shuffle", which is not a fair shuffle. Microsoft used 0.5 - Math.random() in JavaScript for a comparison function. That shuffle had much bias, because 0.5 - Math.random() does not provide a consistent ordering.

Find more Perl answers by Zaid, chinese perl goth, Allen G.

\$\endgroup\$
1
vote
\$\begingroup\$

F#

This solution is very flexible -- it allows you to pick people in batches, so you won't have to run it again for a little while. Supply the number as the first argument to the program:

[<EntryPoint>]
let main argv =
  let getRandom (min, max) = (new System.Random()).Next (min, max)
  let pickBuyers people times = List.init times (fun _ -> List.nth people (getRandom (0, List.length people)))
  printfn "%A" (pickBuyers ["John"; "Jeff"; "Emma"; "Steve"; "Julie"] <| System.Int32.Parse argv.[0])
  0

! Exploits a common mistake when learning random numbers, so you probably caught this if you know the basics of System.Random. Instantiating Random() uses the time as a seed, and calling it in quick succession will cause it to seed exactly the same over and over until the time changes.

However (as pointed out by @kernigh), the more elements you generate at once, the more likely it is to roll over to the next millisecond before it's finished. This will cause the next RNGs to get seeded with a different number, thus changing the resulting number. This will happen every millisecond(?).

\$\endgroup\$
2
  • \$\begingroup\$ The output looks suspicious: ideone.com/AHZVz5 \$\endgroup\$
    – kernigh
    Jun 25, 2014 at 22:04
  • \$\begingroup\$ I'm aware of that -- the more items you generate at once, the more likely it will be that it rolls over the millisecond, thus seeding the RNG differently. It's in the nature of this method, unfortunately. \$\endgroup\$
    – Jwosty
    Jun 25, 2014 at 22:53
1
vote
\$\begingroup\$

TI-BASIC

No computer handy? This works on all TI-83/84/+/SE calculators.

PROGRAM:RANDOM
:"NEW ARRAY NAME:"
:"JOHN"
:"JEFF"
:"EMMA"
:"STEVE"
:"JULIE"
:Disp "NAMES[floor(rand*5)]"
:Disp "NAME: ",Ans

The names are successively set into Ans (so JULIE would be the contents of Ans). Then, the NAMES[floor(rand*5)] is piped away as a useless string, and the last line looks line it is pulling one of the names from the array NAME (which doesn't exist, by the way). Instead, it will always display JULIE. The order of the names can be switched around to provide a different victim on demand.

\$\endgroup\$
0
votes
\$\begingroup\$

C#

private void randomizer()
    {
        string[] allName = {"John", "Jeff", "Emma", "Steve", "Julie"};
        Random getRandomNumber = new Random(0);
        Console.WriteLine(allName[getRandomNumber.Next(0,4)]);
    }

Since I'm making a random with the seed of zero, the result will always be the same, in this special case it would be Emma.

\$\endgroup\$
0
votes
\$\begingroup\$

C++

#include<iostream>
#include<climits>
#include<cstdlib>
#include<cmath>

using namespace std;

const string names[]={ "John", "Jeff", "Emma", "Steve", "Julie" };

int main(){
    srand(time(NULL));
    // Generate a random real number
    double r=(double)rand()/(RAND_MAX+1.);

    // Convert it back into an integer
    unsigned long long x=round(r * (ULLONG_MAX+1.));

    // Simply use the remainder is a bit waste. Add up the digits in base 5 instead
    while(x >= 5)
        x=x/5 + x%5;

    // Print the answer
    cout<<names[x]<<endl;
    return 0;
}

Assume RAND_MAX is 2147483647. This program almost always prints Julie, with chances to print John when r is generated exactly zero.
Firstly, the real things you get in x is r*2^33. Then the while loop in fact computes something like x mod 4. And 4 is a divisor of 2^33. It is not the correct way adding up all digits, either.

\$\endgroup\$
0
votes
\$\begingroup\$

Ozone

(s1v1(1)n1n1s2v21v21s3v3(<+2n2v12+1n1v21v03>)v03)

The trick is in "+2n2".

\$\endgroup\$
2
  • \$\begingroup\$ This appears to be written in a language which doesn't support the generation of random numbers. How is it supposed to fool anyone? \$\endgroup\$ Jun 17, 2014 at 11:44
  • 4
    \$\begingroup\$ Maybe you could explain what the code actually did? \$\endgroup\$
    – kitcar2000
    Jun 17, 2014 at 15:07
0
votes
\$\begingroup\$

Java

import java.security.SecureRandom;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Random;
public class ExampleCode
{
    public static void main( String A[] )
    {
        String[] P = "John Jeff Emma Steve Julie".split( " " );
        P = new HashSet<String>(Arrays.asList( P )).toArray(P);//this should change order of names to random
        Random R = new SecureRandom();//let's use good random number generator
        int O = R.nextInt( P.length );//select random number O
        System.out.println(P[0]);//Show the results
    }
}

Explanation

The line that changes order to "random" changes oreder, but not randomly. Variable with random number is called 'O' (uppercase 'o'), but when getting value from array '0' (result of 1-1) is used, which looks simillar to uppercase 'o'.

\$\endgroup\$
1
0
votes
\$\begingroup\$

Simple solution using JavaScript

var randArrElement = function(arr){
   return arr[Math.ceil(Math.random()*(arr.length-1))];
   //arr[arr.length] is undefined because arrays are 0 indexed, so we subtract 1.
}
randArrElement(["John", "Jeff", "Emma", "Steve", "Julie"]);

First 10 results:
Steve, Steve, Jeff, Steve, Julie, Jeff, Emma, Emma, Steve, Julie

Expanation:

Because I round using ciel, the only way that John could get chosen is if Math.random()*(arr.length-1) is exactly equal to 0. Even if it is 0.0000001, ceil will round up to 1. So John never gets chosen.

\$\endgroup\$
3
  • \$\begingroup\$ This is the wrong way around. You always exclude one instead of always picking that person. But I like the variant enough not to downvote :P \$\endgroup\$
    – Martijn
    Jun 26, 2014 at 14:35
  • \$\begingroup\$ You know, Math.random can return exactly 0. \$\endgroup\$ Nov 2, 2015 at 18:45
  • \$\begingroup\$ @ppperry but it almost surely don't. \$\endgroup\$
    – Xwtek
    Nov 3, 2015 at 9:52

Not the answer you're looking for? Browse other questions tagged or ask your own question.