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 }' | |||||