使用Ruby amb解決說謊者謎題

2021-08-29 17:45:44 字數 3619 閱讀 9474

說謊者謎題是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).

使用Ruby amb解決說謊者謎題

說謊者謎題是sicp4.3.2小節的一道題目,題目本身不難 五個女生參加乙個考試,她們的家長對考試結果過分關注。為此她們約定,在給家裡寫信談到考試的時候,每個姑娘都要寫一句真話和一句假話。下面是從她們的信裡摘抄出來的句子 betty kitty考第二,我只考了第三 ethel 你們應該很高興聽到我考...

誠實者與說謊者問題

問題描述 誠實者與說謊者 內容 有兩個人,乙個是誠實者,乙個是說謊者。誠實者只說真話,說謊者只說假話!兩個人都知道身後兩扇門哪個是對的,哪個是錯的!但情況是不知道誰是誠實者,誰是說謊者。要求 現在你只有一次機會向其中之一問乙個問題來確定那個對的門!你會怎麼問呢?答案 隨便找乙個人問 如果我問另外乙個...

使用管程法解決生產者消費者問題

package com.test.thread 測試生產者消費者模型 利用緩衝區解決 管程法 生產者,消費者,產品,緩衝區 public class testpc 生產者類 class productor extends thread 生產雞!override public void run 消費者...