Bit of fun while generating code

alband

Senior Member
Hi all,

I wanted to make some code to generate a list of 30 random numbers between 1 and 30 with no repeats (just using PE as a helpful tool to do this). I couldn't work out how to do it without using 30 variables to store each number in so that I could check if a number had already been used. That seemed to require writing the whole thing out 30 times and changing the variable name that it was stored in each time. So, I had an idea. I wrote some other code to write this code :D

Code:
let w2 = 65535 / 31
main:		do
			sertxd ("lable",#b0,":	random w27",CR)
			sertxd ("		let w27 = w27 / ",#w2,CR)
			sertxd ("		let b",#b0," = b54",CR)
			
			if b0 > 0 then
			let b1 = b0
			do
			let b1 = b1 - 1
			sertxd ("		if b",#b0," = b",#b1," then lable",#b0,CR)
			loop until b1 = 0
			endif
			sertxd ("		sertxd (#b",#b0,",CR)",CR)
			inc b0
		loop while b0 < 31
		end
I then sat back and let that run for a few minutes while it wrote my code for me. When it was finished, I simply copied the code from the sertxd box into PE and ran that. And out came a list of 30 numbers, between 1 and 30, in a random order, with no repeats! What fun! (well 31 if you count the "0" :(:rolleyes:)

Anyway, for future reference, I'd really appreciate it if someone could tell me the normal way to generate a list of 30 numbers from 1-30 in a random order.

Thanks,
David.
 

MartinM57

Moderator
First hit with Googling for "random number generator with range"

http://www.randomizer.org/form.htm

...which after you've specified the parameters leads to...

Set #1:

20, 27, 17, 19, 15, 12, 10, 22, 23, 18, 4, 24, 0, 1, 7, 28, 26, 9, 25, 11, 13, 30, 21, 3, 14, 6, 8, 2, 16, 5, 29

Total time including typing this post ... ~ 2 mins

(OK - I specified 0 as the lowest value, but you can just take it out)
 

KTarke

Senior Member
Once made a "lottery generator" on pc and basic.

Idea was to create a random number, store it to an array (with Picaxe to eeprom or ram) IF that number was not already used.(test against every cell in the array)
If used, skip, and randomize again.

That was done in a loop, that determines how many numbers was retrieved (in my case, it was 7 numbers out of range 1-42)

I think, this is the most common way.
Code is rude,slow and unefficient, but works well... (if only the "random" -command is really random...)

In the case, where ALL numbers in the range are retrieved (in random order), there will be a lot of "skips" before all the figures are put in the array. So in this case, code is REALLY slow.
When I chose only 7 figures out of 42, there were much less "skips" and the code was acceptable fast.
 
Last edited:

MartinM57

Moderator
...well that's my algorithm ;)

Alternatively:
- start with a set of numbers 1 to 30
- randomly select one of the 30
- remove it from the set
- randomly select one of the remaining 29
- remove it from the set
- randomly select one of the remaining 28
- remove it from the set
- randomly select one of the remaining 27
- remove it from the set
- ...
- randomly select one of the remaining 2
- remove it from the set
- remove the last remaining number

Oh...you wanted the algorithm in PICAXE BASIC as well - that's an exercise for the student :D
 

hippy

Ex-Staff (retired)
Anyway, for future reference, I'd really appreciate it if someone could tell me the normal way to generate a list of 30 numbers from 1-30 in a random order.
I'm not sure there is a "normal way" but a variety of algorithms.

Perhaps the simplest is choose a number, has it already been given, if so then choose another. You'll need 30 'flag variables' to indicate which have been given but they could be bit variables which reduces storage requirements or scratchpad can be used with one byte per number which can be accessed via @bptr. The problem is that as the choice of numbers reduce the chance of selecting one not already given reduces.

( Great minds think alike ... )

The fastest is probably to create an array of 30 numbers ( 1 to 30, sequential or random ). Then randomly select 1 to 30, use the number in the array at the random position, remove that entry from the array, shuffle the rest of the array so it now only contains 29 numbers, repeat selecting a random number between 1 and 29, get the number now at that position, remove, reduce to 28, random between 1 and 28, etc.

For example, a five number array ...

1 2 3 4 5

Random between 1 and 5 gives 2, the 2nd number is "2" so use that, then remove 2nd entry

1 3 4 5

Random between 1 and 4 gives 3, the 3rd number is "4" so use that, then remove 3rd entry

1 3 5

Random between 1 and 3 gives 3, the 3rd number is "5" so use that, then remove 3rd entry

1 3

Random between 1 and 2 gives 1, the 1st number is "1" so use that, then remove 1st entry

3

We only have one number left so use that, "3". Our random order was 2 4 5 1 3
 

KTarke

Senior Member
Perhaps the simplest is choose a number, has it already been given, if so then choose another. You'll need 30 'flag variables' to indicate which have been given but they could be bit variables which reduces storage requirements or scratchpad can be used with one byte per number which can be accessed via @bptr. The problem is that as the choice of numbers reduce the chance of selecting one not already given reduces.
I presented nearly the same "selecting" idea a few posts back, but those bit-flags reduces memory-usage a lot!

The fastest is probably to create an array of 30 numbers ( 1 to 30, sequential or random ). Then randomly select 1 to 30, use the number in the array at the random position, remove that entry from the array, shuffle the rest of the array so it now only contains 29 numbers, repeat selecting a random number between 1 and 29, get the number now at that position, remove, reduce to 28, random between 1 and 28, etc.

For example, a five number array ...

1 2 3 4 5

Random between 1 and 5 gives 2, the 2nd number is "2" so use that, then remove 2nd entry

1 3 4 5

Random between 1 and 4 gives 3, the 3rd number is "4" so use that, then remove 3rd entry

1 3 5

Random between 1 and 3 gives 3, the 3rd number is "5" so use that, then remove 3rd entry

1 3

Random between 1 and 2 gives 1, the 1st number is "1" so use that, then remove 1st entry

3

We only have one number left so use that, "3". Our random order was 2 4 5 1 3
Very nice code again from Hippy, and there is a extra benefit: if the array is already in random order, "randomizing is doubled" (or tripled, when list is shortened in random order)
This is important, if the randomizer is to be doubted... Unfortunately, that was usually the case in pc-programming, there WERE patterns in the generated random lists, though should not be. And finer algorithms had to be generated to get "really" random numbers.
 

MPep

Senior Member
Sorry, this is probably a stupid question, but how did you get a code to write a code?
Copy and paste the code given. Set up for using an X1 or X2 device, then simulate it. Select the code from the serial terminal window, copy this to a new code window in PE. Simulate this code, and there you have a random, non-repeating number generator. :D

I have tried it, and it appears to work very well.
 

MPep

Senior Member
...well that's my algorithm ;)

Alternatively:
- start with a set of numbers 1 to 30
- randomly select one of the 30
- remove it from the set
- randomly select one of the remaining 29
- remove it from the set
- randomly select one of the remaining 28
- remove it from the set
- randomly select one of the remaining 27
- remove it from the set
- ...
- randomly select one of the remaining 2
- remove it from the set
- remove the last remaining number

Oh...you wanted the algorithm in PICAXE BASIC as well - that's an exercise for the student :D
The code posted produces this effect by the looks of it.
 

inglewoodpete

Senior Member
Random Seed

To get a crude random seed, wire a 5k potentiometer between +5 and 0v rails, wiper to an ADC input. Important! Fit a knob to the pot but ensure it does not have a pointer or position marker.

Alternatively, use an LDR and resistor set up as a potential divider to create a random number. This tends to centre the random numbers in a certain range but may be good enough.

Use ReadADC10 at bootup and multiply the number by 64 to give a range of 1024 seeds between 0 and 65472.
 

boriz

Senior Member
I&#8217;d poke the numbers 1-to-30 in sequential RAM locations then loop this: Pick two random locations, swap their contents, repeat. Like shuffling cards. Doesn&#8217;t get much easier than that.

Only trouble is that next time you cycle the power, you will get the same random number sequence. So put this at the start of your code:

Code:
read 0,word w0:random w0:write 0,word w0
Now the internal random number generator will have a new seed every time the Picaxe is turned on.
 
Last edited:
Top