------------------------------------------------------------------------------- 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)) sort seq 0 $((LIMIT-1)) | sort -R | head -1 jot # create 5 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 Generating 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 (or "--random-sort") This will sort using hash of each sorting field, randomising the input order. 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 lines 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 first) 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 last song played 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 includes 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 needing a duplicate of original data. Prevent elements being shuffled twice, or even duplicated or lost. ???? Solution -- needed for pixel spread -------------------------------------------------------------------------------