5
\$\begingroup\$

Find the shortest way to generate a random number between 0-9 without repeating the last generated number. Here is an example written in javascript.

var n=t=0;
while(n==t){
  t=Math.floor(Math.random()*9);
}
n=t;

I don't know if it is possible, but it would be interesting if there is a solution using only one variable.

To clarify the solution can be in any language. Based on the comments I am going to disallow using arrays since apparently that makes it very easy and this is code-golf so the shortest answer wins.

\$\endgroup\$
5
  • \$\begingroup\$ Nope. Interesting would be using only one scalar variable and no stack, nor register. \$\endgroup\$
    – manatwork
    Commented Aug 11, 2015 at 17:57
  • \$\begingroup\$ @qw3n - Can you clarify here? Are answers in all languages acceptable? Are you interested in simply the shortest code. \$\endgroup\$
    – Optimizer
    Commented Aug 11, 2015 at 18:21
  • \$\begingroup\$ Also, as noted in the first comment, this is super trivial if that one variable is an array. \$\endgroup\$
    – Optimizer
    Commented Aug 11, 2015 at 18:22
  • \$\begingroup\$ @Optimizer to explain why I asked the question here instead of SO. I felt there was a clear and simple way to solve the problem (similar to the sample code I have). But I felt that it would be an interesting challenge to see if it could be done in a much shorter way, but not necessarily a way that would be wise to add to an actual codebase. If the question needs to be closed that's fine just wanted to give my point of view. \$\endgroup\$
    – qw3n
    Commented Aug 12, 2015 at 18:47
  • \$\begingroup\$ This is pretty much a simplification of this old question. \$\endgroup\$ Commented Aug 12, 2015 at 20:45

10 Answers 10

9
\$\begingroup\$

Pyth, 7 bytes

e=+ZhO9

Try it online: Demonstration

Explanation

          implicit: Z = 0
     O9   Generate a random int from [0, 1, ..., 8]
    h     add 1
 =+Z      add this to Z and update Z
e         print Z modulo 10
\$\endgroup\$
5
  • \$\begingroup\$ I don't think this is correct. You would need your list to include 9 in order for it to be random. Otherwise, each time you can name a number that you know it won't be, once you've seen the previous random number. \$\endgroup\$
    – mbomb007
    Commented Aug 11, 2015 at 21:34
  • \$\begingroup\$ @mbomb007 h adds 1 to the generated number, so the real range is [1, ..., 9]. \$\endgroup\$
    – Dennis
    Commented Aug 11, 2015 at 21:42
  • \$\begingroup\$ @Dennis Yeah, but it has to be from 0 to 9 as per the OP's question, or am I reading it wrong? Yeah... nvm. I think I read it as inclusive, but just realized that the program he gave multiplies by nine which is exclusive. \$\endgroup\$
    – mbomb007
    Commented Aug 11, 2015 at 22:02
  • \$\begingroup\$ @mbomb007 If you add 0 to the previously generated integer, you get the same integer again, which is precisely what you're trying to avoid. \$\endgroup\$
    – Dennis
    Commented Aug 11, 2015 at 22:05
  • 1
    \$\begingroup\$ @mbomb007 this is the way I've always done it. The first iteration is guaranteed not to contain a 9, but after that it's simply guaranteed to not contain the number from the previous iteration, which is what the OP wants. If it's essential that all ten digits must be able to appear in the first call, followed by no repetitions after that, just call the random number generator once or twice to randomise it, then on the next call it can give any digit. \$\endgroup\$ Commented Aug 11, 2015 at 22:53
5
\$\begingroup\$

CJam, 10 8 bytes

Thanks @Dennis for a 2 bytes golf!

You can repeat this piece of code how many times you want.

A,W-mR:W

Explanation:

         e# At startup, W = -1
A,       e# Push [0 ... 9]
  W-     e# Remove W from the list
    mR   e# Random choice from list
      :W e# Assign to W
         e# The number is left on the stack

Try it online.

\$\endgroup\$
4
  • \$\begingroup\$ Actually you cannot run it multiple times as context is not saved between different runs, so W's value remains -1 at beginning of each run. However, you can repeat the code multiple times to get more than 1 random number \$\endgroup\$
    – Optimizer
    Commented Aug 11, 2015 at 18:36
  • \$\begingroup\$ @Optimizer That's what I meant (and what the online test does). I guess I wasn't very clear, let me edit that :) \$\endgroup\$ Commented Aug 11, 2015 at 18:38
  • \$\begingroup\$ You can use mR instead of mr0=. \$\endgroup\$
    – Dennis
    Commented Aug 12, 2015 at 4:30
  • \$\begingroup\$ @Dennis Missed that in the docs, thanks. \$\endgroup\$ Commented Aug 12, 2015 at 6:56
4
\$\begingroup\$

K5, 19 bytes

Not particularly clever:

t:-1;r:{t::*1?10^t}

Each time r is invoked, it picks 1 random number (*1?) from the set formed by taking the range 0-9 except (^) the previous random number and then stores the result in t (t::). We initialize t (t:-1;) such that the first result can be any digit 0-9.

The definition of r is purely for convenience in repeatedly invoking it, so you're really only using a single variable.

edit:

Just for fun, here's a k5 program which will generate a sequence of N numbers containing no immediate repetitions (as in the above problem) without using any variables:

1_(*1?10^)\[;-1]

For example,

  1_(*1?10^)\[;-1]10
1 8 0 6 8 5 1 0 5 1
  1_(*1?10^)\[;-1]3
4 0 7

Doesn't work quite right in my K implementation, so I suppose writing this and discovering a bug was a decent use of my time!

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

Java, 62 bytes

int a(int p){p+=9*(p+Math.random());return p%10==p/10?9:p%10;}

This is a function. You call it with the previously returned value. Uses only the variable supplied.

2 variables, 59 bytes

int a(int p){int a=(int)(Math.random()*9);return a==p?9:a;}
\$\endgroup\$
2
\$\begingroup\$

Julia - 25 18 bytes

t=(rand(1:9)+t)%10

Or, for a slightly longer, iterative solution:

while t==(t=rand(0:9))end

No temporary second variable necessary.

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

Python 2, 79 bytes

Here's a simple one you can repeatedly run in a REPL:

from random import*
try:p
except:p=n=0
while p==n:n=int(random()*9)
print n
p=n
\$\endgroup\$
1
\$\begingroup\$

Java 8, 89 bytes

As an IntStream...

// Int Stream (89 bytes)
IntStream.iterate(0,(o)->new Random().ints(0,10).filter(x->x!=o).findFirst().getAsInt());

Minimal usage...

// Usage (119 bytes)
IntStream.iterate(0,(o)->new Random().ints(0,10).filter(x->x!=o).findFirst().getAsInt()).forEach(System.out::println);
\$\endgroup\$
1
\$\begingroup\$

Octave, 24 bytes

Here's an anonymous function using one variable (plus the function handle):

r=@(n)mod(randi(9)+n,10)

Sample run:

>> n=5;
>> n=r(n)
n =  2
\$\endgroup\$
0
\$\begingroup\$

Javascript, 39 bytes

Not the most exciting answer, but it is in Javascript.

t=-1;while(t==(t=(Math.random()*9)|0));

To test it:

//set the value here, or it will produce repeated numbers:
t=-1;
for(var i=0; i < 10; i++){
    //generate a new random number, using the code in the answer
    while(t==(t=(Math.random()*9)|0));
  
    document.write(t + '<br>');
}

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

Python 3, 42 33 bytes

If your criteria for "random" is generating a number 0-9,

[...] without repeating the last generated number.

Something like this would work:

i=(i+1)%10if"i"in globals()else 0
\$\endgroup\$
1
  • \$\begingroup\$ An anonymous user suggested to shorten the code to i=(i+1)%10if"i"in globals()else 0 (which I've rejected as a matter of policy). \$\endgroup\$ Commented Aug 12, 2015 at 11:46

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