function amb(sequence sets, integer testrid, integer resrid=-1, object res=0, integer idx=1) integer flag = (res==0) integer pass = 0 if idx>length(sets) then pass = 1 if resrid!=-1 then call_proc(resrid,{sets,res}) end if else if flag then res = repeat(0,length(sets)) end if for k=1 to length(sets[idx]) do res[idx] = k if flag or call_func(testrid,{sets,res,idx}) then {pass,res} = amb(sets,testrid,resrid,res,idx+1) if pass and resrid=-1 then exit end if end if end for end if return {pass,res} end function function pairable(sequence sets, sequence res, integer idx) return sets[idx-1][res[idx-1]][$] = sets[idx][res[idx]][1] end function constant r_pairable = routine_id("pairable") procedure AMB_Show(sequence sets, sequence res) puts(1,"success: ") for i=1 to length(sets) do res[i] = sets[i][res[i]] end for ?res end procedure constant r_show = routine_id("AMB_Show") function pythagorean(sequence sets, sequence res, integer idx) -- (note that res[idx]==sets[idx][res[idx]] in all cases) integer x, y, z if sequence(sets) then end if -- (suppress warning) {x,y,z} = res return idx<3 or (x*x+y*y=z*z) end function constant r_pythagorean = routine_id("pythagorean") procedure pythag_show(sequence sets, sequence res) if sequence(sets) then end if -- (suppress warning) puts(1,"success: ") ?res end procedure constant r_pythag_show = routine_id("pythag_show") -- see http://www.randomhacks.net/articles/2005/10/11/amb-operator function not8(sequence sets, sequence res, integer idx) -- (note that idx==2 in all cases) -- (at the last moment, I flipped the test, after realising that -- someone had completely misunderstood the original article... -- ...and proved it by showing some strange output on rosetta.) -- return sets[1][res[1]]*sets[idx][res[idx]]!=8 return sets[1][res[1]]*sets[idx][res[idx]]=8 end function constant r_not8 = routine_id("not8") procedure not8_show(sequence sets, sequence res) puts(1,"success: ") ?{sets[1][res[1]],sets[2][res[2]]} end procedure constant r_not8_show = routine_id("not8_show") sequence sets = {{"the","that","a"}, {"frog","elephant","thing"}, {"walked","treaded","grows"}, {"slowly","quickly"}} sequence sets2 = repeat(tagset(11),3) sequence sets3 = {{1, 2, 3}, {4, 5, 6}} puts(1,"\nThe original:\n") {} = amb(sets,r_pairable,r_show) puts(1,"\nSmall Pythagorean triples problem:\n") {} = amb(sets2,r_pythagorean,r_pythag_show) puts(1,"\nSome strange not 8 problem:\n") -- (now fixed) {} = amb(sets3,r_not8,r_not8_show)