22
\$\begingroup\$

I read this question and thought it would make a nice challenge.

Task

Give an input 0<n<10 generate a random number with

  • exactly n digits
  • the first not a 0
    • so f(n)>10**(n-1)-1
  • distinct digits

Winning criteria

This is so shortest code wins.

Random

I mean evenly distributed random. So from the view of the program each possible number has the same chance. If the language you're writing in has a weird random number generator, it's okay to use that one.

Example

The list of values to randomly select from for n=2 is:

[10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98]
\$\endgroup\$
  • 4
    \$\begingroup\$ Requiring randomness without specifying a distribution should be avoided. \$\endgroup\$ – flawr Apr 24 '17 at 19:50
  • \$\begingroup\$ return as an integer, not a string, yes? \$\endgroup\$ – Giuseppe Apr 24 '17 at 20:46
  • \$\begingroup\$ @Giuseppe generate a random number \$\endgroup\$ – mbomb007 Apr 24 '17 at 20:57
  • 4
    \$\begingroup\$ I think of this every single time someone makes a random number question xkcd.com/221 \$\endgroup\$ – Thunda Apr 25 '17 at 4:56
  • 1
    \$\begingroup\$ @ais523 "Give an input 0<n<10 generate a random number with" \$\endgroup\$ – cleblanc Apr 25 '17 at 13:46

31 Answers 31

17
\$\begingroup\$

Python 2, 77 bytes

from random import*
r=range(10)
while[1]>r:shuffle(r)
print`r`[1:input()*3:3]

Try it online!

Shuffles the list of 10 digits until it doesn't start with 0, then makes a number with the first n digits listed.

\$\endgroup\$
  • \$\begingroup\$ Definitely runs faster and with less memory for input of 9 or 10. \$\endgroup\$ – mbomb007 Apr 24 '17 at 21:15
  • \$\begingroup\$ Neat solution! Could you explain how the [1::3] works to convert it from a list to a string? I've never seen that before. \$\endgroup\$ – Julian Wolf Apr 24 '17 at 21:15
  • \$\begingroup\$ @JulianWolf It only works if each element of the list is the same length. It actually takes the string representation of the list, then slices it taking every 3rd character after skipping the first [. \$\endgroup\$ – mbomb007 Apr 24 '17 at 21:16
  • \$\begingroup\$ @JulianWolf [1::3] gets the character at index 1, then every third. For [1, 2, 3], that gives 123, skipping the brackets, commas, and spaces. \$\endgroup\$ – Dennis Apr 24 '17 at 21:16
  • \$\begingroup\$ Shoot, okay—that makes sense. I was forgetting that [1, 2, 3] had already been stringified and that commas and spaces needed skipping. Thanks! \$\endgroup\$ – Julian Wolf Apr 24 '17 at 21:53
10
\$\begingroup\$

Brachylog, 9 10 bytes

{~lℕ₁≜≠}ᶠṛ

Try it online!

As usual for Brachylog, this is a function submission. The TIO link above has been given a command-line argument to make the function into a full program.

I had to add an extra byte from the first version of this, changing to ℕ₁, to disallow the output 0 (something that's now been clarified).

Explanation

{~lℕ₁≜≠}ᶠṛ
{      }ᶠṛ  Pick a random value with these properties:
 ~l           it has length equal to the input;
   ℕ₁         it's a positive integer;
     ≜        it's a specific value (not a constraint);
      ≠       all its elements (digits in this case) are different.

Fairly inefficient, because the interpreter generates a list of all possible values and then picks one at random (that's what ᶠṛ means; Brachylog didn't have a "pick a random solution" option at the time this question was asked).

Some comments on the labelization here: if the is omitted, the section within the braces only produces one value, a constraint representing numbers with the property we want; picking a random result therefore gives us the constraint, and the interpreter outputs the minimum absolute value that meets the constraint (1, 10, 102, 1023, 10234, etc.), which is not what we want. We thus have to force it to construct the list via an explicit labelization.

Most Prolog implementations I've seen have a builtin to find a random result matching a constraint, but typically not with uniform probability; Brachylog didn't have one, though (one got added in response to this challenge, but obviously I can't use it due to loophole rules). If it did, and if it happened to give uniform probability on this problem, this program would just be ~lℕ₁≠ followed by that builtin, for a likely length of 6 bytes.

Brachylog, 8 bytes, in collaboration with @Fatalize

~lℕ₁≠≜ᶠṛ

Try it online!

This is the sort of genius low-level trick that only makes sense with the way Prolog does things, and doesn't make much sense when described mathematically.

As before, ~lℕ₁≠ builds up a value that describes a constraint ("length equal to the input, natural number, all elements different"). Then ≜ᶠ generates all possible values that meet the constraint. The point here is that with Brachylog's evaluation sequence, no actual choices are made until the appears, so the "find all solutions" operation need apply to nothing but the "specific value that fulfils a constraint" operation . That means there's no need for a {…} to select its scope, saving 2 bytes.

\$\endgroup\$
  • \$\begingroup\$ I was going to post a solution with ≜₁ before I realized that it was added because of this challenge \$\endgroup\$ – Unrelated String May 16 at 10:12
8
\$\begingroup\$

Jelly, 9 bytes

⁵*ṖQL$€MX

Try it online! (won't work at TIO for n > 6 due to the inefficiency of the implementation)

or an alternative implementation of the same thing:

⁵*ṖQL$ÐṀX

How?

This is pretty sneaky, and very inefficient! Jelly does some useful things implicitly when an atom expects a list but receives an integer (this is by design).
This code uses a couple of these useful implicit actions:

  • The monadic atom , "pop", when called with an integer input implicitly makes a range from which to pop, so an input of n first makes [1, 2, ..., n], then pops, yielding [1, 2, ..., n-1].

  • The monadic atom Q, "de-duplicate" or "unique", when called with an integer input implicitly makes a decimal list to de-duplicate, so an input of n where:
    n = dk-1×10k-1 + dk-2×10k-2 + ... + d1×10 + d0
    first makes
    [dk-1, dk-2, ... ,d1, d0]
    and then yields the unique values by first appearance.
    So, for example, n = 5835518 would yield [5, 8, 3, 1].

Furthermore the monadic atom M, "maximal element indexes", returns the indexes of the maximal items from a list, this saves two bytes over the far more obvious alternative of testing for equality with the input and finding truthy indexes, ⁵*ṖQL$€=⁸TX, or ⁵*ṖðQL⁼ð€TX

⁵*ṖQL$€MX - Main link: n                       e.g. 2
⁵         - literal 10
 *        - exponentiate: 10^n                      100
  Ṗ       - pop (make range 1 to 10^n, then pop)    [1  ,2  ,...,21   ,22 ,23   ,...,97   ,98   ,99]
     $€   - last two links as a monad for €ach:
   Q      -   unique (makes a decimal list first)   [[1],[2],...,[2,1],[2],[2,3],...,[9,7],[9,8],[9]]
    L     -   length                                [1  ,1  ,...,2    ,1  ,2    ,...,2    ,2    ,1  ]
       M  - indexes of maximal elements             [        ...,21       ,23,   ...,97   ,98       ]
          -                                         - i.e. all n-digit numbers with n-distinct digits.
        X - pick a random element from that list

This is all quite quite inefficient, both in time and memory: first a list of 10n integers is made and one is discarded, then for each of these a list of n integers (not some fancy 4-bit object or enum) is made and then de-duplicated. This de-duplication has a completely list-based implementation (no sets, sorted-sets, or dictionaries are involved under-the-hood, each digit is checked for existence in the list that eventually gets output).
Offline n = 7 uses ~0.5GB and takes ~25 seconds, while n = 8 uses ~4GB and takes ~5 minutes - I have not bothered running n = 9 as I only have 16GB ram (I guess it would take ~45 minutes).

The alternative implementation just uses the built-in ÐṀ quick to filter-keep minimal (which here just adds a little overhead in management for the same byte-count).

\$\endgroup\$
  • \$\begingroup\$ Oh wow. I was trying something very like this but missed the trick of storing the values to return in the list indexes (via suitably padding out the list), rather than trying to store them separately. This is a trick that comes in useful in Jelly fairly often and I always seem to miss it. \$\endgroup\$ – user62131 Apr 25 '17 at 3:28
7
\$\begingroup\$

Jelly, 11 bytes

9Xœ|⁵ḶẊ¤ḣ¹Ḍ

Try it online!

How it works

9Xœ|⁵ḶẊ¤ḣ¹Ḍ  Main link. Argument: n

9            Set the return value to 9.
 X           Pick; pseudo-randomly select an integer from [1, ..., 9].
       ¤     Combine the three preceding links into a niladic chain.
    ⁵          Yield 10.
     Ḷ         Unlength; yield [0, ..., 9].
      Ẋ        Shuffle; pseudo-randomly select a permutation of [0, ..., 9].
  œ|         Multiset OR; prepend the selected integer to the selected permutation
             and remove the second occurrence of the first element.
         ¹   Identity; yield n.
        ḣ    Head; keep the first n digits of the permutation.
          Ḍ  Undecimal; convert from base 10 to integer.
\$\endgroup\$
  • \$\begingroup\$ That's a very clever way to remove the duplicate... \$\endgroup\$ – Leaky Nun Apr 25 '17 at 3:43
7
\$\begingroup\$

JavaScript (ES6), 72 71 70 69 bytes

f=(x,y="")=>x?!y.match(z=Math.random()*10|0)&&y|z?f(x-1,y+z):f(x,y):y

This is a recursive function that takes in the number of digits x. The second parameter y, initially set to the empty string, keeps track of the number as we generate it digit by digit.

First we generate a random digit z with Math.random()*10|0. Now, we want to check that the y does not contain z, and that y and z are not both 0.

We can calculate the first condition with !y.match(z). y.match(z) returns an array (always truthy) if y contains z, null (falsy) otherwise; the ! converts this to a boolean and inverts it.

The second condition is checked with y|z. Although y is a string, JS implicitly converts it to an integer when using |. This is a positive integer if y already contains digits, 0 otherwise. The net result is that y|z returns 0 iff y is empty and z is 0, or a positive integer otherwise.

If both of these conditions are true, then we append the digit to y, decrement x, and start the process over again. Otherwise, we simply return to the beginning and hope that the next random digit works. When x reaches 0, we simply return the empty string to end the recursion.


Previous version:

f=(x,y)=>x?~y>>(z=Math.random()*10|0)&1&&y|z?z+f(x-1,y|1<<z):f(x,y):""

This is a recursive function that takes in the number of digits. The initially undefined second parameter, y, is a 10-bit lookup table telling us which digits we already have, conveniently stored as an integer.

First we generate a random digit z with Math.random()*10|0. Now, we want to check that the z'th least significant bit of y is not set, and that y and z are not both 0.

We can calculate the first condition with ~y>>z&1; invert y, shift it z bits to the right, and take only the least significant bit. This gives 1 if we have not yet generated the digit in question, or 0 otherwise.

The second condition was initially pretty difficult to figure out (I tried using y/z at first to generate NaN if they're both 0), but at some point I realized that simply y|z would do the trick. The result is 0 iff both y and z are 0; a positive integer otherwise.

If both of these conditions are true (~y>>z&1&&y|z), then we generate the rest of the number and prepend z. The rest of the number is generated by calling the function again with x-1 and y|1<<z (y, but with the bit at index z set to 1). When x reaches 0, we simply return the empty string to end the recursion.

\$\endgroup\$
5
\$\begingroup\$

ClojureScript, 81 79 bytes

#(let[a(subvec(shuffle(range 10))0 %)](if(=(a 0)0)(recur %)(int(apply str a))))

This is an anonymous function, so you have to use it like this:

(#(...) {arguments})

Where you replace {arguments} with your arguments.

You can try the code here (ClojureScript REPL).

Thanks @cliffroot for shaving off 2 bytes!


Expanded code:

(defn random-digits [n]
  (let [num-vector
        (subvec
          (shuffle (range 10))
          0 n)]
    (if (= (num-vector 0) 0)
      (recur n)
      (int (apply str num-vector)))))

Explanation:

I'm going to go through the lines one by one, using an example input of 8.


(defn random-digits [n] ...)

Pretty simple, this defines the function random-digits with one argument, called n. In my answer I used an anonymous function (#(...)), to save bytes.


(let [num-vector ...] ...)

Let's examine inside the let, from inside out:

(shuffle (range 10))

In ClojureScript (and Clojure), (range n) is similar to Python's range(n): it gives you a list with every number from 0 to n - 1 (9 in this case).

shuffle takes a list, and returns a vector (which is slightly different from a list) with all of its elements shuffled. So, using our example, we get something like this:

[1 0 8 3 6 7 9 2 4 5]

(subvec {see above} 0 n)

(subvec vector start end) takes a vector (only a vector), and returns a vector which has all the elements from index start to end. In this case, we're taking elements from the 0th element to the argument given to random-digits. If we apply that to our example, we get:

[1 0 8 3 6 7 9 2]

(if (= (num-vector 0) 0)
  (recur n)
  (int (apply str num-vector)))

This if statement checks if the first element of num-vector is a 0.

If it is 0, then we call the function again, with the argument n, using recur.

If it isn't 0:


(int (apply str num-vector))

(apply function list) takes a list, and spits them into the function as arguments. For example:

(apply + [2 3 4])

Turns into:

(+ 2 3 4)

Which equals 9.

(str items) turns every item in items into a string, and then concatenates them. int converts anything to an integer. So if we apply this to our example, we get:

   (int (apply str [1 0 8 3 6 7 9 2]))
=> (int (str 1 0 8 3 6 7 9 2))
=> (int "10836792")
=> 10836792

Which is our final answer.

\$\endgroup\$
  • 2
    \$\begingroup\$ Gotta love ClojureScript for allowing (int string) instead of (Integer/parseInt string) :) \$\endgroup\$ – cliffroot Apr 25 '17 at 7:52
  • 1
    \$\begingroup\$ @cliffroot I mean, you can do read-string in Clojure, but it's not much better... \$\endgroup\$ – clismique Apr 25 '17 at 7:53
  • \$\begingroup\$ 2 bytes saved #(let[a(subvec(shuffle(range 10))0 %)](if(=(a 0)0)(recur %)(int(apply str a)))) moves apply str part to the end, allows to compare to 0 instead of \0 and uses subvec instead of take allows to use vector as a function and thus to remove first \$\endgroup\$ – cliffroot Apr 25 '17 at 8:30
  • \$\begingroup\$ @cliffroot Huh, did not know that shuffle turned the collection into a vec. Thanks! Will have to write a new explanation, though... \$\endgroup\$ – clismique Apr 25 '17 at 10:03
5
\$\begingroup\$

Python 2, 89 81 80 bytes

from random import*
lambda n:choice([i for i in range(10**n)if`set(`i`)`[5*n:]])

Try it online

\$\endgroup\$
  • \$\begingroup\$ I don't think you need a start value for the range. \$\endgroup\$ – Dennis Apr 24 '17 at 21:21
  • \$\begingroup\$ Nice! That'll slow it down. :D Too bad I can't use a generator instead of a list. \$\endgroup\$ – mbomb007 Apr 24 '17 at 21:22
  • \$\begingroup\$ Only by 11%. Drop in a bucket for code golf. \$\endgroup\$ – Dennis Apr 24 '17 at 21:26
  • \$\begingroup\$ Yeah, I should use 99**n, just to be sure I get them all. :D \$\endgroup\$ – mbomb007 Apr 24 '17 at 21:27
  • \$\begingroup\$ I looked at doing it this way too, but got 80, by using if`set(`i`)`[5*n:]]. \$\endgroup\$ – Jonathan Allan Apr 26 '17 at 5:38
5
\$\begingroup\$

R, 45 Bytes

k=0
i=scan()
while(!k[1])k=sample(0:9)[1:i]
k
\$\endgroup\$
  • \$\begingroup\$ I think you can just set k=0 since it's an implicit vector of length one, and you can use i=scan() to take input from stdin as a number. I'm also not sure that a list of digits is a "correct" submission, but I'm not the judge. \$\endgroup\$ – Giuseppe Apr 25 '17 at 14:47
  • \$\begingroup\$ @Giuseppe Thanks for the input, updated both of your suggestion (on both posts), thanks. \$\endgroup\$ – Neil Apr 25 '17 at 16:08
  • \$\begingroup\$ Would while(!k[1]) work to save 2 bytes? \$\endgroup\$ – BLT Apr 26 '17 at 19:37
  • \$\begingroup\$ @BLT Updated, thanks. \$\endgroup\$ – Neil Apr 26 '17 at 21:08
3
\$\begingroup\$

Bash + GNU utils, 46

seq 1e$[$1-1] 1e$1|egrep -v '(.).*\1'|shuf -n1

Try it online.

This takes a long time for larger n - about 30s for n=7, and increasing 10 times for each increment, so probably 8-9 hours for n=10.

\$\endgroup\$
  • \$\begingroup\$ per the question, n=10 doesn't need to even work, much less be fast \$\endgroup\$ – ysth Apr 25 '17 at 11:45
3
\$\begingroup\$

Java 7, 150 147 145 134 bytes

String c(int n){String r="";for(int l,x;(l=r.length())<n;)if(l<1&(x=(int)(Math.random()*10))>0|(l>0&!r.contains(""+x)))r+=x;return r;}

-2 bytes thanks to @TheLethalCoder

(old) Explanation:

String c(int n){                           // Method with integer parameter and String return-type
  String r="";                             //  Result-String
  for(int l=0,x;l<n;l=r.length()){         //  Loop until the length of the result-String is equal to the parameter integer
    x=new java.util.Random().nextInt(10);  //   Random digit
    if((l<1&x>0)                           //   If the length is zero and the random digit is not zero
       |(l>0&!r.contains(""+x)))           //     or the length is at least 1, and the result-String does not contain this random digit yet
      r+=x;                                //    Append the random digit to the result-String
  }                                        //  End of for-loop
  return r;                                //  Return result-String
}                                          // End of method

Test code:

Try it here.

class M{
  String c(int n){String r="";for(int l,x;(l=r.length())<n;)if(l<1&(x=(int)(Math.random()*10))>0|(l>0&!r.contains(""+x)))r+=x;return r;}

  public static void main(String[] a){
    M m = new M();
    System.out.println(m.c(4));
    System.out.println(m.c(10));
  }
}

Example output:

7194
8672953041
\$\endgroup\$
  • \$\begingroup\$ Can you not use a lambda expression here? i.e. n->... or is that Java 8+? \$\endgroup\$ – TheLethalCoder Apr 25 '17 at 9:54
  • 1
    \$\begingroup\$ You can also borrow the trick I just used in my answer, set the length in the comparison check i.e. for(int l,x;(l=r.length())<n;) and you should save a byte. \$\endgroup\$ – TheLethalCoder Apr 25 '17 at 9:59
  • 1
    \$\begingroup\$ @TheLethalCoder Ah of course, thanks. Great teamwork! ;) And yes, n->... is Java 8. Personally I prefer to codegolf in Java 7, even though 8 is always shorter. \$\endgroup\$ – Kevin Cruijssen Apr 25 '17 at 11:35
2
\$\begingroup\$

Perl 6, 44 bytes

{(->{+[~] (^10).pick($_)}...*>9 x$_-1).tail}

Try it

Expanded:

{  # bare block with implicit parameter 「$_」
  (

    ->{  # pointy block lambda with no parameters

      +                # turn the following into a numeric
      [~]              # concatenate the following

        (^10).pick($_) # grab $_ digits at random from 0..9
    }

    ...                # keep doing that until

    * > 9 x $_-1       # one of them is big enough

  ).tail # return the last one (only valid one)
}
\$\endgroup\$
2
\$\begingroup\$

PHP, 67 Bytes

Online Version

All versions based of shuffle the digits from 0-9

for($a=range(0,9);!$a[0];)shuffle($a);for(;$i<$argn;)echo$a[+$i++];

71 Bytes

for($s="0123456789";!$s[0];)$s=str_shuffle($s);echo substr($s,0,$argn);

73 Bytes

for($a=range(0,9);!$a[0];)shuffle($a);echo join(array_slice($a,0,$argn));
\$\endgroup\$
2
\$\begingroup\$

MATL, 15 bytes

`4Y2GZr1)48=]8M

Try it at MATL Online!

Explanation

`        % Do...while
  4Y2    %   Push predefined literal '0123456789'
  G      %   Push input n
  Zr     %   Random sample of n unique characters from that string
  1)     %   Pick the first
  48=    %   Is it 48? This is the loop condition
]        % End. If top of the stack evaluates to true: next iteration
8M       % Push the latest random sample. Implicitly display
\$\endgroup\$
2
\$\begingroup\$

Jelly, 12 bytes

9×!X+!Œ?’ḣƓḌ

Currently one byte behind my other Jelly answer, but I really like this one.

Try it online!

How it works

9×!X+!Œ?’ḣƓḌ  Main link. No arguments.

9             Set the argument and the return value to 9.
  !           Yield 9!
 ×            Compute 9 × 9!.
   X          Pick; pseudo-randomly select an integer j from [1, ..., 9 × 9!].
     !        Yield 9!
    +         Compute k := j + 9!.
              The result will belong to [9! + 1, 10!].
      Œ?      Get the permutation P of R := [1, ..., r], with minimal r, such that
              P is the lexicographically k-th permutation of R.
              Since k belongs to [9! + 1, 10!], r = 10 and this generates a per-
              mutation between [2,1,3,4,5,6,7,8,9,10] and [10,9,8,7,6,5,4,3,2,1].
        ’     Subtract 1 from all integers in P.
          Ɠ   Read an integer n from STDIN and yield it.
         ḣ    Head; keep the first n digits of the permutation.
           Ḍ  Undecimal; convert from base 10 to integer.
\$\endgroup\$
2
\$\begingroup\$

APL (Dyalog), 27 19 17 bytes

Requires ⎕IO←0 which is default on many systems.

10⊥⊢↑{?⍨10}⍣{×⊃⍺}

Try it online!

Shuffles the digits until valid:

10⊥ decode from base-10 digits to regular number,

 the n

 first elements of

{}⍣{} repeating the function…
?⍨10 shuffle the first ten positive integers
until…
⊃⍺ the first digit of the last attempt
× is positive

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

Python 2, 100 93 92 90 bytes

Thanks to @mbomb007 for shaving off 2 bytes

from random import*
def f(n):k=randint(10**~-n,10**n-1);return(n==len(set(`k`)))*k or f(n)

Tries numbers in the required until one is found with unique digits. I'll bet there's a much cleaner way to do this, but none's coming to mind.

\$\endgroup\$
  • \$\begingroup\$ return(n==len(set(`k`)))*k or f(n). Try it online \$\endgroup\$ – mbomb007 Apr 24 '17 at 21:19
1
\$\begingroup\$

Pyth, 11 bytes

jk<{+OS9.ST
jk<{+OS9.STQ implicit Q

       9     9
      S      [1,2,3,4,5,6,7,8,9]
     O       random element

          T  10
        .S   random permutation of [0,1,2,3,4,5,6,7,8,9]

    +        add the results from the previous two paragraphs together
   {         deduplicate
  <        Q first (input) elements
jk           join by empty string

Uses the same algorithm as Dennis' answer.

Try it online!

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

Perl, 48 bytes

1until$_=1+int rand 10**$n-1,/.{$n}/&&!/(.).*\1/

Explanation:

Repeatedly generate random integers from 1 to 10**$n-1, rejecting them until there is one of the correct length (so at least 10**($n-1)) with no repeated digits.

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

Batch, 156 bytes

@set/af=9,r=x=0
@for /l %%i in (1,1,%1)do @call:c
@echo %r%
@exit/b
:c
@set/a"d=9-%random%%%f,e=x>>d&1
@if %e%==1 goto c
@set/a"r=r*10+d,f=10,x|=1<<d

x maintains a bitmask of used digits. f indicates the number of available digits (counting down from 9). Random digits are generated until an unused digit is found. n=10 could be supported for 165 bytes:

@set/af=9,r=x=0
@for /l %%i in (1,1,%1)do @call:c
@echo %r:~1%
@exit/b
:c
@set/a"d=9-%random%%%f,e=x>>d&1
@if %e%==1 goto c
@set r=%r%%d%
@set/a"f=10,x|=1<<d

(r contains an extra leading zero because it's golfier that way.) Previous approach for 165 bytes special-cased the first digit, and also happened to work with n=10 (the numeric version actually took 166 bytes!):

@set/ar=%random%%%9+1,x=0
@for /l %%i in (2,1,%1)do @set/a"x|=1<<d"&call:c
@echo %r%
@exit/b
:c
@set/a"d=%random%%%10,e=x>>d&1
@if %e%==1 goto c
@set r=%r%%d%

Original approach for 170 bytes also worked for n=10:

@set/ar=%random%%%9+1
@for /l %%i in (2,1,%1)do @call:c
@echo %r%
@exit/b
:c
@set/ad=%random%%%10
@call set s=%%r:%d%=%%
@if not "%s%"=="%r%" goto c
@set r=%r%%d%

Uses string manipulation to detect duplicate digits.

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

Bash, 66 bytes

a=0;while [[ $a == 0* ]];do a=`shuf -i0-9 -n$1|xargs`;done;echo $a

Try it online!

Straight forward, usues shuf, xargs is used to join lines and continues to try while the combination starts with 0.

Cant beat 46 char from other answer but thus is fast!

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

Pyth, 15 28 bytes

=+YhO9VtQ#KOTI!hxYK=+YKB;jkY

Try it here

\$\endgroup\$
  • 1
    \$\begingroup\$ Welcome to PPCG, and great job using a golfing language right off the bat :-) I see 2 small issues: 1) it seems that the second digit is always 0, so I think you'll want to change ^TttQ to ^TtQ (-1 byte, bonus!). 2) all digits in the output must unique, so you'll have to force that to happen somehow. \$\endgroup\$ – ETHproductions Apr 25 '17 at 19:38
  • \$\begingroup\$ @ETHproductions Arg!! Thanks for pointing that out. I've fixed it. \$\endgroup\$ – Maria Apr 25 '17 at 20:16
1
\$\begingroup\$

C#, 127 132 128 126 125 bytes

n=>{var s="";for(int l,r;(l=s.Length)<n;)if((l<1&(r=new System.Random().Next(10))>0)|(l>0&!s.Contains(r+"")))s+=r;return s;};

Try It Online!

Borrowed the idea from @KevinCruijssen's answer to initialise the random, r, in the if statement to save 2 bytes.

Pretty sure this can be golfed further but I don't have time at the moment.


Old version using a while loop:

n=>{var s="";while(s.Length<n){int r=new System.Random().Next(10);if(s.Length<1&r>0)s+=r;else if(!s.Contains(r+""))s+=r;}return s;};
\$\endgroup\$
  • \$\begingroup\$ I don't think this is correct. Let's say the first random integer is 0, it would first try if(s.Length<1&r>0) which is false, but then it will do if(!s.Contains(r+"")) which is true and still append "0" to s as first digit. \$\endgroup\$ – Kevin Cruijssen Apr 25 '17 at 8:38
  • \$\begingroup\$ @KevinCruijssen Fixed and golfed further \$\endgroup\$ – TheLethalCoder Apr 25 '17 at 8:48
  • 1
    \$\begingroup\$ @KevinCruijssen Ah I've worked it out, in your example you don't end the .Next(10)... with a ;. So no further improvements there, but good idea. \$\endgroup\$ – TheLethalCoder Apr 25 '17 at 9:31
  • 1
    \$\begingroup\$ I have just posted it. And oops, you're right I missed that semi-colon.. You can still golf it like this though: n=>{var s="";for(int l=0,r;l<n;l=s.Length)if((l<1&(r=new System.Random().Next(10))>0)|(l>0&!s.Contains(r+"")))r+=x;return s;}; :) \$\endgroup\$ – Kevin Cruijssen Apr 25 '17 at 9:34
  • 1
    \$\begingroup\$ @KevinCruijssen I just borrowed the idea from your answer as you was writing that comment! Nice improvement thanks \$\endgroup\$ – TheLethalCoder Apr 25 '17 at 9:37
1
\$\begingroup\$

C (gcc), 123 122 100 95 104 103 99 97 bytes

This one generating an actual random number

j;f(n){for(int i,k=n,s[10]={j=0};n;s[i+=i?0:k==n]=!s[i]?j+=i*pow(10,--n):1)i=rand()%10;return j;}

Try it online!

C (gcc), 87 85 bytes

Here it is printing a string of digits.

f(n){for(int i,k=n,s[10]={0};n;s[i+=i?0:k==n]=!s[i]?--n,putchar(48+i):1)i=rand()%10;}

Try it online!

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

PHP, 65 63 bytes

while(count(count_chars($x=rand(1,10**$argn),1))<$argn);echo$x;

takes input from STDIN; run with -nR.

create random number between 1 and 10^N inclusive;
repeat while count of distinct characters is < N.

\$\endgroup\$
  • 1
    \$\begingroup\$ while(count(count_chars($x=rand(1,10**$argn),1))<$argn);echo$x; -2 Bytes \$\endgroup\$ – Jörg Hülsermann Apr 27 '17 at 1:56
0
\$\begingroup\$

Mathematica 65 60 Bytes

0For[a=11,Max@DigitCount@a>1,a=RandomInteger[10^{#-1,#}]]+a&

Here is a faster version but adds 9 bytes:

FromDigits@Join[f=(s=RandomSample)[r=Range@9,1],s[r/.f[[1]]->0,#-1]]&
\$\endgroup\$
0
\$\begingroup\$

Java 9 JShell, 86 bytes

n->new Random().longs(0,10).limit(n-1).reduce(new Random().nextInt(9)+1,(a,b)->a*10+b)

Try it online!

Note: I'm not counting the imports as those packages are imported by default in JShell, but there's no Try-it-online link that I know of for JShell, so I've provided one for Java 9 with header and footer code to make it work in that context. In JShell you can just do:

jshell> Function<Integer,Long> f =
   ...> n->new Random().longs(0,10).limit(n-1).reduce(new Random().nextInt(9)+1,(a,b)->a*10+b)
f ==> $Lambda$27/633070006@5702b3b1

And then:

jshell> f.apply(6)
$26 ==> 746202

How it works:

We define a function from Integer to Long and create an infinite stream of random longs in the range from 0-9, limit it to the first n-1 items, then reduce it with a random int from 1-9 as the initial value and a function that multiplies the value by 10 and adds the next value from the stream.

I used longs so this should work for up to about 18 digits (n = 18).

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

C, 96 93 bytes

f(n){char d[11],i=0,r;for(;i++^10;d[i-1]=d[r=rand()%i],d[r]=47+i);*d^48?d[n]=0,puts(d):f(n);}

Fisher-Yates shuffle initialization until the first digit isn't zero.

Is uniform, assuming rand()%i is uniform. (Since for most i RAND_MAX/i leaves a small remainder, there is a very small bias. This bias grows smaller as RAND_MAX grows larger.)

See it work online.

See it generate correct numbers for when n equals 2, as shown in the question.

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

Axiom, 191 bytes

g(a:NNI):Complex INT==(a<1 or a>9=>%i;r:List NNI:=[];b:=a;repeat(a=0=>break;d:=random()$INT rem 10;a=b and d=0=>0;~member?(d,r)=>(a:=a-1;r:=cons(d,r)));reduce(+,[r.i*10^(i-1)for i in 1..#r]))

ungolf it, test result

-- Return one number of 'a' different random digits if 0<a<10
f(a:NNI):Complex INT==
    a<1 or a>9=>%i
    r:List NNI:=[];b:=a
    repeat
       a=0=>break
       d:=random()$INT rem 10
       a=b and d=0  =>0
       ~member?(d,r)=>(a:=a-1;r:=cons(d,r))
    reduce(+,[r.i*10^(i-1)for i in 1..#r])

(4) -> [[i,g(i)] for i in 0..10]
   (4)
   [[0,%i], [1,9], [2,76], [3,135], [4,6810], [5,48675], [6,415768],
    [7,7461539], [8,98421537], [9,825046739], [10,%i]]
                                          Type: List List Complex Integer
(5) -> [[i,g(i)] for i in [3,3,3,3,3,3,3,3,3]]
   (5)
   [[3,653],[3,128],[3,254],[3,268],[3,914],[3,594],[3,276],[3,240],[3,398]]
\$\endgroup\$
0
\$\begingroup\$

Jellyfish, 17 bytes

p
d^u ?
 j?r10
10

Try it online!

Fork of Dennis' Jelly answer.

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

Ruby, 53 52 bytes

Shuffle until the first digit is not 0, then combine the digits and convert to an integer.

->n{a=*0..9;a.shuffle!while a[0]==0;eval a[0,n]*''}

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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