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.
-
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\$the default.– the default.2021年07月25日 13:40:21 +00:00Commented Jul 25, 2021 at 13:40
-
1\$\begingroup\$ @thedefault better than that :) any rng you find on the internet will be fine \$\endgroup\$user7467– user74672021年07月25日 13:56:47 +00:00Commented Jul 25, 2021 at 13:56
-
8\$\begingroup\$ Well, @thedefault.'s rng can be found on the internet... \$\endgroup\$val - disappointed in SE– val - disappointed in SE2021年07月25日 15:41:02 +00:00Commented 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\$val - disappointed in SE– val - disappointed in SE2021年07月25日 15:44:54 +00:00Commented 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– user74672021年07月25日 15:49:32 +00:00Commented Jul 25, 2021 at 15:49
27 Answers 27
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)
-
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 fromSHL ecx, 2
(which is 3 bytes) toSHL ecx, 1
(which is 2 bytes), or evenADD ecx, ecx
(still 2 bytes). Unfortunately, the 64-bit version ofRDRAND
is 1 byte larger, as is the 64-bit version ofSTOS
, so it's a net change of +1 byte. \$\endgroup\$Cody Gray– Cody Gray2021年07月26日 22:08:56 +00:00Commented 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– Cody Gray2021年07月27日 03:26:05 +00:00Commented 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\$the default.– the default.2021年07月27日 04:38:58 +00:00Commented Jul 27, 2021 at 4:38
Vyxal, 7 bytes
ƛ7ƛ0c/o;B
ƛ # Map...
7ƛ ; # Map 128 to...
0c/o # 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:
ƛ7Eʁc/o
ƛ # Map...
7E # 2 ** 128
ʁ # Range (0...x)
c/o # Choose a random item
It's trying to generate a 2128-item array, do you think it's gonna finish any time soon?
-
\$\begingroup\$ So
7Ec/o
gives you a random digit from the decimal value of2¹²8
? \$\endgroup\$Neil– Neil2021年07月31日 12:25:10 +00:00Commented 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– emanresu A2021年07月31日 20:06:56 +00:00Commented Jul 31, 2021 at 20:06
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))
-
1
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\_\.@
'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:
-
\$\begingroup\$ A great advert for julia. But why such an ancient version? \$\endgroup\$user7467– user74672021年07月25日 19:34:06 +00:00Commented 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– MarcMush2021年07月25日 19:35:13 +00:00Commented Jul 25, 2021 at 19:35
C (gcc), (削除) 68 (削除ここまで) 42 bytes
f(n,a)char*a;{for(n*=16;n--;)a[n]=rand();}
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
-
\$\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\$the default.– the default.2021年07月25日 16:28:43 +00:00Commented 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\$the default.– the default.2021年07月25日 17:37:14 +00:00Commented Jul 25, 2021 at 17:37
-
\$\begingroup\$ Seems to segfault on TIO \$\endgroup\$user7467– user74672021年07月25日 20:22:55 +00:00Commented Jul 25, 2021 at 20:22
-
\$\begingroup\$ @Anush yes I operated on 32 chars exceeding a little bit the array lol \$\endgroup\$AZTECCO– AZTECCO2021年07月25日 20:32:42 +00:00Commented Jul 25, 2021 at 20:32
-
\$\begingroup\$ try this
f(n,a)int*a;{for(n*=4;n--;)a[n]=rand();}
\$\endgroup\$jdt– jdt2021年08月03日 15:31:16 +00:00Commented Aug 3, 2021 at 15:31
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
-
3\$\begingroup\$
1<<128
can also be4**64
, which saves a byte. \$\endgroup\$dingledooper– dingledooper2021年07月25日 08:09:37 +00:00Commented 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\$dingledooper– dingledooper2021年07月25日 08:25:52 +00:00Commented Jul 25, 2021 at 8:25 -
\$\begingroup\$ Is uuid random? Isn't it the same every time? \$\endgroup\$user7467– user74672021年07月25日 08:51:15 +00:00Commented Jul 25, 2021 at 8:51
-
-
2\$\begingroup\$ Type 4 UUIDs aren't uniformly random; some bits are fixed. \$\endgroup\$the default.– the default.2021年07月25日 15:00:55 +00:00Commented Jul 25, 2021 at 15:00
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.
Original (57 bytes):
@(1..$n|%{(Get-Random -Mi 0.0 -Ma 1)*[Math]::Pow(2,128)})
-
\$\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\$2021年07月25日 22:06:53 +00:00Commented 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– Julian2021年07月25日 23:44:10 +00:00Commented Jul 25, 2021 at 23:44 -
1\$\begingroup\$ Rearranged to have less
tb
digits and less stuff afterRandom
Try it online! \$\endgroup\$Julian– Julian2021年07月26日 02:52:33 +00:00Commented Jul 26, 2021 at 2:52
Factor, (削除) 33 (削除ここまで) 31 bytes
[ [ 128 2^ random ] replicate ]
replicate
Create a sequence given a number of elements and a generating quotation.128 2^
2128random
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.
Wolfram Language (Mathematica), (削除) 25 (削除ここまで) 24 bytes
–1 byte thanks to Bubbler!
RandomInteger[4^64-1,#]&
I wrote this and even I can't find anything interesting to say about it
-
2\$\begingroup\$ Change
2^128
to4^64
to save a byte. \$\endgroup\$Bubbler– Bubbler2021年07月26日 03:43:36 +00:00Commented Jul 26, 2021 at 3:43 -
\$\begingroup\$ The shortest answer containing the word random? Everything is interesting in at least one way :) \$\endgroup\$user7467– user74672021年07月26日 05:40:40 +00:00Commented Jul 26, 2021 at 5:40
-
1\$\begingroup\$ @Anush I applaud your glass-half-full attitude :) \$\endgroup\$Greg Martin– Greg Martin2021年07月26日 07:03:59 +00:00Commented Jul 26, 2021 at 7:03
Excel, 62 bytes
=MID(CONCAT((RANDARRAY(A1*128)>0.5)*1),SEQUENCE(A1,,,128),128)
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.
R, (削除) 24 (削除ここまで) 22 bytes
Edit: -1 byte thanks to pajonk
runif(scan())*4^64%/%1
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})
-
\$\begingroup\$ How do the floating point numbers have enough precision for 128 bits? \$\endgroup\$user7467– user74672021年07月26日 05:42:22 +00:00Commented 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\$Dominic van Essen– Dominic van Essen2021年07月26日 05:56:20 +00:00Commented 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– user74672021年07月26日 06:01:09 +00:00Commented Jul 26, 2021 at 6:01
-
-
\$\begingroup\$ @pajonk - Thank you! \$\endgroup\$Dominic van Essen– Dominic van Essen2021年07月26日 08:06:21 +00:00Commented Jul 26, 2021 at 8:06
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] + '')
}
}
-
\$\begingroup\$ No TIO possible? \$\endgroup\$user7467– user74672021年07月26日 06:55:14 +00:00Commented Jul 26, 2021 at 6:55
-
\$\begingroup\$ @Anush No, this feature is added this month while TIO is outdated yearly. \$\endgroup\$tsh– tsh2021年07月26日 07:14:09 +00:00Commented Jul 26, 2021 at 7:14
-
\$\begingroup\$ Which feature exactly was added? \$\endgroup\$user7467– user74672021年07月26日 07:29:20 +00:00Commented Jul 26, 2021 at 7:29
-
\$\begingroup\$
crypto.getRandomValues
only support(U)Int(8|16|32)Array
but notBig(U)Int64Array
before. Try to passingBigUint64Array
tocrypto.getRandomValues
will cause an exception before. \$\endgroup\$tsh– tsh2021年07月26日 07:32:31 +00:00Commented 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 writerequire('crypto').webcrypto
instead ofcrypto
. \$\endgroup\$tsh– tsh2021年07月26日 07:37:34 +00:00Commented Jul 26, 2021 at 7:37
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)
MathGolf, 5 bytes
É♣ów]
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)
-
1
Raku, 17 bytes
{roll ^4**64: $_}
^4**64
is the range of numbers [0, 2128). The roll
method returns randomly selected numbers from that range, in the quantity of $_
, the input argument.
-
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\$Aaroneous Miller– Aaroneous Miller2021年08月02日 12:14:13 +00:00Commented 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\$the default.– the default.2021年08月03日 04:06:50 +00:00Commented Aug 3, 2021 at 4:06
Python 3.8 (pre-release), 56 bytes
lambda n:eval('randint(0,4**64),'*n)
from random import*
Doesn't work for n=0
.
Rust with rand
, 59 bytes
|n|->Vec<u128>{vec![0;n].iter().map(|_|random()).collect()}
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>()
-
\$\begingroup\$ Another reason to love rust! And that you can print them out easily, unlike in C/C++. \$\endgroup\$user7467– user74672021年11月17日 11:05:20 +00:00Commented Nov 17, 2021 at 11:05
Jelly, 7 bytes
Ø72*X’)
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
Ø7 | 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.
Perl 5, 51 bytes
sub{join('',map chr rand 256,1..16*pop)=~/.{16}/sg}
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.
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.
-
3\$\begingroup\$ I don't think the output format has enough precision to represent all integers between 0 and 2^128-1. \$\endgroup\$Bubbler– Bubbler2021年07月26日 01:26:01 +00:00Commented Jul 26, 2021 at 1:26
CJam, (削除) 20 (削除ここまで) 19 bytes
ri{L{2mr+}128*2bN}*
CJam, (削除) 27 (削除ここまで) 24 bytes (Old method)
ri{8,{G*YG#(mr\m<}%:+N}*
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.
Charcoal, 10 bytes
IEN‽X2¦128
Try it online! Link is to verbose version of code. Explanation:
N Input integer
E Map over implicit range
X2¦128 2128
‽ Random integer (0-indexed)
I Cast to string
Implicitly print