-------------------------------------------------------------------------------
Get a random number in scripts
For example, produce a number 0 - $LIMIT-1
LIMIT=100
(k/z/ba)sh
echo $(( RANDOM % LIMIT ))
No idea what the modulus is, but it seems around 32000
awk:
awk 'BEGIN{srand();printf "%d\n", '"$LIMIT"'*rand()}'
# awk modulus size testing:
# keep increasing the power of 2 until you get no decimal places
# and the last digit is not always even
#
awk 'BEGIN{srand();printf "%.5f\n", 2^53*rand()}'
date: (only good for getting a starting 'seed')
date=`date +%s`
num=`expr $date \% $LIMIT`
echo $(( ( $$ ^ $(date +%s) ) % LIMIT ))
shuf
# GNU "shuf" can do it but can so a lot more too...
shuf -n 1 -i 0-$((LIMIT-1))
jot
# create N random numbers in a range
jot -r 5 1000 9999
# -> 3435 1811 2641 7472 2528
Shell randomly picking digits...
!/bin/bash
MX="0123456789"
NL="5" # size of the random number wanted
while [ ${n:=1} -le $NL ]
do
NUM="$NUM${MX:$(($RANDOM%${#MX})):1}"
let n+=1
done
echo "$NUM"
Use a "linear congruence pseudo-random number generator"
#!/bin/csh -f
#
# Random limit -- produce random number from 1 to limit
#
set multiplier = 25173
set increment = 13849
set modulus = 65536
set seedfile = $HOME/.rnd # seed file to use
if ( ! -f $seedfile ) then
echo '17' > $seedfile
endif
@ number = ( `cat $seedfile` * $multiplier + $increment ) % $modulus
echo $number > $seedfile
@ number = $number % $1 + 1
echo $number
Use a Linear Feedback Shift Register with appropriate 'taps'
Google for "LFSR" for more information
Use a generate disk uuid (512 bits as hexadecimal with dashes)
NOTE: some parts are not random!
uuidgen
0bd2753a-98c0-4254-9faf-69cbeb16b33e
Advice on generating cryptographic-quality random numbers can be
found in RFC1750.
-------------------------------------------------------------------------------
For Random Passwords and Phrases
See "info/crypto/passwd_generation.txt"
-------------------------------------------------------------------------------
Weighted Random Pick
Create an array of weights into a cumulative distribution.
Only needs to be done once.
Use random.random() to pick a random float 0.0 <= x < total.
Search the distribution using bisect. (binary search)
=======8<--------
from random import random
from bisect import bisect
def weighted_choice(choices):
# prepare total and cumulitive array
values, weights = zip(*choices)
total = 0
cum_weights = []
for w in weights:
total += w
cum_weights.append(total)
# weighted selection
x = random() * total
i = bisect(cum_weights, x)
return values[i]
>>> weighted_choice([("WHITE",90), ("RED",8), ("GREEN",2)])
'WHITE'
=======8<--------
If you need to make more than one choice, split this into two functions, one to
build the cumulative weights and another to bisect to a random point.
-------------------------------------------------------------------------------
Randomize Lists
shuf
The Gnu shuffle command
shuf -n 1 -i 0-$((LIMIT-1))
shuf -n 1 -e hearts diamonds clubs spades
shuf -n 1 /usr/share/dict/words
sort -R
This will sort using hash of each sorting field, producing the same list
such that is essentially randomised. However there are a few caveats.
1/ each run uses a different hash key, so produces a different sort order
2/ elements that have the same sorted field are grouped together!!!
That is output is random but with duplicate input grouped!
Perl "randomize" (personal script)
https://antofthy.gitlab.io/software/#random
Perl script to shuffle the output of a file that was completely
read in using Fisher-Yates method. (A truely random shuffle)
Also see "randomline" (next)
-------------------------------------------------------------------------------
Random Line Pick from a Stream
You can read a file, holding the 'current pick', and replacing that
pick if the probability is of it being selected is correct.
That is rand( N ) < 1 when we just read the Nth line.
From the Original Perl (Camel) Book, page 246 or the cookbook page 284
"Selecting a Random Line from a File"
See my script "randomline"
https://antofthy.gitlab.io/software/#randomline
Alternative (but reads the whole file in memory)
shuf -n 1
-------------------------------------------------------------------------------
Play List Shuffle
A play list of N songs.
Songs should be played at least once every N songs
But are not played within M songs of last time.
Solution 1
* keep a constant record of last M songs played.
* shuffle the list of songs and play in sequence
* if song about to be played was recently played it put M songs later
* repeat when all songs played.
This works, and songs are fully shuffled.
Each song will be played again after N songs
Solution 2
play the songs in list in order.
The oldest song in the queue is 'psuedo-appended' to the play list
Psuedo-append
append the new item to end of list
while chance < 1/M and no more than N-M times <--- ??? to be worked out
swap song to next position up the queue.
The song will always be inserted at least M from from front of the queue
but will more likely added closer to end of the queue, displacing songs
that may not otherwise get played very often.
May be not random enough, unless the chance is carefully worked out.
Some songs may still not play for a long time unless a low chance is used.
In which case you don't see a lot of shuffling.
Solution 3
Never-ending Shuffled Sequences - When Random is too Random
http://kaioa.com/node/53
(not really very good)
-------------------------------------------------------------------------------
Limited Shuffle
Elements in array are shuffled uniformly between +/- N of there current
position.
That included there original position. Elements at edges tend to
shuffle more toward middle but still remain within N of start point
Problems
How to do it without a full duplicate of original data.
Prevent elements being shuffled twice, or even duplicated or lost.
???? Solution -- needed for pixel spread
-------------------------------------------------------------------------------