Run time is number of lines, memory usage is max longest line, you can't get better than this (though it's a bit slow because of how it gets random values, and how often)..main
@@ -0,0 +1,44 @@ | |||||
#!/bin/sh - | |||||
# Run time: O(number of lines) | |||||
# Memory: O(longest line) | |||||
# srand seed: | |||||
# "dd if=/dev/random 2>/dev/null | LC_ALL=C tr -d -c 1-9 | dd bs=1 count=19 2>/dev/null" | getline seed; srand(seed) | |||||
# + rand() | |||||
LC_ALL=C awk ' | |||||
function urandom(n) { | |||||
# return random [0, n) | |||||
# maxn needs to be 2**(x*4), and cbs=x | |||||
maxn = 4294967296 | |||||
if (n == 1) | |||||
return 0 | |||||
if (n > maxn) { | |||||
printf("n too large!\n") > "/dev/stderr" | |||||
exit(5) | |||||
} | |||||
for (;;) { | |||||
"dd if=/dev/random | LC_ALL=C tr -c -d 0-9a-f | dd conv=unblock cbs=8" | getline a | |||||
r = ("0x" a) + 0 | |||||
quot = int(maxn / n) * n | |||||
if (r >= quot) | |||||
continue | |||||
return r % n | |||||
} | |||||
} | |||||
{ | |||||
#"jot -r 1 0 " (NR - 1) | getline a | |||||
a = urandom(NR) | |||||
#a = int(rand() * (NR)) | |||||
if (a == 0) | |||||
save = $0 | |||||
} | |||||
END { print save }' |