<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    莊周夢蝶

    生活、程序、未來
       :: 首頁 ::  ::  :: 聚合  :: 管理

    使用Ruby amb解決說謊者謎題

    Posted on 2008-11-15 18:50 dennis 閱讀(4413) 評論(3)  編輯  收藏 所屬分類: 動態語言計算機科學與基礎
        說謊者謎題是sicp4.3.2小節的一道題目,題目本身不難:
    五個女生參加一個考試,她們的家長對考試結果過分關注。為此她們約定,在給家里寫信談到考試的時候,每個姑娘都要寫一句真話和一句假話。下面是從她們的信里摘抄出來的句子:
    Betty : kitty考第二,我只考了第三
    Ethel : 你們應該很高興聽到我考了第一,joan第二
    joan :   我考第三,可憐的Ethel墊底
    kitty:  我第二,marry只考了第四
    marry: 我是第四,Betty的成績最高。
    這五個姑娘的實際排名是什么?

        Ruby本來就有call/cc,因此也可以實現amb操作符,網上已經有一個實現了:
    class Amb
      
    class ExhaustedError < RuntimeError; end
      def initialize
        @fail 
    = proc { fail ExhaustedError, "amb tree exhausted" }
      end
      def choose(
    *choices)
        prev_fail 
    = @fail
        callcc { 
    |sk|
          choices.each { 
    |choice|
            callcc { 
    |fk|
              @fail 
    = proc {
                @fail 
    = prev_fail
                fk.call(:fail)
              }
              
    if choice.respond_to? :call
                sk.call(choice.call)
              
    else
                sk.call(choice)
              end
            }
          }
          @fail.call
        }
      end
      def failure
        choose
      end
      
      def 
    assert(cond)
        failure unless cond
      end
      alias :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
    end
    def xor(exp1,exp2)
     (exp1 
    or exp2) and !(exp1 and exp2)
    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:#{betty} ethel:#{ethel} joan:#{joan} kitty:#{kitty} marry:#{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).



    評論

    # re: 使用Ruby amb解決說謊者謎題  回復  更多評論   

    2008-11-16 18:48 by ychael
    這個AMB挺有趣,人是不是就有這個沖動勁,除了死怎么或者都行

    # re: 使用Ruby amb解決說謊者謎題  回復  更多評論   

    2008-11-16 19:07 by dennis
    @ychael
    啥意思啊,不明白

    # re: 使用Ruby amb解決說謊者謎題[未登錄]  回復  更多評論   

    2010-04-05 15:03 by frank
    @dennis
    這都不明白別人說什么,嘿嘿
    主站蜘蛛池模板: 最近免费2019中文字幕大全| 国产AV无码专区亚洲AV漫画 | 日本免费网址大全在线观看| 一级免费黄色大片| 亚洲愉拍一区二区三区| 久久久无码精品亚洲日韩蜜臀浪潮 | 亚洲一区二区三区乱码A| 黄色片在线免费观看 | 亚洲国产aⅴ综合网| 最近中文字幕mv免费高清电影| 男人都懂www深夜免费网站| 亚洲黄片手机免费观看| 阿v免费在线观看| 亚洲av成人无码网站…| 亚洲日本一线产区和二线| 亚洲成人午夜电影| 久久亚洲精品成人AV| 亚洲AV成人精品网站在线播放| 浮力影院亚洲国产第一页| 国产91在线免费| 国产色婷婷精品免费视频| 免费毛片在线看片免费丝瓜视频 | 亚洲六月丁香六月婷婷蜜芽| 91天堂素人精品系列全集亚洲| 亚洲va无码va在线va天堂| 国产亚洲精品成人a v小说| 亚洲国产精品一区二区九九 | 亚洲欧美精品午睡沙发| 亚洲电影免费在线观看| h视频在线免费观看| 亚洲av无码专区首页| 亚洲色精品VR一区区三区| 亚洲国产成人综合| 亚洲性一级理论片在线观看| 亚洲欧洲日产国码www| 91亚洲精品麻豆| 亚洲永久在线观看| 亚洲一区二区观看播放| 亚洲AV无码一区二区三区性色| 春暖花开亚洲性无区一区二区| 色天使亚洲综合一区二区|