Build string by generating random characters step by step

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
3
down vote

favorite












I'm trying to create a program that will try to build a target string character by character by generating random characters. I have come up with the following Nodejs program with a little bit of Google help:



const args = process.argv.slice(2)

const targetWord = args[0]
let builtWord = ''

function getRandomChar()
return String.fromCharCode(Math.floor(Math.random() * (126 - 32 + 1)) + 32)


function updateWord()
const length = builtWord
const nextChar = getRandomChar()
process.stdout.write('r')
process.stdout.write(builtWord)
process.stdout.write(nextChar)
if (targetWord[length] === nextChar)
builtWord += nextChar



const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))

async function main()
while (true)
updateWord()
if (builtWord === targetWord)
break

await sleep(1000 / 16)



main()


What are your thoughts on it, anything I can improve or do differently? Thanks 😙!







share|improve this question



























    up vote
    3
    down vote

    favorite












    I'm trying to create a program that will try to build a target string character by character by generating random characters. I have come up with the following Nodejs program with a little bit of Google help:



    const args = process.argv.slice(2)

    const targetWord = args[0]
    let builtWord = ''

    function getRandomChar()
    return String.fromCharCode(Math.floor(Math.random() * (126 - 32 + 1)) + 32)


    function updateWord()
    const length = builtWord
    const nextChar = getRandomChar()
    process.stdout.write('r')
    process.stdout.write(builtWord)
    process.stdout.write(nextChar)
    if (targetWord[length] === nextChar)
    builtWord += nextChar



    const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))

    async function main()
    while (true)
    updateWord()
    if (builtWord === targetWord)
    break

    await sleep(1000 / 16)



    main()


    What are your thoughts on it, anything I can improve or do differently? Thanks 😙!







    share|improve this question























      up vote
      3
      down vote

      favorite









      up vote
      3
      down vote

      favorite











      I'm trying to create a program that will try to build a target string character by character by generating random characters. I have come up with the following Nodejs program with a little bit of Google help:



      const args = process.argv.slice(2)

      const targetWord = args[0]
      let builtWord = ''

      function getRandomChar()
      return String.fromCharCode(Math.floor(Math.random() * (126 - 32 + 1)) + 32)


      function updateWord()
      const length = builtWord
      const nextChar = getRandomChar()
      process.stdout.write('r')
      process.stdout.write(builtWord)
      process.stdout.write(nextChar)
      if (targetWord[length] === nextChar)
      builtWord += nextChar



      const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))

      async function main()
      while (true)
      updateWord()
      if (builtWord === targetWord)
      break

      await sleep(1000 / 16)



      main()


      What are your thoughts on it, anything I can improve or do differently? Thanks 😙!







      share|improve this question













      I'm trying to create a program that will try to build a target string character by character by generating random characters. I have come up with the following Nodejs program with a little bit of Google help:



      const args = process.argv.slice(2)

      const targetWord = args[0]
      let builtWord = ''

      function getRandomChar()
      return String.fromCharCode(Math.floor(Math.random() * (126 - 32 + 1)) + 32)


      function updateWord()
      const length = builtWord
      const nextChar = getRandomChar()
      process.stdout.write('r')
      process.stdout.write(builtWord)
      process.stdout.write(nextChar)
      if (targetWord[length] === nextChar)
      builtWord += nextChar



      const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))

      async function main()
      while (true)
      updateWord()
      if (builtWord === targetWord)
      break

      await sleep(1000 / 16)



      main()


      What are your thoughts on it, anything I can improve or do differently? Thanks 😙!









      share|improve this question












      share|improve this question




      share|improve this question








      edited May 1 at 9:41









      Vogel612♦

      20.9k345124




      20.9k345124









      asked May 1 at 9:19









      Jennifer Zhou

      183




      183




















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          2
          down vote



          accepted










          Extract magic numbers into constants




          • For instance, what do 126 and 32 represent in the following line?



            return String.fromCharCode(Math.floor(Math.random() * (126 - 32 + 1)) + 32)


            It is much better to extract magic numbers into constants, i.e. to annotate them with a semantically meaningful name:



            const HIGHEST_ASCII_PRINTABLE_CHARACTER = 126;
            const LOWEST_ASCII_PRINTABLE_CHARACTER = 32;


            But even when you replace the numbers by their constant's name, it isn't immediately clear what you're doing with -32, +32, Math.random() and Math.floor() there. Even if you are accustomed to random number generation, a dedicated function call is more readable with less redundancy and in fact is easier to reason about:



            return String.fromCharCode(getRandomInt(LOWEST_ASCII_PRINTABLE_CHARACTER, HIGHEST_ASCII_PRINTABLE_CHARACTER));


            Especially, with your old code, I had to look up Math.random() on MDN to make really sure that is produces a uniform distribution. Now you can just add a docblock comment to getRandomInt indicating that property.



          • await sleep(1000 / 16) also features magic numbers.


          Miscellaneous remarks



          • Using async-await for waiting after each loop iteration is a good use case and really makes the code cleaner!


          • Extracting only a single property with the object destructuring syntax (const length = builtWord) seems a bit unidiomatic to me as opposed to const length = builtWord.length.
            Apart from that, you are using length only once anyway, so I would drop that variable all together.



          • Try to avoid global variables and interdependencies.




            • For example, builtWord as well as targetWord are shared (and the former even modified!) by main and updateWord. I would suggest making updateWord accepting both as arguments and returning the possibly newly built word:



              function tryUpdateWord(currentBuiltWord, targetWord) 
              // This is a good moment to introduce a sanity check as well
              if (currentBuildWord.length >= targetWord.length)
              throw new Error('<todo>');


              const nextChar = getRandomChar()
              process.stdout.write('r')
              process.stdout.write(currentBuiltWord)
              process.stdout.write(nextChar)
              if (targetWord[currentBuildWord.length] === nextChar)
              return currentBuiltWord + nextChar

              else
              return currentBuiltWord;





            • Since the interdependencies have now been eliminiated, I would also move the part reading the process arguments into main():



              async function main() 
              const targetWord = process.args[2]
              let builtWord = ''

              const SLEEP_PER_ITERATION = 1000 / 16;
              while (true)
              builtWord = tryUpdateWord(builtWord, targetWord)
              if (builtWord === targetWord)
              break

              await sleep(SLEEP_PER_ITERATION)









          share|improve this answer























            Your Answer




            StackExchange.ifUsing("editor", function ()
            return StackExchange.using("mathjaxEditing", function ()
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            );
            );
            , "mathjax-editing");

            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "196"
            ;
            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',
            convertImagesToLinks: false,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );








             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f193339%2fbuild-string-by-generating-random-characters-step-by-step%23new-answer', 'question_page');

            );

            Post as a guest






























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            2
            down vote



            accepted










            Extract magic numbers into constants




            • For instance, what do 126 and 32 represent in the following line?



              return String.fromCharCode(Math.floor(Math.random() * (126 - 32 + 1)) + 32)


              It is much better to extract magic numbers into constants, i.e. to annotate them with a semantically meaningful name:



              const HIGHEST_ASCII_PRINTABLE_CHARACTER = 126;
              const LOWEST_ASCII_PRINTABLE_CHARACTER = 32;


              But even when you replace the numbers by their constant's name, it isn't immediately clear what you're doing with -32, +32, Math.random() and Math.floor() there. Even if you are accustomed to random number generation, a dedicated function call is more readable with less redundancy and in fact is easier to reason about:



              return String.fromCharCode(getRandomInt(LOWEST_ASCII_PRINTABLE_CHARACTER, HIGHEST_ASCII_PRINTABLE_CHARACTER));


              Especially, with your old code, I had to look up Math.random() on MDN to make really sure that is produces a uniform distribution. Now you can just add a docblock comment to getRandomInt indicating that property.



            • await sleep(1000 / 16) also features magic numbers.


            Miscellaneous remarks



            • Using async-await for waiting after each loop iteration is a good use case and really makes the code cleaner!


            • Extracting only a single property with the object destructuring syntax (const length = builtWord) seems a bit unidiomatic to me as opposed to const length = builtWord.length.
              Apart from that, you are using length only once anyway, so I would drop that variable all together.



            • Try to avoid global variables and interdependencies.




              • For example, builtWord as well as targetWord are shared (and the former even modified!) by main and updateWord. I would suggest making updateWord accepting both as arguments and returning the possibly newly built word:



                function tryUpdateWord(currentBuiltWord, targetWord) 
                // This is a good moment to introduce a sanity check as well
                if (currentBuildWord.length >= targetWord.length)
                throw new Error('<todo>');


                const nextChar = getRandomChar()
                process.stdout.write('r')
                process.stdout.write(currentBuiltWord)
                process.stdout.write(nextChar)
                if (targetWord[currentBuildWord.length] === nextChar)
                return currentBuiltWord + nextChar

                else
                return currentBuiltWord;





              • Since the interdependencies have now been eliminiated, I would also move the part reading the process arguments into main():



                async function main() 
                const targetWord = process.args[2]
                let builtWord = ''

                const SLEEP_PER_ITERATION = 1000 / 16;
                while (true)
                builtWord = tryUpdateWord(builtWord, targetWord)
                if (builtWord === targetWord)
                break

                await sleep(SLEEP_PER_ITERATION)









            share|improve this answer



























              up vote
              2
              down vote



              accepted










              Extract magic numbers into constants




              • For instance, what do 126 and 32 represent in the following line?



                return String.fromCharCode(Math.floor(Math.random() * (126 - 32 + 1)) + 32)


                It is much better to extract magic numbers into constants, i.e. to annotate them with a semantically meaningful name:



                const HIGHEST_ASCII_PRINTABLE_CHARACTER = 126;
                const LOWEST_ASCII_PRINTABLE_CHARACTER = 32;


                But even when you replace the numbers by their constant's name, it isn't immediately clear what you're doing with -32, +32, Math.random() and Math.floor() there. Even if you are accustomed to random number generation, a dedicated function call is more readable with less redundancy and in fact is easier to reason about:



                return String.fromCharCode(getRandomInt(LOWEST_ASCII_PRINTABLE_CHARACTER, HIGHEST_ASCII_PRINTABLE_CHARACTER));


                Especially, with your old code, I had to look up Math.random() on MDN to make really sure that is produces a uniform distribution. Now you can just add a docblock comment to getRandomInt indicating that property.



              • await sleep(1000 / 16) also features magic numbers.


              Miscellaneous remarks



              • Using async-await for waiting after each loop iteration is a good use case and really makes the code cleaner!


              • Extracting only a single property with the object destructuring syntax (const length = builtWord) seems a bit unidiomatic to me as opposed to const length = builtWord.length.
                Apart from that, you are using length only once anyway, so I would drop that variable all together.



              • Try to avoid global variables and interdependencies.




                • For example, builtWord as well as targetWord are shared (and the former even modified!) by main and updateWord. I would suggest making updateWord accepting both as arguments and returning the possibly newly built word:



                  function tryUpdateWord(currentBuiltWord, targetWord) 
                  // This is a good moment to introduce a sanity check as well
                  if (currentBuildWord.length >= targetWord.length)
                  throw new Error('<todo>');


                  const nextChar = getRandomChar()
                  process.stdout.write('r')
                  process.stdout.write(currentBuiltWord)
                  process.stdout.write(nextChar)
                  if (targetWord[currentBuildWord.length] === nextChar)
                  return currentBuiltWord + nextChar

                  else
                  return currentBuiltWord;





                • Since the interdependencies have now been eliminiated, I would also move the part reading the process arguments into main():



                  async function main() 
                  const targetWord = process.args[2]
                  let builtWord = ''

                  const SLEEP_PER_ITERATION = 1000 / 16;
                  while (true)
                  builtWord = tryUpdateWord(builtWord, targetWord)
                  if (builtWord === targetWord)
                  break

                  await sleep(SLEEP_PER_ITERATION)









              share|improve this answer

























                up vote
                2
                down vote



                accepted







                up vote
                2
                down vote



                accepted






                Extract magic numbers into constants




                • For instance, what do 126 and 32 represent in the following line?



                  return String.fromCharCode(Math.floor(Math.random() * (126 - 32 + 1)) + 32)


                  It is much better to extract magic numbers into constants, i.e. to annotate them with a semantically meaningful name:



                  const HIGHEST_ASCII_PRINTABLE_CHARACTER = 126;
                  const LOWEST_ASCII_PRINTABLE_CHARACTER = 32;


                  But even when you replace the numbers by their constant's name, it isn't immediately clear what you're doing with -32, +32, Math.random() and Math.floor() there. Even if you are accustomed to random number generation, a dedicated function call is more readable with less redundancy and in fact is easier to reason about:



                  return String.fromCharCode(getRandomInt(LOWEST_ASCII_PRINTABLE_CHARACTER, HIGHEST_ASCII_PRINTABLE_CHARACTER));


                  Especially, with your old code, I had to look up Math.random() on MDN to make really sure that is produces a uniform distribution. Now you can just add a docblock comment to getRandomInt indicating that property.



                • await sleep(1000 / 16) also features magic numbers.


                Miscellaneous remarks



                • Using async-await for waiting after each loop iteration is a good use case and really makes the code cleaner!


                • Extracting only a single property with the object destructuring syntax (const length = builtWord) seems a bit unidiomatic to me as opposed to const length = builtWord.length.
                  Apart from that, you are using length only once anyway, so I would drop that variable all together.



                • Try to avoid global variables and interdependencies.




                  • For example, builtWord as well as targetWord are shared (and the former even modified!) by main and updateWord. I would suggest making updateWord accepting both as arguments and returning the possibly newly built word:



                    function tryUpdateWord(currentBuiltWord, targetWord) 
                    // This is a good moment to introduce a sanity check as well
                    if (currentBuildWord.length >= targetWord.length)
                    throw new Error('<todo>');


                    const nextChar = getRandomChar()
                    process.stdout.write('r')
                    process.stdout.write(currentBuiltWord)
                    process.stdout.write(nextChar)
                    if (targetWord[currentBuildWord.length] === nextChar)
                    return currentBuiltWord + nextChar

                    else
                    return currentBuiltWord;





                  • Since the interdependencies have now been eliminiated, I would also move the part reading the process arguments into main():



                    async function main() 
                    const targetWord = process.args[2]
                    let builtWord = ''

                    const SLEEP_PER_ITERATION = 1000 / 16;
                    while (true)
                    builtWord = tryUpdateWord(builtWord, targetWord)
                    if (builtWord === targetWord)
                    break

                    await sleep(SLEEP_PER_ITERATION)









                share|improve this answer















                Extract magic numbers into constants




                • For instance, what do 126 and 32 represent in the following line?



                  return String.fromCharCode(Math.floor(Math.random() * (126 - 32 + 1)) + 32)


                  It is much better to extract magic numbers into constants, i.e. to annotate them with a semantically meaningful name:



                  const HIGHEST_ASCII_PRINTABLE_CHARACTER = 126;
                  const LOWEST_ASCII_PRINTABLE_CHARACTER = 32;


                  But even when you replace the numbers by their constant's name, it isn't immediately clear what you're doing with -32, +32, Math.random() and Math.floor() there. Even if you are accustomed to random number generation, a dedicated function call is more readable with less redundancy and in fact is easier to reason about:



                  return String.fromCharCode(getRandomInt(LOWEST_ASCII_PRINTABLE_CHARACTER, HIGHEST_ASCII_PRINTABLE_CHARACTER));


                  Especially, with your old code, I had to look up Math.random() on MDN to make really sure that is produces a uniform distribution. Now you can just add a docblock comment to getRandomInt indicating that property.



                • await sleep(1000 / 16) also features magic numbers.


                Miscellaneous remarks



                • Using async-await for waiting after each loop iteration is a good use case and really makes the code cleaner!


                • Extracting only a single property with the object destructuring syntax (const length = builtWord) seems a bit unidiomatic to me as opposed to const length = builtWord.length.
                  Apart from that, you are using length only once anyway, so I would drop that variable all together.



                • Try to avoid global variables and interdependencies.




                  • For example, builtWord as well as targetWord are shared (and the former even modified!) by main and updateWord. I would suggest making updateWord accepting both as arguments and returning the possibly newly built word:



                    function tryUpdateWord(currentBuiltWord, targetWord) 
                    // This is a good moment to introduce a sanity check as well
                    if (currentBuildWord.length >= targetWord.length)
                    throw new Error('<todo>');


                    const nextChar = getRandomChar()
                    process.stdout.write('r')
                    process.stdout.write(currentBuiltWord)
                    process.stdout.write(nextChar)
                    if (targetWord[currentBuildWord.length] === nextChar)
                    return currentBuiltWord + nextChar

                    else
                    return currentBuiltWord;





                  • Since the interdependencies have now been eliminiated, I would also move the part reading the process arguments into main():



                    async function main() 
                    const targetWord = process.args[2]
                    let builtWord = ''

                    const SLEEP_PER_ITERATION = 1000 / 16;
                    while (true)
                    builtWord = tryUpdateWord(builtWord, targetWord)
                    if (builtWord === targetWord)
                    break

                    await sleep(SLEEP_PER_ITERATION)










                share|improve this answer















                share|improve this answer



                share|improve this answer








                edited May 1 at 16:06


























                answered May 1 at 16:01









                ComFreek

                608617




                608617






















                     

                    draft saved


                    draft discarded


























                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f193339%2fbuild-string-by-generating-random-characters-step-by-step%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Popular posts from this blog

                    Chat program with C++ and SFML

                    Function to Return a JSON Like Objects Using VBA Collections and Arrays

                    Will my employers contract hold up in court?