15
\$\begingroup\$

Given an input value \$n\$, construct an array of \$n\$ random 128 bit (unsigned) integers. The integers should be uniformly random.

Your code can use any in built random number generation function it has or you can implement your own. Clearly this challenge is harder (and more fun) in lower level languages.

\$\endgroup\$
10
  • 2
    \$\begingroup\$ If we decide to implement our own RNG, how good does it have to be? (returning the same number repeatedly is technically uniform, if the input seed is) \$\endgroup\$ Commented Jul 25, 2021 at 13:40
  • 1
    \$\begingroup\$ @thedefault better than that :) any rng you find on the internet will be fine \$\endgroup\$
    – user7467
    Commented Jul 25, 2021 at 13:56
  • 8
    \$\begingroup\$ Well, @thedefault.'s rng can be found on the internet... \$\endgroup\$ Commented Jul 25, 2021 at 15:41
  • 1
    \$\begingroup\$ Also, what can we do if language lacks 128-bit integers? Is returning array of 64-bit integers that's twice as long as requested and uniformly random allowed? \$\endgroup\$ Commented Jul 25, 2021 at 15:44
  • 2
    \$\begingroup\$ You can still print out 128 bit integers in decimal as some of the solutions are doing. It's not ideal but better than nothing. \$\endgroup\$
    – user7467
    Commented Jul 25, 2021 at 15:49

27 Answers 27

13
\$\begingroup\$

x86-64 machine code, 10 bytes

Fortunately, there is a built-in RNG. Requires the RDRAND instruction.

00000000: c1e1 020f c7f0 abe2 fac3                 ..........

Disassembled:

shl ecx, 2
label:
 rdrand eax
 stosd
 loop label
ret

Outputs to a pre-allocated buffer in rdi. n is passed in ecx (arrays with 2^30 elements and more are not supported).

Try it online! (a helper function is needed because of the unusual calling convention)

\$\endgroup\$
3
  • 2
    \$\begingroup\$ It's worth noting explicitly that it outputs to a pre-allocated buffer at ES:RDI! Common modern operating systems use a flat segment model, but x86-64 doesn't require/guarantee that. For one byte extra, you can optimize the performance of the code by generating and storing 64-bit values (RDRAND rax; STOSQ). This also allows switching from SHL ecx, 2 (which is 3 bytes) to SHL ecx, 1 (which is 2 bytes), or even ADD ecx, ecx (still 2 bytes). Unfortunately, the 64-bit version of RDRAND is 1 byte larger, as is the 64-bit version of STOS, so it's a net change of +1 byte. \$\endgroup\$
    – Cody Gray
    Commented Jul 26, 2021 at 22:08
  • \$\begingroup\$ Also, forgot to mention in my previous comment that the RDRAND instruction is an optional part of the x86-64 ISA. It is supported by Intel Ivy Bridge and later. This is not an issue for Code Golf, of course, but whenever I've used it, I've preferred to call out that requirement in the title, since that's a stipulation of what environment I'm targeting with my submission. \$\endgroup\$
    – Cody Gray
    Commented Jul 27, 2021 at 3:26
  • \$\begingroup\$ @CodyGray I don't know very much about segments, but Google results say that the cs/ds/ss/es segments always start at zero and end at 2^64 in long mode (and these results don't seem OS-specific). I tried using 64-bit rdrand/stosq, but I also saw that it was 1 byte longer. \$\endgroup\$ Commented Jul 27, 2021 at 4:38
4
\$\begingroup\$

Vyxal, 7 bytes

ƛ₇ƛ₀℅;B

Try it Online!

ƛ       # Map...
 ₇ƛ  ;  # Map 128 to...
   ₀℅   # Random choice from digits of 10
      B # Convert to base 10

Or if it's allowed not to complete within the lifetime of the universe, 5 bytes:

ƛ₇Eʁ℅

Try it Online!

ƛ     # Map...
 ₇E   # 2 ** 128
   ʁ  # Range (0...x)
    ℅ # Choose a random item

It's trying to generate a 2128-item array, do you think it's gonna finish any time soon?

\$\endgroup\$
2
  • \$\begingroup\$ So ₇E℅ gives you a random digit from the decimal value of 2¹²⁸? \$\endgroup\$
    – Neil
    Commented Jul 31, 2021 at 12:25
  • \$\begingroup\$ @Neil Yeah, although I'm trying to change that - see the second-to-last item of this tasklist \$\endgroup\$
    – emanresu A
    Commented Jul 31, 2021 at 20:06
4
\$\begingroup\$

JavaScript (Node.js),  72  70 bytes

Saved 2 bytes thanks to @RedwolfPrograms

The helper function g builds a 128-bit integer, one bit at a time. This seems a bit long...

n=>Array(n).fill(128n).map(g=k=>k--&&BigInt(Math.random()<.5)|2n*g(k))

Try it online!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ I think this saves 2 bytes, by using Array and fill: tio.run/… \$\endgroup\$
    – rydwolf
    Commented Jul 25, 2021 at 17:22
3
\$\begingroup\$

Befunge-98 (PyFunge), 57 37 bytes

&'wa+0> #;\1-:9j;+1?;#*2\_$.1-:!#@_1j

Try it online! Note that the input has to have a trailing space because of a bug in the interpreter.

The part generating a random 128-bit number bit by bit is explained below:

'wa+0> #;\1-:9j;+1?;#*2\_\.@

Try it online!

'wa+                           push loop counter, initially 129
    0                          push initial number 0
     >                         if the IP is coming from the right, turn it around
       #;                      # skips the next instruction
         \                     swap to the loop counter
          1-:                  decrement it and push an additional copy
             9j                skip over the next 9 instructions
                        _      if the loop counter is 0, go right:
                         \.      swap to the number and print it
                           @     terminate the execution
                        _      else, go right:
                     *2\         swap to the number and multiply by 2
                  ?              go into a random direction, if up or down is selected, ? gets executed again
        ;          ;             if right is selected, jump to the next semicolon and continue with the next iteration
     > #;      ;+1               if left, increment the number and go to the next iteration

Animation with 9 instead of 128 bits:

enter image description here

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

Julia 1.0, 18 bytes

!n=rand(UInt128,n)

Try it online!

sorry, boring useful built-in

\$\endgroup\$
2
  • \$\begingroup\$ A great advert for julia. But why such an ancient version? \$\endgroup\$
    – user7467
    Commented Jul 25, 2021 at 19:34
  • \$\begingroup\$ that's the latest version available on TIO, this will of course work for any 1.x version \$\endgroup\$
    – MarcMush
    Commented Jul 25, 2021 at 19:35
3
\$\begingroup\$

C (gcc), 68 42 bytes

f(n,a)char*a;{for(n*=16;n--;)a[n]=rand();}

Try it online!

  • takes an 0 array and the number requested as input

  • the array I taken as *char to be manipulated byte by byte so that we set every 8bit to rand() which is RAND_MAX e.g. At least 32767 and thus guaranteed to affect every bit

  • numbers printed as decimal thanks to this good answer on the topic I copy-pasted-adapted

\$\endgroup\$
6
  • \$\begingroup\$ The upper halves of these random numbers are always very small (and not printed in the TIO link). I think you can replace 64 with 128 and remove the %4. \$\endgroup\$ Commented Jul 25, 2021 at 16:28
  • 1
    \$\begingroup\$ It still doesn't work (and the upper halves still aren't printed in the TIO link) \$\endgroup\$ Commented Jul 25, 2021 at 17:37
  • \$\begingroup\$ Seems to segfault on TIO \$\endgroup\$
    – user7467
    Commented Jul 25, 2021 at 20:22
  • \$\begingroup\$ @Anush yes I operated on 32 chars exceeding a little bit the array lol \$\endgroup\$
    – AZTECCO
    Commented Jul 25, 2021 at 20:32
  • \$\begingroup\$ try this f(n,a)int*a;{for(n*=4;n--;)a[n]=rand();} \$\endgroup\$
    – jdt
    Commented Aug 3, 2021 at 15:31
2
\$\begingroup\$

Python 2

54 53 bytes: Try it online!

lambda n:map(randrange,[4**64]*n)
from random import*

69 bytes: Try it online!

lambda n:[int(os.urandom(i).encode('hex'),i)for i in[16]*n]
import os

Python 3

54 bytes: Try it online!

lambda n:[*map(randbits,[128]*n)]
from secrets import*

57 56 bytes: Try it online!

lambda n:[*map(randrange,[4**64]*n)]
from random import*

70 bytes: Try it online!

lambda n:[int.from_bytes(os.urandom(i),'big')for i in[16]*n]
import os
\$\endgroup\$
7
  • 3
    \$\begingroup\$ 1<<128 can also be 4**64, which saves a byte. \$\endgroup\$ Commented Jul 25, 2021 at 8:09
  • 1
    \$\begingroup\$ You might also want to add eval('uuid.uuid4().int,'*n); it works in both versions of Python as far as I can tell. \$\endgroup\$ Commented Jul 25, 2021 at 8:25
  • \$\begingroup\$ Is uuid random? Isn't it the same every time? \$\endgroup\$
    – user7467
    Commented Jul 25, 2021 at 8:51
  • \$\begingroup\$ @Anush uuid4 is a function to generate a random uuid (docs) \$\endgroup\$
    – ovs
    Commented Jul 25, 2021 at 8:52
  • 2
    \$\begingroup\$ Type 4 UUIDs aren't uniformly random; some bits are fixed. \$\endgroup\$ Commented Jul 25, 2021 at 15:00
2
\$\begingroup\$

PowerShell, 57 bytes 41 bytes

@(1..$n|%{(Random 1.0)*("2*"*128+1|iex)})

Explanation: 1..$n enumerates integers from 1 to $n, % is an alias to ForEach-Object, Random decimal between 0 and 1.0, multiply by 2^128 through this clever obfuscation. @() encapsulates the result in an array, save 3 bytes if a actual array isn't needed.

Try it online!

Original (57 bytes):

@(1..$n|%{(Get-Random -Mi 0.0 -Ma 1)*[Math]::Pow(2,128)})
\$\endgroup\$
3
  • \$\begingroup\$ Welcome to Code Golf, and nice first answer! Be sure to check out our Tips for golfing in Powershell page for ways you can golf your program \$\endgroup\$ Commented Jul 25, 2021 at 22:06
  • \$\begingroup\$ Hi @ssh2ksh! Nice first answer! Make sure you get the $n parameter as an argument. For example: Try it online!. I also changed the power calculation, and removed the @() that is not needed in this context \$\endgroup\$
    – Julian
    Commented Jul 25, 2021 at 23:44
  • 1
    \$\begingroup\$ Rearranged to have less tb digits and less stuff after Random Try it online! \$\endgroup\$
    – Julian
    Commented Jul 26, 2021 at 2:52
2
\$\begingroup\$

Factor, 33 31 bytes

[ [ 128 2^ random ] replicate ]

Try it online!

  • replicate Create a sequence given a number of elements and a generating quotation.
  • 128 2^ 2128
  • random Return a uniformly random number (via Factor's default Mersenne Twister PRNG) from 0 to whatever number is on top of the data stack minus one.
\$\endgroup\$
2
\$\begingroup\$

Wolfram Language (Mathematica), 25 24 bytes

–1 byte thanks to Bubbler!

RandomInteger[4^64-1,#]&

Try it online!

I wrote this and even I can't find anything interesting to say about it

\$\endgroup\$
3
  • 2
    \$\begingroup\$ Change 2^128 to 4^64 to save a byte. \$\endgroup\$
    – Bubbler
    Commented Jul 26, 2021 at 3:43
  • \$\begingroup\$ The shortest answer containing the word random? Everything is interesting in at least one way :) \$\endgroup\$
    – user7467
    Commented Jul 26, 2021 at 5:40
  • 1
    \$\begingroup\$ @Anush I applaud your glass-half-full attitude :) \$\endgroup\$ Commented Jul 26, 2021 at 7:03
2
\$\begingroup\$

Excel, 62 bytes

=MID(CONCAT((RANDARRAY(A1*128)>0.5)*1),SEQUENCE(A1,,,128),128)

Link to Spreadsheet

Excel doesn't handle 128 bit integers. What this returns is technically n strings of 128 random 1s and 0s, which could be interpreted as n 128 bit binary integers. If Excel did handle 128 bit integers, then answer would be =RANDARRAY(A1,,,2^128-1,1) which is 26 bytes.

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

R, 24 22 bytes

Edit: -1 byte thanks to pajonk

runif(scan())*4^64%/%1

Try it online!

Output is an integer uniformly selected from the range 0...2^128-1.
R does not natively support 128-bit inteters, so the data type of the output is a floating-point representation (click here for a TIO link that dispays all the digits, instead of displaying in scientific notation). Note though that although 128-bit numbers can be represented using floating-point variables, rounding inaccuracies can occur when more than 53 bits are required.

If floating point output (with its associated rounding inaccuracies) isn't Ok, we can output the exact value in the form of a vector of binary digits for 35 bytes (or flattened into a string of bits for 41 bytes).

If neither floating point nor binary output are Ok, then base-R will struggle a bit, but we can still manage by constructing string of random 0-9 digits (so including leading zeros), and checking that its lexicographically smaller than "340282366920938463463374607431768211456", for a whopping 117 113 bytes:
for(i in 1:scan())show({while((a=Reduce(paste0,sample(0:9,39,T)))>"340282366920938463463374607431768211456")0;a})

\$\endgroup\$
5
  • \$\begingroup\$ How do the floating point numbers have enough precision for 128 bits? \$\endgroup\$
    – user7467
    Commented Jul 26, 2021 at 5:42
  • \$\begingroup\$ @Anush - They don't. It wasn't clear to me from the challenge whether this was a requirement (if it is it should probably be specified explicitly, see here). However, I do realise that this was an obvious limitation of the approach: hence the two other versions. \$\endgroup\$ Commented Jul 26, 2021 at 5:56
  • \$\begingroup\$ Thanks. It's a very nice set of answers all in. My thoughts were that the uniform requirement would already imply full precision. Is that wrong? \$\endgroup\$
    – user7467
    Commented Jul 26, 2021 at 6:01
  • \$\begingroup\$ -1 byte \$\endgroup\$
    – pajonk
    Commented Jul 26, 2021 at 7:32
  • \$\begingroup\$ @pajonk - Thank you! \$\endgroup\$ Commented Jul 26, 2021 at 8:06
2
\$\begingroup\$

JavaScript (Browser), 99 bytes

n=>crypto.getRandomValues(a=new BigUint64Array(n*2)).reduce((r,v,i)=>i&1?[v<<64n|a[i^1],...r]:r,[])

This feature is introduced eailer this month by this post. And it currently requires a recent version of Firefox / Chromium Nightly build to run.

It is a sad story that words crypto, getRandomValues, BigUint64Array are too long for golfing.

const f=

n=>crypto.getRandomValues(a=new BigUint64Array(n*2)).reduce((r,v,i)=>i&1?[v<<64n|a[i^1],...r]:r,[])

{
let len = 5;
let arr = f(len);
for (let i = 0; i < arr.length; i++) {
  console.log(arr[i] + '')
}
}

\$\endgroup\$
8
  • \$\begingroup\$ No TIO possible? \$\endgroup\$
    – user7467
    Commented Jul 26, 2021 at 6:55
  • \$\begingroup\$ @Anush No, this feature is added this month while TIO is outdated yearly. \$\endgroup\$
    – tsh
    Commented Jul 26, 2021 at 7:14
  • \$\begingroup\$ Which feature exactly was added? \$\endgroup\$
    – user7467
    Commented Jul 26, 2021 at 7:29
  • \$\begingroup\$ crypto.getRandomValues only support (U)Int(8|16|32)Array but not Big(U)Int64Array before. Try to passing BigUint64Array to crypto.getRandomValues will cause an exception before. \$\endgroup\$
    – tsh
    Commented Jul 26, 2021 at 7:32
  • 2
    \$\begingroup\$ @Anush Also, window.crypto is only available in browsers. If you are using Node.js 15+, you may need to write require('crypto').webcrypto instead of crypto. \$\endgroup\$
    – tsh
    Commented Jul 26, 2021 at 7:37
2
\$\begingroup\$

05AB1E, 7 bytes

LεžyoÝΩ

No TIO, since it won't finish anyway.

Explanation:

L        # Push a list in the range [1, (implicit) input-integer]
 ε       # Map each to:
  žy     #  Push builtin 128
    o    #  Pop and push 2 to the power this 128
     Ý   #  Pop and push a list in the range [0, 2^128]
      Ω  #  Pop and push a random item from this list
         # (after which the result is output implicitly)
\$\endgroup\$
2
\$\begingroup\$

MathGolf, 5 bytes

É♣ów]

Try it online.

Explanation:

É      # Loop the (implicit) input amount of times,
       # using the following three characters as inner code-block:
 ♣     #  Push builtin 128
  ó    #  Pop and push 2**128
   w   #  Pop and push a random integer in the range [0,2**128)
]      # After the loop, wrap the entire stack into an array
       # (after which the entire stack is output implicitly as result)
\$\endgroup\$
1
\$\begingroup\$

Ruby, 29 Bytes

->n{n.times.map{rand 2**128}}

Try It Online

\$\endgroup\$
1
  • 1
    \$\begingroup\$ 27 bytes \$\endgroup\$
    – Dingus
    Commented Jul 25, 2021 at 23:43
1
\$\begingroup\$

Raku, 17 bytes

{roll ^4**64: $_}

Try it online!

^4**64 is the range of numbers [0, 2¹²⁸). The roll method returns randomly selected numbers from that range, in the quantity of $_, the input argument.

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

Scala, 49 bytes

def f(n:Int)=Seq.fill(n)(BigInt(128,util.Random))

Try it online!

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

Racket srfi/27, 45 bytes

(for/list([i n])(*(random-real)(expt 2 128)))

Try it online!

depends on srfi/27 package

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Welcome to code golf, and nice answer! Just so you know, when a submission uses a certain package, it's common practice to put those next to the name of the language, e.g. "Racket srfi/27, 45 bytes" \$\endgroup\$ Commented Aug 2, 2021 at 12:14
  • 1
    \$\begingroup\$ @AaronMiller I don't think that's common practice. I'd probably assume the string next to the name is a command line argument. And a note in the post is sufficient. \$\endgroup\$ Commented Aug 3, 2021 at 4:06
1
\$\begingroup\$

C (gcc), 59 bytes

f(n){int*a=malloc(n*16),i=0;for(;i<n*4;)a[i++]=rand();n=a;}

Try it online!

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

Python 3.8 (pre-release), 56 bytes

lambda n:eval('randint(0,4**64),'*n)
from random import*

Try it online!

Doesn't work for n=0.

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

Rust with rand, 59 bytes

|n|->Vec<u128>{vec![0;n].iter().map(|_|random()).collect()}

Try it on Rust Playground!

vec![0;n] is a built-in macro that generates a Vec of length n with all values initialized to 0. While this macro does accept an expression as the first argument, unfortunately it only evaluates it once, not for each item. Otherwise everything from .iter() to the end wouldn't be needed.

I was excited when I realised Rust has native support for 128-bit integer primitives through i128 and u128, but then I realised Rust's stdlib no longer includes RNG features, meaning we need the rand crate to handle RNG. random() is from the rand crate. Specifically random() is an alias for thread_rng().gen() and generates a random value of the given, or inferred type.
Thankfully, rust's type inference is good enough that, even though we only specify u128 in the return type of the closure, it figures it out and calls random::<u128>()

\$\endgroup\$
1
  • \$\begingroup\$ Another reason to love rust! And that you can print them out easily, unlike in C/C++. \$\endgroup\$
    – user7467
    Commented Nov 17, 2021 at 11:05
0
\$\begingroup\$

Jelly, 7 bytes

Ø⁷2*X’)

Try it online!

A monadic link taking a single argument and returning a list of random 128-bit unsigned integers of that length.

Explanation

      ) | For each value from 1..n
Ø⁷      | 128
  2*    | 2 ** that
    X   | Random Int from 1 to that
     ’  | Subtract 1

If the output can be from 1 to \$2^{128}\$ rather than 0 to \$2^{128} - 1\$, which for practical purposes is almost the same given how unlikely it is to generate the extremes, I can shave off a byte.

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

Perl 5, 51 bytes

sub{join('',map chr rand 256,1..16*pop)=~/.{16}/sg}

Try it online!

Creates n random 128 bit integers. Or n strings of 16 random 8 bit chars. How to print the array elements as decimal numbers can be seen by clicking the "Try it online" link.

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

Japt, 7 bytes

ÇMq2pIÑ
Ç       // Create the range [0..U) where U is the input, then map each value to
 Mq     // a random non-negative integer smaller than
   2    // 2
    p   // to the power of
     IÑ // 64 * 2.

Try it here.

\$\endgroup\$
1
  • 3
    \$\begingroup\$ I don't think the output format has enough precision to represent all integers between 0 and 2^128-1. \$\endgroup\$
    – Bubbler
    Commented Jul 26, 2021 at 1:26
0
\$\begingroup\$

CJam, 20 19 bytes

ri{L{2mr+}128*2bN}*

Try it online!

CJam, 27 24 bytes (Old method)

ri{8,{G*YG#(mr\m<}%:+N}*

Try it online!

Edit: had a better idea using the "repeat N times" operator. Saved 3 characters.

Edit 2: tried a completely new algorithm. Saved 4 characters.

Edit 3: went for the string manipulation side of things. Saved 1 character.

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

Charcoal, 10 bytes

IEN‽X²¦¹²⁸

Try it online! Link is to verbose version of code. Explanation:

  N         Input integer
 E          Map over implicit range
    X²¦¹²⁸  2¹²⁸
   ‽        Random integer (0-indexed)
I           Cast to string
            Implicitly print
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.