Generate random numbers without repeating a value

From Rosetta Code
Revision as of 17:51, 24 August 2021 by PureFox (talk | contribs) (Added Wren)
Generate random numbers without repeating a value is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Many puzzle games such as the 15 puzzle game need a way to randomize the order of the pieces. One way to do this is to create an array and fill it with random values, with each element's index in that array being its position. Unfortunately, most random number generators can produce the same value more than once, which in this case isn't what we want.


Task

Create a random number generator and have it output the numbers 1 through 20 (inclusive), in a random order. It cannot produce the same value more than once.

Or

Given the output of an existing random number generator that does produce repeated output, create a function that constrains the output to numbers 1 through 20 (inclusive), and no number is output more than once. (Technically it stops being "random" at that point, but that's beyond the scope of this task.) Try your best not to make the process take too long at runtime.

For the second version of the task, the random number generator itself need not be implemented; however you must specify its possible range of values before your constraint function is applied. (e.g "Assume the random number generator creates a value from 0 to 255, and values are allowed to repeat")

Related Tasks



Wren

This uses Wren's 'native' pseudo-random number generator which internally uses WELL512a and can generate random integers in the 32-bit range. <lang ecmascript>import "random" for Random import "/fmt" for Fmt

var rand = Random.new()

// Generates and prints all numbers within an inclusive range whose endpoints are 32 bit integers. // The numbers are generated in random order with any repetitions being ignored. var generate = Fn.new { |r|

   var generated = List.filled(r.to - r.from + 1, false) // zero indexing
   while (generated.any { |g| !g }) { 
       var n = rand.int(r.from, r.to + 1) // upper endpoint is exclusive
       if (!generated[n - r.from]) {      
           generated[n - r.from] = true
           Fmt.write("$2d ", n)
       }
   }
   System.print()

}

// generate 5 sets say for (i in 1..5) generate.call(1..20)</lang>

Output:

Sample run:

 4 16 10  5  1  2  9 19  7 12 15 11 18  3 13 17 20 14  6  8 
16  1  9 11  8 10 19  5  4  6 17 20 12 15  3  7 14 18  2 13 
 5 15 13  1 17 19 16  2  7 12 18  8 14  6 20  9 10 11  3  4 
 9  6 20 16  2 14 19  1  7 18 11 12  4 15  5 17  3  8 10 13 
16  1  8 14  5 19  3  4 18 12 20  2 10  6 13 11  7 15  9 17