Re: Random number generator without duplicates?
Re: Random number generator without duplicates?
- Subject: Re: Random number generator without duplicates?
- From: Timothy Bates <email@hidden>
- Date: Wed, 18 Apr 2001 11:26:23 +1000
hi brennan et al.,
I would be interested in any generic list handlers or other helper libraries
that people have developed. I enclose my own list stuff (not all of it is
original coding). The read and writespreadsheet functions someone might find
useful.
This library is designed to be called from our PsyScript scriptable
Psychology Laboratory <www.maccs.mq.edu.au/~tim/psyscript/>
--initializeList(5, "0")
-->{"0", "0", "0", "0", "0"}
to initializeList(theCount, theContents)
set TheList to {}
repeat with N from 1 to theCount
set the end of TheList to theContents
end repeat
return TheList
end initializeList
--getOffset(6, {1, 2, 3})
-->-1
on getOffset(what, TheList) -- return -1 if not found
repeat with i from 1 to (count of TheList)
if item i of TheList is what then return i
end repeat
return -1 --
end getOffset
on sort(TheList)
if length of TheList = 1 then return TheList
set x to item 1 of TheList
set ll to rest of TheList
set listOne to {}
set listTwo to {}
repeat with i in ll
if x < i then
set listTwo to listTwo & i
else
set listOne to listOne & i
end if
end repeat
if length of listOne > 1 then set listOne to sort(listOne)
if length of listTwo > 1 then set listTwo to sort(listTwo)
return listOne & x & listTwo
end sort
to randomize(TheList)
repeat with i from length of TheList to 1 by -1
set current_item to (random number from 1 to i)
tell TheList -- exchange item current_item with item i
set temp to item i
set item i to item current_item
set item current_item to temp
end tell
end repeat
return TheList
end randomize
--return insert(3, "first after 3", {1, 2, 3, 4})
--{1, 2, 3, "first after 3", 4}
--return insert({3, 2}, {"first after 3", "second after 2"}, {1, 2, 3, 4})
--{1, 2, "second after 2", 3, "first after 3", 4}
to insert(insertionAt, addingTheseItems, toThisList)
local N
if class of insertionAt is list then
if class of addingTheseItems is not list then
error "NewItems parameter for insertItemsAfter must be list"
number -1719
else if class of toThisList is not list then
error ("originalList parameter for insertItemsAfter must be list
not " & (class of toThisList as string)) number -1719
else if (count of insertionAt) (count of addingTheseItems) then
error "insertItemsAfter says \"insertionCount & count of
NewItems must be equal\"" number -1719
else
repeat with N from 1 to count of insertionAt
set toThisList to insert(item N of insertionAt, item N of
addingTheseItems, toThisList)
end repeat
return toThisList
end if
else --inserting 1 item
copy (insertionAt as number) to x
if x = 0 then
return {} & addingTheseItems & toThisList --prepend if index is
<1
else if (x (count toThisList)) then
return (toThisList & addingTheseItems) --append if is large
index
else if x = 1 then
return (item 1 of toThisList) & addingTheseItems & (items (x +
1) thru -1 of toThisList)
else
return (items 1 thru (x) of toThisList) & addingTheseItems &
(items (x + 1) thru -1 of toThisList)
end if
end if
end insert
--replaceItems({1, -1}, {"a", "b"}, {1, 2, 3, 4})
-->{"a", 2, 3, "b"}
to replaceItems(itemIndices, NewItems, originalList)
copy originalList to scratchList
if class of itemIndices is not list then
error "insertionIndices parameter for replaceItemsAt must be list"
number -1719
else if class of NewItems is not list then
error "NewItems parameter for replaceItemsAt must be list" number
-1719
else if class of originalList is not list then
error "originalList parameter for replaceItemsAt must be list not "
& (class of originalList) number -1719
else
set N to count of itemIndices
repeat with x from 1 to N
set item (item x of itemIndices) of scratchList to (contents of
item x of NewItems)
end repeat
return scratchList
end if
end replaceItems
on readSpreadsheet(thefile) --takes a file path, returns a 2D array.
set outArray to {}
set oldDelims to AppleScript's text item delimiters
set AppleScript's text item delimiters to {tab}
if ":" is not in thefile then set thefile to pMyContainer & thefile
try
set f to open for access thefile
repeat
try
set end of outArray to (every text item of (read f before
return))
on error theMessage number errNumber
if errNumber = -39 then
-- end of file, clean up & get out
set AppleScript's text item delimiters to oldDelims
close access f
return outArray
else
-- Another error. Clean up & resignal user
close file f
set AppleScript's text item delimiters to oldDelims
error theMessage & "
readspreadsheet" number N
end if
end try
end repeat
on error m number N
error "could not find the file :" & thefile & return & m number N
end try
end readSpreadsheet
--parsetostring({{1, 2, 3, 4}, {"a", "b", "c", "d"}}, {"", return})
-->1234
-->abcd
on parsetostring(TheList, theDelimiters)
if (count of theDelimiters) > 1 then
if class of item 1 of TheList is not list then
error "you gave delimiters suggesting a 2D array but I only see
1D"
else if ((count of theDelimiters) > 2) then
error "I can only do a 2D string so far"
else
set outstring to ""
repeat with aline in TheList
set outstring to outstring & my parsetostring(aline, item 1
of theDelimiters) & item 2 of theDelimiters
end repeat
end if
else --1D
set savedTextItemDelimiters to AppleScript's text item delimiters
try
set AppleScript's text item delimiters to {theDelimiters}
set TheList to TheList as string
set AppleScript's text item delimiters to
savedTextItemDelimiters
return TheList
on error errMsg number errNum from f to t partial result p
--also reset text item delimiters in case of an error:
set AppleScript's text item delimiters to
savedTextItemDelimiters
--and resignal the error:
return TheList
error errMsg number errNum from f to t partial result p
end try
end if
end parsetostring
to subset(indices, TheList)
set outList to {}
if class of indices is not list then
return {}
else
repeat with itemIndex in indices
set end of outList to item (itemIndex as number) of TheList
end repeat
return outList
end if
end subset
on removeItem(x, TheList) --at x --, theList)
-- removes any item from a list
set x to (x as number)
if x < 1 then return TheList
set numItems to count of items in TheList
if numItems is 1 then return {}
if x > numItems then return TheList
if x = 1 then
set newList to (items 2 thru -1 of TheList)
else if x = numItems then
set newList to (items 1 thru -2 of TheList)
else
set newList to (items 1 thru (x - 1) of TheList) & (items (x + 1)
thru -1 of TheList)
end if
return newList
end removeItem
--sample with Replacement given take:3, outof:{1, 2, 3, 4, 5, 6, 7, 8, 9}
-->{3, 9, 7}
--sample without Replacement given take: 3 outof: {1, 2, 3, 4, 5, 6, 7, 8,
9}
-->{3, 9, 7}
to sample(itemCount, TheList, replacing)
if itemCount > length of TheList then
error "source:sample(itemcount, thelist, replacing):
Asked for more items than exist"
else
set chosenItems to {}
if replacing then
repeat with N from 1 to itemCount
set end of chosenItems to some item of TheList
end repeat
else
repeat with N from 1 to itemCount
set x to random number from 1 to count of TheList
set end of chosenItems to item x of TheList
set stimList to removeItem(x, TheList)
end repeat
end if
return chosenItems
end if
end sample
--makeASparseList given taking:10, outof:{}, separatedBy:4
-->{5, 7, 3}
on sparseRepeat given taking:numberWanted, outof:TheList, separatedBy:min
set outList to {}
set separationCheckList to {}
repeat while (count of outList) < numberWanted
set candidate to (some item of TheList)
if candidate is not in separationCheckList then
set outList to outList & candidate
set separationCheckList to separationCheckList & candidate
if (count of separationCheckList) > min then set
separationCheckList to items -min thru -1 of separationCheckList
end if
end repeat
return outList
end sparseRepeat