說謊者謎題是sicp4.3.2小節的一道題目,題目本身不難:
五個女生參加乙個考試,她們的家長對考試結果過分關注。為此她們約定,在給家裡寫信談到考試的時候,每個姑娘都要寫一句真話和一句假話。下面是從她們的信裡摘抄出來的句子:
betty : kitty考第二,我只考了第三
ethel : 你們應該很高興聽到我考了第一,joan第二
joan : 我考第三,可憐的ethel墊底
kitty: 我第二,marry只考了第四
marry: 我是第四,betty的成績最高。
這五個姑娘的實際排名是什麼?
ruby本來就有call/cc,因此也可以實現amb操作符,網上已經有乙個實現了:
class
ambclass
exhaustederror
<
runtimeerror; end
def initialize
@fail
=proc
enddef choose(
*choices)
prev_fail
=@fail
callcc
ifchoice.respond_to
?:call
sk.call(choice.call)
else
sk.call(choice)
end}
}@fail.call
}end
def failure
choose
enddef
assert
(cond)
failure unless cond
endalias :require :
assert
end
這一段**與scheme巨集實現amb是完全相同的:
(define amb
-fail '*)
(define initialize
-amb
-fail
(lambda
()(set! amb
-fail
(lambda
()(error
"amb tree exhausted
")))))
(initialize
-amb
-fail)
(define call
/cc call
-with
-current
-continuation)
(define
-syntax amb
(syntax
-rules ()
((amb alt
(let ((prev
-amb
-fail amb
-fail))
(call/cc
(lambda
(sk)
(call/cc
(lambda
(fk)
(set! amb
-fail
(lambda
()(set! amb
-fail prev
-amb
-fail)
(fk
'fail)))
(sk alt)))
(prev
-amb
-fail)))))))
回到謎題,從題意可知每個姑娘的兩句話的異或結果為true,並且姑娘的排名肯定不會相同,因此定義兩個輔助過程:
require
'amb
'def
distinct?(items)
items.uniq
==items
enddef
xor(exp1,exp2)
(exp1
orexp2)
and!(exp1
andexp2)
end 剩下的完全就是將題目翻譯成**即可了,沒有多少可以解釋的東西:
amb=amb.new
betty
=amb.choose(*[
1,2,
3,4,
5])ethel
=amb.choose(*[
1,2,
3,4,
5])joan
=amb.choose(*[
1,2,
3,4,
5])kitty
=amb.choose(*[
1,2,
3,4,
5])marry
=amb.choose(*[
1,2,
3,4,
5])amb.require(xor(kitty==2
,betty==3
))amb.require(xor(ethel==1
,joan==2
))amb.require(xor(joan==3
,ethel==5
))amb.require(xor(kitty==2
,marry==4
))amb.require(xor(marry==4
,betty==1
))amb.require(distinct?([betty,ethel,joan,kitty,marry]))
puts
"betty:# ethel:# joan:# kitty:# marry:#"
答案就是:
betty:3 ethel:5 joan:2 kitty:1 marry:4
最後給出乙個prolog的解答:
notmember(a,).
notmember(a,[b
|l]):-a\
==b,
notmember(a,l).
distinct([a,b,c,d,e]):
-notmember(a,[b,c,d,e]),
notmember(b,[a,c,d,e]),
notmember(c,[a,b,d,e]),
notmember(d,[a,b,c,e]),
notmember(e,[a,b,c,d]).
xor(exp1,exp2):
-(exp1;exp2),\
+(exp1,exp2).
solve(betty,ethel,joan,kitty,marry):-x
=[1,
2,3,
4,5],
member(betty,x),
member(ethel,x),
member(joan,x),
member(kitty,x),
member(marry,x),
distinct([betty,ethel,joan,kitty,marry]),
xor(kitty=:
=2,betty=:
=3),xor(ethel=:
=1,joan=:
=2),xor(joan=:
=3,ethel=:
=5),xor(kitty=:
=2,marry=:
=4),xor(marry=:
=4,betty=:
=1).
文章**莊周夢蝶 ,原文發布時間2008-11-15
使用Ruby amb解決說謊者謎題
說謊者謎題是sicp4.3.2小節的一道題目,題目本身不難 五個女生參加乙個考試,她們的家長對考試結果過分關注。為此她們約定,在給家裡寫信談到考試的時候,每個姑娘都要寫一句真話和一句假話。下面是從她們的信裡摘抄出來的句子 betty kitty考第二,我只考了第三 ethel 你們應該很高興聽到我考...
誠實者與說謊者問題
問題描述 誠實者與說謊者 內容 有兩個人,乙個是誠實者,乙個是說謊者。誠實者只說真話,說謊者只說假話!兩個人都知道身後兩扇門哪個是對的,哪個是錯的!但情況是不知道誰是誠實者,誰是說謊者。要求 現在你只有一次機會向其中之一問乙個問題來確定那個對的門!你會怎麼問呢?答案 隨便找乙個人問 如果我問另外乙個...
使用管程法解決生產者消費者問題
package com.test.thread 測試生產者消費者模型 利用緩衝區解決 管程法 生產者,消費者,產品,緩衝區 public class testpc 生產者類 class productor extends thread 生產雞!override public void run 消費者...