Generate random numbers without repeating a value: Difference between revisions

→‎{{header|jq}}: Use Knuth shuffle
(→‎{{header|jq}}: simplify)
(→‎{{header|jq}}: Use Knuth shuffle)
Line 171:
 
In this entry, an external source of entropy is used to define a jq
filter, `knuthShuffle`, so that the specific task can then be accomplished using the expression:
filter, `prn_without_repetitions`, which generates a stream of
<lang jq>[range(1;21)] | knuthShuffle</lang>
pseudo-random numbers in the range 0 up to but excluding a specified
value. The specific task can then be expressed as:
<lang jq>(19 | prn_without_repetitions) + 1
</lang>
 
In the following, a bash or bash-like scripting environment is assumed, and the jq command is assumed to be "jq".
Line 181 ⟶ 178:
< /dev/urandom tr -cd '0-9' | fold -w 1 | jq -MRcnr -f program.jq
</lang>
'''program.jq'''
<lang jq># Output: a prn in range(0;$n) except for $exceptions, where $n is `. and $n > 0.`
| def pprn:
if . == 1 then 0
else . as $n
else| ([1, (($n-1)|tostring|length),1]|minmax) as $w
| [limit($w; inputs)] | join("") | tonumber
| if . < $n then $available[.] else ($n | pprn) end
pend;
 
def knuthShuffle:
'''program.jq'''
| ($available|length) as $n
<lang jq># Output: a prn in range(0;$n) except for $exceptions, where $n is . and $n > 0.
| if $n <= 1 then .
def prn($exceptions):
else {i: $n, a: .}
([range(0;.)] - $exceptions) as $available
| until(.i == 0;
| ($available|length) as $n
.[i += -1]);
| def p:
| (.i + 1 | prn) as $j
if $n == 0 then "prn must have a non-empty pool from which to draw" | error
elif $n == 1 then| $available.a[0.i] as $t
| .a[.i] = .a[$j]
else ([(($n-1)|tostring|length),1]|min) as $w
| .a[limit($w; inputs)j] |= join(""$t) | tonumber
| .a
| if . < $n then $available[.] else $n | p end
end;
p;
 
# Output: a stream
def prn_without_repetitions:
. as $n
| foreach range(0;$n) as $i ([];
. as $exceptions
| . + [$n|prn($exceptions)];
.[-1]);
 
# The task:
[range(201;21)] | prn_without_repetitions) + 1;knuthShuffle</lang>
{{out}}
<pre>
2,442

edits