Hi folks
Anyone have a snippet of code to generate a list of numbers from 1 to x so that the numbers are in random order and do not repeat?
For example: Random list from 1 to 10
{2, 5, 7, 8, 1, 3, 6, 4, 10, 9}
Thanks
Hi folks
Anyone have a snippet of code to generate a list of numbers from 1 to x so that the numbers are in random order and do not repeat?
For example: Random list from 1 to 10
{2, 5, 7, 8, 1, 3, 6, 4, 10, 9}
Thanks
Is this what you mean?
Jon
[This script was automatically tagged for color coded syntax by Convert Script to Markup Code]
Not bad, jonn, except that your script will take exponentially longer the more numbers there are in the list because there’s a larger number of double hits that have to be taken into account.
A much faster solution (although it’s more script code) would be to eliminate each item from the list as its picked. That way you know any number in the original list is still unique and you don’t need to scan the random list to see if you’ve already chosen it.
Something like this:
[This script was automatically tagged for color coded syntax by Convert Script to Markup Code]
Note that I’ve set this up to accept a low and high mark as parameters to the handler. This makes is very flexible, but isn’t necessary if you know you’re dealing with the same set of numbers.
That’s good! Like Jon’s script, it assumes that the number range is not greater than the number of numbers required, but it’s easily adapted if not.
An even more efficacious speed hike with big lists is to write your own random number generator rather than relying on ‘random number’ (each use of which is an OSAX call). In conjuction with an optimisation of Camelot’s handler, it might look like this:
property fastRandomSeed : pi
on reseedFastRandom()
set fastRandomSeed to (fastRandom from 0.0 to (current date)'s time) mod 1
end reseedFastRandom
on fastRandom from a to b
set fastRandomSeed to (fastRandomSeed * pi) mod 1
if a's class is integer and b's class is integer then
if a < b then
a + (b - a + 1) * fastRandomSeed div 1
else
a + (b - a - 1) * fastRandomSeed div 1
end if
else
a + (b - a) * fastRandomSeed
end if
end fastRandom
on getRandomList(low, high)
local randomList, pick
script o
property numList : {}
property randomList : {}
end script
reseedFastRandom()
repeat with i from low to high
set end of o's numList to i
end repeat
repeat high - 1 times
set pick to fastRandom from 1 to high
set end of o's randomList to item pick of o's numList
set item pick of o's numList to missing value
set o's numList to o's numList's numbers
set high to high - 1
end repeat
set end of o's randomList to beginning of o's numList
return o's randomList
end getRandomList
getRandomList(1,100)
Sorry. I forgot to allow for non-1 values of ‘low’. It’s only one extra line, but here’s the whole thing again to avoid confusion:
property fastRandomSeed : pi
on reseedFastRandom()
set fastRandomSeed to (fastRandom from 0.0 to (current date)'s time) mod 1
end reseedFastRandom
on fastRandom from a to b
set fastRandomSeed to (fastRandomSeed * pi) mod 1
if a's class is integer and b's class is integer then
if a < b then
a + (b - a + 1) * fastRandomSeed div 1
else
a + (b - a - 1) * fastRandomSeed div 1
end if
else
a + (b - a) * fastRandomSeed
end if
end fastRandom
on getRandomList(low, high)
script o
property numList : {}
property randomList : {}
end script
reseedFastRandom()
repeat with i from low to high
set end of o's numList to i
end repeat
set high to high - low + 1
repeat high - 1 times
set pick to fastRandom from 1 to high
set end of o's randomList to item pick of o's numList
set item pick of o's numList to missing value
set o's numList to o's numList's numbers
set high to high - 1
end repeat
set end of o's randomList to beginning of o's numList
return o's randomList
end getRandomList
getRandomList(1, 100)
Create an ordered list of numbers, then randomise the order. Very efficient.
Using the List library from AppleMods http://applemods.sourceforge.net:
property _Loader : run application "LoaderServer"
----------------------------------------------------------------------
-- DEPENDENCIES
property _List : missing value
on __load__(loader)
set _List to loader's loadLib("List")
end __load__
----------------------------------------------------------------------
__load__(_Loader's makeLoader())
on orderedList(fromNum, toNum, byStep)
set lst to {}
repeat with i from fromNum to toNum by byStep
set lst's end to i
end repeat
return lst
end orderedList
_List's unsortList(orderedList(1, 100, 1))
Gosh yes. After reading your post, I wrote a random-swap routine that turned out to be about three times as fast as what I posted earlier. Then I downloaded your list library and had a look at the ‘unsortList’ handler. It’s very similar code, but your built-in, specialised random integer generator makes it about a quarter as fast again. (Tested with a 1000-item list, not in a library context.)
That’s a pretty mean list randomiser.