| -- The Great Computer Language Shootout |
| -- http://shootout.alioth.debian.org/ |
| -- contributed by Mike Pall |
| |
| local co = coroutine |
| local create, resume, yield = co.create, co.resume, co.yield |
| |
| local N = tonumber(arg and arg[1]) or 10 |
| local first, second |
| |
| -- Meet another creature. |
| local function meet(me) |
| while second do yield() end -- Wait until meeting place clears. |
| local other = first |
| if other then -- Hey, I found a new friend! |
| first = nil |
| second = me |
| else -- Sniff, nobody here (yet). |
| local n = N - 1 |
| if n < 0 then return end -- Uh oh, the mall is closed. |
| N = n |
| first = me |
| repeat yield(); other = second until other -- Wait for another creature. |
| second = nil |
| yield() -- Be nice and let others meet up. |
| end |
| return other |
| end |
| |
| -- Create a very social creature. |
| local function creature(color) |
| return create(function() |
| local me = color |
| for met=0,1e9 do |
| local other = meet(me) |
| if not other then return met end |
| if me ~= other then |
| if me == "blue" then me = other == "red" and "yellow" or "red" |
| elseif me == "red" then me = other == "blue" and "yellow" or "blue" |
| else me = other == "blue" and "red" or "blue" end |
| end |
| end |
| end) |
| end |
| |
| -- Trivial round-robin scheduler. |
| local function schedule(threads) |
| local resume = resume |
| local nthreads, meetings = table.getn(threads), 0 |
| repeat |
| for i=1,nthreads do |
| local thr = threads[i] |
| if not thr then return meetings end |
| local ok, met = resume(thr) |
| if met then |
| meetings = meetings + met |
| threads[i] = nil |
| end |
| end |
| until false |
| end |
| |
| -- A bunch of colorful creatures. |
| local threads = { |
| creature("blue"), |
| creature("red"), |
| creature("yellow"), |
| creature("blue"), |
| } |
| |
| io.write(schedule(threads), "\n") |