-- Santa Claus Problem: (non-compilable) solution in occam-pi by Adam Sampson -- -- Santa repeatedly sleeps until wakened by either all of his -- nine reindeer, back from their holidays, or by a group of -- three of his ten elves. If awakened by the reindeer, he -- harnesses each of them to his sleigh, delivers toys with -- them and finally unharnesses them (allowing them to go off -- on holiday). If awakened by a group of elves, he shows each -- of the group into his study, consults with them on toy R&D -- and finally shows them each out (allowing them to go back to -- work). Santa should give priority to the reindeer in the -- case that there is both a group of elves and a group of -- reindeer waiting. -- -- "Jingle Bells: Solving the Santa Claus Problem in Polyphonic C#" -- by Nick Benton #USE "course.lib" VAL INT n.reindeer IS 9: VAL INT need.reindeer IS n.reindeer: VAL INT n.elves IS 10: VAL INT need.elves IS 3: VAL INT max.group IS 10: -- Santa uses client end RECURSIVE CHAN TYPE CHAT MOBILE RECORD CHAN INT num!: CHAN CHAT! done?: : PROTOCOL GROUP IS INT::[]CHAT!: PROTOCOL REPORT IS INT::[]BYTE ; INT ; INT::[]BYTE: PROC send.report (SHARED CHAN REPORT rep!, VAL []BYTE type, VAL INT number, VAL []BYTE msg) CLAIM rep! rep ! (SIZE type)::type ; number ; (SIZE msg)::msg : PROC reindeer (SHARED CHAN REPORT rep!, VAL INT num, CHAN CHAT! group!) CHAT! cli: CHAT? svr: SEQ cli, svr := MOBILE CHAT WHILE TRUE SEQ send.report (rep!, "Reindeer", num, "Back from holiday") group ! cli svr[num] ! num send.report (rep!, "Reindeer", num, "Attached to sleigh") svr[done] ? cli send.report (rep!, "Reindeer", num, "Going on holiday") : PROC elf (SHARED CHAN REPORT rep!, VAL INT num, CHAN CHAT! group!) CHAT! cli: CHAT? svr: SEQ cli, svr := MOBILE CHAT WHILE TRUE SEQ send.report (rep!, "Elf", num, "I need to talk to Santa") group ! cli svr[num] ! num send.report (rep!, "Elf", num, "Talking to Santa") svr[done] ? cli send.report (rep!, "Elf", num, "Going back to work") : PROC santa (SHARED CHAN REPORT rep!, CHAN GROUP reindeer?, elves?) WHILE TRUE INT count: [max.group]INT num: [max.group]CHAT! chat: PRI ALT reindeer ? count::chat SEQ send.report (rep!, "Santa", 0, "Awakened by reindeer") SEQ i = 0 FOR count SEQ chat[i][num] ? num[i] send.report (rep!, "Santa", num[i], "Harnessed reindeer") send.report (rep!, "Santa", 0, "Delivering presents") SEQ i = 0 FOR count SEQ send.report (rep!, "Santa", num[i], "Unharnessing reindeer") chat[i][done] ! chat[i] send.report (rep!, "Santa", 0, "Returning to bed") elves ? count::chat SEQ send.report (rep!, "Santa", 0, "Awakened by elves") SEQ i = 0 FOR count SEQ send.report (rep!, "Santa", 0, "Letting elf in") chat[i][num] ? num[i] send.report (rep!, "Santa", num[i], "Talking to elf") chat[i][done] ! chat[i] send.report (rep!, "Santa", num[i], "Done with elf") send.report (rep!, "Santa", 0, "Returning to bed") : PROC grouper ([]CHAN CHAT! in?, CHAN GROUP out!, VAL INT need.count) INITIAL INT count IS 0: [max.group]CHAT! chat: WHILE TRUE ALT i = 0 FOR SIZE in in[i] ? chat[count] SEQ count := count + 1 IF count = need.count SEQ out ! count::[chat FROM 0 FOR count] count := 0 TRUE SKIP : PROC report.display(SHARED CHAN REPORT in?, CHAN BYTE out!) WHILE TRUE INT type.s, message.s, number: [80]BYTE type, message: SEQ CLAIM in? in ? type.s::type ; number ; message.s::message out.string ([type FROM 0 FOR type.s], 0, out!) out ! ' ' out ! '#' out.int (number, 0, out!) out ! ' ' out.string ([message FROM 0 FOR message.s], 0, out!) out ! '*n' : PROC santa.claus.problem (CHAN BYTE keyb?, scr!, err!) SHARED CHAN REPORT rep: [n.reindeer]CHAN CHAT! from.reindeer: [n.elves]CHAN CHAT! from.elf: CHAN GROUP reindeer, elves: PAR PAR i = 0 FOR n.reindeer reindeer (rep!, (i + 1), from.reindeer[i]!) grouper (from.reindeer?, reindeer!, need.reindeer) PAR i = 0 FOR n.elves elf (rep!, (i + 1), from.elf[i]!) grouper (from.elf?, elves!, need.elves) santa (rep!, reindeer?, elves?) report.display (rep?, scr!) :