Pich numbers randomly from a list without duplicates (or deal a deck of cards)

lbenson

Senior Member
Pick numbers randomly from a list without duplicates (or deal a deck of cards)

A quesition was posed about how to randomly pick each number from a list with no duplicates until each is chosen. The following program does this. To get a random number to start the sequence of random number used in the choosing loop, the program starts with the value of the "timer" register, which is available only on X1 and higher parts. The data goes in the eeprom starting at position 0, and may be put there with the EEPROM or DATA statement, or by the program (e.g., the numbers 1-52 representing the cards in a deck).

The program loops backwards by minus 1 from the number of items down to 2. A "slot" or position for the next chosen item is picked using the remainder operator ("//"). The value at this slot is displayed as the chosen value. The number in the last available slot is then moved to replace the chosen number (which may result in no change if the last slot has been chosen), and the loop is then repeated with one less slot available to chose from. When the loop is done, the last unchosen number, is displayed from slot 0.

For other than X1 parts, a different method must be chosen to get the starting random number value.

Code:
' 28Random.bas -- randomly pick each number from a list
'                 with no duplicates until each is chosen
#picaxe 28x1

symbol nItems = 8

symbol lastValue = b7   ' value in last slot
symbol lastSlot = b8    ' last position in current unchosen list
symbol loopCount = b9   ' counter for looping
symbol value = b10      ' the chosen value
symbol slotChoice = b11 ' the chosen position
symbol randomNo = w6    ' random number

' put nItems of data starting at eeprom 0 (by any method)
eeprom 0,(0,1,2,3,4,5,6,7)

' seed random number with "timer" register (available on X1 parts)
randomNo = timer ' will vary if embedded in larger program somewhere
for loopCount = nItems to 2 step -1 ' loop, counting down
  random randomNo                ' get new random number
  lastSlot = loopCount - 1       ' last position of shrinking array
  slotChoice = randomNo // loopCount ' position chosen
  read slotChoice,value          ' value at position chosen
  sertxd (#value)                ' display chosen value
  read lastSlot,lastValue      ' take highest remaining value
  write slotChoice,lastValue   ' put in slot for used value
  write lastSlot, value        ' not needed, but retains the chosen list (backwards)
next loopCount
read 0,value ' last unchosen value now in position 0
sertxd (#value)                  ' display last value
 
Last edited:

lbenson

Senior Member
Random number with 08M, 14M, 18M, 20M, etc.

The following code uses PIC timer1 together with a pushbutton to introduce randomness to get a random seed for any purpose--in this case to pick from a set of numbers randomly. At each pushbutton press it takes the least significant byte (LSB) of timer1 and puts it to first the LSB of the random seed, and then to the MSB. Note that it won't work in the simulator because of the POKEs and PEEKs.

Code:
' 14TmrTst tests timer variously

#picaxe 14M

' ---Timer Definitions
symbol PIC_TMR1H = 0x0F  ' (MSB) PIC Timer1 data (counter) register
symbol PIC_TMR1L = 0x0E  ' (MSB) PIC Timer1 data (counter) register
symbol PIC_T1CON = 0x10  ' PIC Timer1 Control Register

symbol lastValue = b7   ' value in last slot
symbol lastSlot = b8    ' last position in current unchosen list
symbol loopCount = b9   ' counter for looping
symbol value = b10      ' the chosen value
symbol slotChoice = b11 ' the chosen position
symbol randomNo = w6    ' random number

' put nItems of data starting at eeprom 0 (by any method)
symbol nItems = 8
eeprom 0,(0,1,2,3,4,5,6,7)

pause 1000

' seed random number (use "timer" for 28X1 & above)
' equivalent to w6 = timer
poke PIC_T1CON, 0x31    ' Start PIC timer1 running at 524 mSec 16-bit rollover

start:
  pause 1000
  sertxd ("Press button twice to prime random number: ")
  do : loop while pin3 = 0 ' wait for a pushbutton
  peek PIC_TMR1L,b12  ' get LSB of random number
  do : loop while pin3 = 1
  pause 100  ' debounce pause
  do : loop while pin3 = 0 ' wait for a pushbutton
  peek PIC_TMR1L,b13  ' get MSB of random number
'  poke PIC_T1CON, 0x00    ' Stop PIC timer1 (optional)
  sertxd (#randomNo,cr,lf)
  sertxd ("After display, press button to repeat",cr,lf)

main:
  for loopCount = nItems to 2 step -1 ' loop, counting down
    random randomNo                ' get new random number
    lastSlot = loopCount - 1       ' last position of shrinking array
    slotChoice = randomNo // loopCount ' position chosen
    read slotChoice,value          ' value at position chosen
  '  sertxd (#value)                ' display chosen value
    read lastSlot,lastValue      ' take highest remaining value
    write slotChoice,lastValue   ' put in slot for used value
    write lastSlot, value        ' not needed, but retains the chosen list (backwards)
  next loopCount
  'read 0,value ' last unchosen value now in position 0
  'sertxd (#value)                  ' display last value
  lastSlot = nItems - 1
  for loopCount = lastSlot to 0 step -1
    read loopCount,value      ' take highest remaining value
    sertxd (#value," ")
  next loopcount
  sertxd (cr,lf)
  do : loop while pin3 = 0 ' wait for a pushbutton
  goto main
'  goto start
Example output:
Press button twice to prime random number: 7106
After display, press button to repeat
1 6 0 3 5 7 4 2
5 3 2 7 1 0 6 4
4 0 5 1 2 7 3 6
6 7 3 4 0 1 5 2
7 0 6 5 3 1 4 2
1 7 5 3 0 6 4 2
0 6 3 5 1 7 2 4

Could some kind moderator change the first word of the subject from "Pich" to "Pick"?
 

BCJKiwi

Senior Member
@ IB

Thanks for the posts - sure they will come in handy!

You can edit the title yourself. Edit the first post and click 'go advanced' while in the editor. The title appears near the top and can be changed there.
 

lbenson

Senior Member
BCJ--thanks. I did make the change in Advanced, and it is reflected in the post title for post #1--but not in the thread title :-<
 
Top