The interesting point is that even though this is the very first code I wrote in newLISP, and I have many years' experience working with Revolution and environments like it, the newLISP code is roughly 7 times faster!! On my computer, running 10,000 iterations of the code takes about 2,300 milliseconds in newLISP, and about 18,000 milliseconds in Revolution.
By the way, I tried inlining the function call in the Revolution code, but that's not a significant bottleneck. Revolution doesn't have profiling tools (does newLISP?) so it's difficult to say just what's causing the slowdown. I have a reputation in the Revolution community for writing fairly fast code, but I'll post this to their mailing list to see if I'm missing something obvious.
Here's the newLISP code. If there's a way to make it faster, I'm happy to hear it.
Code: Select all
(set 'start (time-of-day))
(seed (date-value))
#choose how many prisoners, and the measure of success
(set 'prisonerCount 100 'prisonerGoal 90)
(set 'wincount 0 'losecount 0)
(dotimes (t 100)
#set up random lists for the warden and the prisoners
(set 'warden (randomize (sequence 0 (- prisonerCount 1)))
'prisoners (randomize (sequence 0 (- prisonerCount 1))))
#initialize an array that will store how the two lists map to each other
(set 'prisonerArray (array prisonerCount))
#populate the array with entries.
#the index is the number from the prisoners' list
#the value is the number from the warden's list
(map (fn (x y) (nth-set (prisonerArray x) y)) prisoners warden)
#initialize the results lists
(set 'loopList '() 'prisonerDoneList (array prisonerCount))
#for each prisoner entry
(dolist (i prisoners)
#if the prisoner has already been included in a list, go next
(until (prisonerDoneList i)
#mark the prisoner as done
(nth-set (prisonerDoneList i) 1)
#find what is in the prisoner's box,
#and start a list with the prisoner
(set 'x (prisonerArray i) 'oneLoop (list i))
#repeat until we find a loop
(until (= x i)
#put the new box at the end of the list
(push x oneLoop -1)
#mark the new prisoner/box as done
(nth-set (prisonerDoneList x) 1)
#move on to the next box in the loop
(set 'x (prisonerArray x)))
#when we have a complete loop,
#add it to the list of loops
(push oneLoop loopList -1)))
#create a sorted list with the lengths of the loops
(set 'loopCount (sort (map length loopList) > ) )
(if (> (first loopCount) prisonerGoal)
(inc 'losecount)
(inc 'wincount)))
#print the results
(println "prisoners win: " wincount " and prisoners lose: " losecount " in " (- (time-of-day) start) " ms")
Here's the Revolution code. Sorry for the lack of comments. It follows much the same path as the newLISP code so it should be somewhat understandable.
Code: Select all
on mouseUp
local tPrisonersDone
put 100 into tCount
put ticks() into t
repeat 100
put randomList(1,tCount) into tWarden
put randomList(1,tCount) into tPrisoners
put empty into tResult
put empty into tLoops
repeat with i = 1 to tCount
put line i of tWarden into tMap[line i of tPrisoners]
end repeat
delete local tPrisonersDone
repeat with i = 1 to tCount
if tPrisonersDone[i] = 1 then next repeat
put i into x
repeat
put tMap[x] into y
put 1 into tPrisonersDone[y]
put y after tLoops
if y is i then exit repeat
put y into x
put space after tLoops
end repeat
put cr after tLoops
end repeat
delete char -1 of tLoops
repeat for each line L in tLoops
put (the number of words of L) & " -- " & L & cr after tResult
end repeat
delete char -1 of tResult
sort lines of tResult descending numeric by word 1 of each
--put cr & cr & tResult after fld "loops"
if word 1 of tResult > 90 then add 1 to tFailed else add 1 to tSuccess
end repeat
put (ticks() - t) && "prisoners won" && tSuccess && "prisoners lost" && tFailed
end mouseUp
function randomList pStart,pStop
repeat with i = pStart to pStop
put i & cr after tList
end repeat
delete char -1 of tList
sort lines of tList by random(100*pStop)
return tList
end randomList