サーバーサイドJavaScript(Rhino)の継続でambを書いてみた
"amb は 天使のオペレータです。" 独習 Scheme 三週間
ambで、三平方の定理を満たす整数の組を探す。
var fail = []; function amb(l) { if (l.length == 0) return (fail.pop())(); var k = new Continuation(); fail.push(function () {k(amb(l.slice(1)))}); return l[0]; } function pythag(a,b,c) { if (a * a + b * b == c * c) return [a,b,c]; amb([]); } print((function() { var k = new Continuation(); fail.push(function() {k("no choise")}); return pythag(amb([1,2,3]),amb([3,4,5]),amb([4,5,6])); })());
% rhino -opt -1 -f pythag.js
3,4,5
("-opt -1"をつけるのは継続を使うため)
次は、ambで論理パズルを解いてみる。
SICP の問題 4.42. を解いてみましょう。問題は以下の通りです:
5人の女子生徒が試験を受けた。彼女らの両親は結果に対し過度の関心を持っている、と彼女らは考えている。 そこで彼女らは自宅へ試験についての手紙を書くのに、誰もが1つの正しい情報と1つのうその情報を書こうと 約束した。以下は彼女らの手紙の関係する部分である。
Betty: 「Kitty は試験が2番で私は3番でした。」
Ethel: 「私がトップと聞いてうれしいでしょう。Joan が2ばんでした。」
Joan: 「私は3番でした。可哀想な Ethel はビリでした。」
Kitty: 「私は2番になりました。Mary は4番でしかありませんでした。」
Mary: 「私は4番でした。トップの座は Betty がとりました。」
5人の女子生徒の本当の順番はどうなっているのか。
var fail = []; function amb(l) { if (l.length == 0) return (fail.pop())(); var k = new Continuation(); fail.push(function () {k(amb(l.slice(1)))}); return l[0]; } function assert(pred) { pred ? true : amb([]); } function xor(a,b) { return a ? !b: b; } function allDifferent() { if (arguments.length <= 1) return true; for (var i = 0; i < arguments.length; i++) { for (var j = i + 1; j < arguments.length; j++) { if (arguments[i] == arguments[j]) return false; } }; return true; } //SICP Exercise 4.42 function girlsExam() { var kitty = amb([1, 2, 3, 4, 5]); var betty = amb([1, 2, 3, 4, 5]); assert(xor((kitty == 2), (betty == 3))); var mary = amb([1, 2, 3, 4, 5]); assert(xor((kitty == 2), (mary == 4))); assert(xor((mary == 4), (betty == 1))); var ethel = amb([1, 2, 3, 4, 5]); var joan = amb([1, 2, 3, 4, 5]); assert(xor((ethel == 1), (joan == 2))); assert(xor((joan == 3), (ethel == 5))); assert(allDifferent(kitty, betty, ethel, joan, mary)); return ["kitty", kitty, "betty", betty, "ethel", ethel, "joan" , joan, "mary" , mary]; } print((function () { var k = new Continuation(); fail.push(function() {k("no choise")}); return girlsExam(); })());
% rhino -opt -1 -f girls.js
kitty,1,betty,3,ethel,5,joan,2,mary,4