How do I specify chance when setting a variable to random item in array?












6















Currently I do something like this to set a variable to a random item in an array:



array=("foo" "bar" "baz")

var=${array[$RANDOM % ${#array[@]} ]}


How would I do if I want to set $var to one of these values, but specify the chance that the variable will be set to the value of each item respectively? Say I want a 73,3% chance for foo, 26,6% chance for bar, and 0,1% chance for baz.










share|improve this question

























  • Are you allowed to use only bash builtins and no external programs?

    – Mark Plotnick
    yesterday











  • @MarkPlotnick I would prefer bash, but anything that I can run from the command line works

    – DisplayName
    yesterday
















6















Currently I do something like this to set a variable to a random item in an array:



array=("foo" "bar" "baz")

var=${array[$RANDOM % ${#array[@]} ]}


How would I do if I want to set $var to one of these values, but specify the chance that the variable will be set to the value of each item respectively? Say I want a 73,3% chance for foo, 26,6% chance for bar, and 0,1% chance for baz.










share|improve this question

























  • Are you allowed to use only bash builtins and no external programs?

    – Mark Plotnick
    yesterday











  • @MarkPlotnick I would prefer bash, but anything that I can run from the command line works

    – DisplayName
    yesterday














6












6








6








Currently I do something like this to set a variable to a random item in an array:



array=("foo" "bar" "baz")

var=${array[$RANDOM % ${#array[@]} ]}


How would I do if I want to set $var to one of these values, but specify the chance that the variable will be set to the value of each item respectively? Say I want a 73,3% chance for foo, 26,6% chance for bar, and 0,1% chance for baz.










share|improve this question
















Currently I do something like this to set a variable to a random item in an array:



array=("foo" "bar" "baz")

var=${array[$RANDOM % ${#array[@]} ]}


How would I do if I want to set $var to one of these values, but specify the chance that the variable will be set to the value of each item respectively? Say I want a 73,3% chance for foo, 26,6% chance for bar, and 0,1% chance for baz.







command-line variable array random






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited yesterday









terdon

130k32254432




130k32254432










asked yesterday









DisplayNameDisplayName

4,48094580




4,48094580













  • Are you allowed to use only bash builtins and no external programs?

    – Mark Plotnick
    yesterday











  • @MarkPlotnick I would prefer bash, but anything that I can run from the command line works

    – DisplayName
    yesterday



















  • Are you allowed to use only bash builtins and no external programs?

    – Mark Plotnick
    yesterday











  • @MarkPlotnick I would prefer bash, but anything that I can run from the command line works

    – DisplayName
    yesterday

















Are you allowed to use only bash builtins and no external programs?

– Mark Plotnick
yesterday





Are you allowed to use only bash builtins and no external programs?

– Mark Plotnick
yesterday













@MarkPlotnick I would prefer bash, but anything that I can run from the command line works

– DisplayName
yesterday





@MarkPlotnick I would prefer bash, but anything that I can run from the command line works

– DisplayName
yesterday










2 Answers
2






active

oldest

votes


















5














One way: set up a parallel array with the corresponding percentage chances; below, I've scaled them to 1000. Then, choose a random number between 1 and 1000 and iterate through the array until you've run out of chances:



#!/bin/bash

array=( "foo" "bar" "baz")
chances=(733 266 1)

choice=$((1 + (RANDOM % 1000)))
value=

for((index=0; index < ${#array[@]}; index++))
do
choice=$((choice - ${chances[index]}))
if [[ choice -le 0 ]]
then
value=${array[index]}
break
fi
done

[[ index -eq ${#array[@]} ]] && value=${array[index]}
printf '%sn' "$value"





share|improve this answer
























  • I've also used this method before. It works well. However: it might be worth to calculate the sum dynamically. If it's not actually 1000, you get the wrong results. Also, if RANDOM is limited to 32768, there might be some random bias in the selection.

    – frostschutz
    yesterday











  • Great points, frostschutz; I didn't do any error-checking of the sums, since I assumed they were all assigned manually.

    – Jeff Schaller
    yesterday



















5














The shell can't do floating point math, but if we just move the decimal point, we can use $RANDOM and integer math:



#!/usr/local/bin/bash
array=("foo" "bar" "baz")
dieroll=$(($RANDOM % 1000))

if [[ "$dieroll" -lt 1 ]]; then
printf "%sn" "${array[2]}"
elif [[ "$dieroll" -lt 266 ]]; then
printf "%sn" "${array[1]}"
else
printf "%sn" "${array[0]}"
fi


This has the advantages of not having to blow the array up to 1000 entries or needing any for loops.






share|improve this answer

























    Your Answer








    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "106"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f498638%2fhow-do-i-specify-chance-when-setting-a-variable-to-random-item-in-array%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    5














    One way: set up a parallel array with the corresponding percentage chances; below, I've scaled them to 1000. Then, choose a random number between 1 and 1000 and iterate through the array until you've run out of chances:



    #!/bin/bash

    array=( "foo" "bar" "baz")
    chances=(733 266 1)

    choice=$((1 + (RANDOM % 1000)))
    value=

    for((index=0; index < ${#array[@]}; index++))
    do
    choice=$((choice - ${chances[index]}))
    if [[ choice -le 0 ]]
    then
    value=${array[index]}
    break
    fi
    done

    [[ index -eq ${#array[@]} ]] && value=${array[index]}
    printf '%sn' "$value"





    share|improve this answer
























    • I've also used this method before. It works well. However: it might be worth to calculate the sum dynamically. If it's not actually 1000, you get the wrong results. Also, if RANDOM is limited to 32768, there might be some random bias in the selection.

      – frostschutz
      yesterday











    • Great points, frostschutz; I didn't do any error-checking of the sums, since I assumed they were all assigned manually.

      – Jeff Schaller
      yesterday
















    5














    One way: set up a parallel array with the corresponding percentage chances; below, I've scaled them to 1000. Then, choose a random number between 1 and 1000 and iterate through the array until you've run out of chances:



    #!/bin/bash

    array=( "foo" "bar" "baz")
    chances=(733 266 1)

    choice=$((1 + (RANDOM % 1000)))
    value=

    for((index=0; index < ${#array[@]}; index++))
    do
    choice=$((choice - ${chances[index]}))
    if [[ choice -le 0 ]]
    then
    value=${array[index]}
    break
    fi
    done

    [[ index -eq ${#array[@]} ]] && value=${array[index]}
    printf '%sn' "$value"





    share|improve this answer
























    • I've also used this method before. It works well. However: it might be worth to calculate the sum dynamically. If it's not actually 1000, you get the wrong results. Also, if RANDOM is limited to 32768, there might be some random bias in the selection.

      – frostschutz
      yesterday











    • Great points, frostschutz; I didn't do any error-checking of the sums, since I assumed they were all assigned manually.

      – Jeff Schaller
      yesterday














    5












    5








    5







    One way: set up a parallel array with the corresponding percentage chances; below, I've scaled them to 1000. Then, choose a random number between 1 and 1000 and iterate through the array until you've run out of chances:



    #!/bin/bash

    array=( "foo" "bar" "baz")
    chances=(733 266 1)

    choice=$((1 + (RANDOM % 1000)))
    value=

    for((index=0; index < ${#array[@]}; index++))
    do
    choice=$((choice - ${chances[index]}))
    if [[ choice -le 0 ]]
    then
    value=${array[index]}
    break
    fi
    done

    [[ index -eq ${#array[@]} ]] && value=${array[index]}
    printf '%sn' "$value"





    share|improve this answer













    One way: set up a parallel array with the corresponding percentage chances; below, I've scaled them to 1000. Then, choose a random number between 1 and 1000 and iterate through the array until you've run out of chances:



    #!/bin/bash

    array=( "foo" "bar" "baz")
    chances=(733 266 1)

    choice=$((1 + (RANDOM % 1000)))
    value=

    for((index=0; index < ${#array[@]}; index++))
    do
    choice=$((choice - ${chances[index]}))
    if [[ choice -le 0 ]]
    then
    value=${array[index]}
    break
    fi
    done

    [[ index -eq ${#array[@]} ]] && value=${array[index]}
    printf '%sn' "$value"






    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered yesterday









    Jeff SchallerJeff Schaller

    40.9k1056130




    40.9k1056130













    • I've also used this method before. It works well. However: it might be worth to calculate the sum dynamically. If it's not actually 1000, you get the wrong results. Also, if RANDOM is limited to 32768, there might be some random bias in the selection.

      – frostschutz
      yesterday











    • Great points, frostschutz; I didn't do any error-checking of the sums, since I assumed they were all assigned manually.

      – Jeff Schaller
      yesterday



















    • I've also used this method before. It works well. However: it might be worth to calculate the sum dynamically. If it's not actually 1000, you get the wrong results. Also, if RANDOM is limited to 32768, there might be some random bias in the selection.

      – frostschutz
      yesterday











    • Great points, frostschutz; I didn't do any error-checking of the sums, since I assumed they were all assigned manually.

      – Jeff Schaller
      yesterday

















    I've also used this method before. It works well. However: it might be worth to calculate the sum dynamically. If it's not actually 1000, you get the wrong results. Also, if RANDOM is limited to 32768, there might be some random bias in the selection.

    – frostschutz
    yesterday





    I've also used this method before. It works well. However: it might be worth to calculate the sum dynamically. If it's not actually 1000, you get the wrong results. Also, if RANDOM is limited to 32768, there might be some random bias in the selection.

    – frostschutz
    yesterday













    Great points, frostschutz; I didn't do any error-checking of the sums, since I assumed they were all assigned manually.

    – Jeff Schaller
    yesterday





    Great points, frostschutz; I didn't do any error-checking of the sums, since I assumed they were all assigned manually.

    – Jeff Schaller
    yesterday













    5














    The shell can't do floating point math, but if we just move the decimal point, we can use $RANDOM and integer math:



    #!/usr/local/bin/bash
    array=("foo" "bar" "baz")
    dieroll=$(($RANDOM % 1000))

    if [[ "$dieroll" -lt 1 ]]; then
    printf "%sn" "${array[2]}"
    elif [[ "$dieroll" -lt 266 ]]; then
    printf "%sn" "${array[1]}"
    else
    printf "%sn" "${array[0]}"
    fi


    This has the advantages of not having to blow the array up to 1000 entries or needing any for loops.






    share|improve this answer






























      5














      The shell can't do floating point math, but if we just move the decimal point, we can use $RANDOM and integer math:



      #!/usr/local/bin/bash
      array=("foo" "bar" "baz")
      dieroll=$(($RANDOM % 1000))

      if [[ "$dieroll" -lt 1 ]]; then
      printf "%sn" "${array[2]}"
      elif [[ "$dieroll" -lt 266 ]]; then
      printf "%sn" "${array[1]}"
      else
      printf "%sn" "${array[0]}"
      fi


      This has the advantages of not having to blow the array up to 1000 entries or needing any for loops.






      share|improve this answer




























        5












        5








        5







        The shell can't do floating point math, but if we just move the decimal point, we can use $RANDOM and integer math:



        #!/usr/local/bin/bash
        array=("foo" "bar" "baz")
        dieroll=$(($RANDOM % 1000))

        if [[ "$dieroll" -lt 1 ]]; then
        printf "%sn" "${array[2]}"
        elif [[ "$dieroll" -lt 266 ]]; then
        printf "%sn" "${array[1]}"
        else
        printf "%sn" "${array[0]}"
        fi


        This has the advantages of not having to blow the array up to 1000 entries or needing any for loops.






        share|improve this answer















        The shell can't do floating point math, but if we just move the decimal point, we can use $RANDOM and integer math:



        #!/usr/local/bin/bash
        array=("foo" "bar" "baz")
        dieroll=$(($RANDOM % 1000))

        if [[ "$dieroll" -lt 1 ]]; then
        printf "%sn" "${array[2]}"
        elif [[ "$dieroll" -lt 266 ]]; then
        printf "%sn" "${array[1]}"
        else
        printf "%sn" "${array[0]}"
        fi


        This has the advantages of not having to blow the array up to 1000 entries or needing any for loops.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited yesterday

























        answered yesterday









        DopeGhotiDopeGhoti

        45.2k55988




        45.2k55988






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Unix & Linux Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f498638%2fhow-do-i-specify-chance-when-setting-a-variable-to-random-item-in-array%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Paul Cézanne

            UIScrollView CustomStickyHeader Resize height generates problems when scroll is too fast

            Angular material date-picker (MatDatepicker) auto completes the date on focus out