1

I want to pseudo-randomly pick one element from an array of 5 elements: I want to control the occurrence probability of each of those 5 elements.

Example: I have an array like this: [A B C D E]

  • I want the probability to pick A: 0.10 (10%)
  • I want the probability to pick B: 0.10 (10%)
  • I want the probability to pick C: 0.20 (20%)
  • I want the probability to pick D: 0.20 (20%)
  • I want the probability to pick E: 0.40 (40%)

I have seen that I can weight a random selection from an array here: Weighted random selection from array.

How can I weight elements contained in an array like this?

TylerH
  • 20,799
  • 66
  • 75
  • 101
charlesD
  • 27
  • 5

1 Answers1

2

You'd use the bash builtin variable RANDOM, with a little arithmetic

weighted_selection() {
    local ary=("$@")
    case $(( RANDOM % 10 )) in
        0) index=0 ;;      # one out of ten
        1) index=1 ;;      # one out of ten
        2|3) index=2 ;;    # two out of ten
        4|5) index=3 ;;    # two out of ten
        *) index=4 ;;      # remaining is four out of ten
    esac
    echo ${ary[index]}
}

Let's test it:

a=(A B C D E)
declare -A count
for ((i=1; i<1000; i++)); do
    (( count[$(weighted_selection "${a[@]}")]++ ))
done
declare -p count

outputs

declare -A count='([A]="99" [B]="100" [C]="211" [D]="208" [E]="381" )'
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • 1
    `RANDOM` ranges from 0 to 32767, so this really produces a distribution like 10.006%/10.006%/20.012%/20.012%/39.99%. If that difference matters (and it probably shouldn't), you could do something like `x=32768; until (( x < 32760 )); x=$RANDOM`, then check `$x % 10`. – chepner Mar 06 '19 at 01:05
  • does it have go version for this algo? – Soma Hesk Mar 06 '19 at 08:54