天天看點

邏輯式程式設計語言極簡實作(使用C#) - 2. 一道邏輯題:誰是兇手

使用邏輯式程式設計找出兇手!

Boddy 先生死于謀殺,現有六個嫌疑犯,每個人在不同的房間,每間房間各有一件可能的兇器,但不知道嫌疑犯、房間、兇器的對應關系。請根據條件和線索,找出誰是兇手。

本系列前面的文章:

邏輯式程式設計語言極簡實作(使用C#) - 1. 邏輯式程式設計語言介紹

這是一道Prolog經典的練習題,中文翻譯版來自阮一峰的文章《Prolog 語言入門教程》。

Boddy 先生死于謀殺,現有六個嫌疑犯,每個人在不同的房間,每間房間各有一件可能的兇器,但不知道嫌疑犯、房間、兇器的對應關系。請根據下面的條件和線索,找出誰是兇手。

六個嫌疑犯是三男(George、John、Robert)三女(Barbara、Christine、Yolanda)。

六個嫌疑犯分别待在六個房間:浴室(Bathroom)、飯廳(Dining Room)、廚房(Kitchen)、起房間(Living Room)、 儲藏室(Pantry)、書房(Study)。每間房間都有一件可疑的物品,可以當作兇器:包(Bag)、火槍(Firearm)、瓦斯(Gas)、刀(Knife)、毒藥(Poison)、繩索(Rope)。

所有線索如下:

線索一:廚房裡面是一個男人,那裡的兇器不是繩索、刀子、包和火槍。

線索二:Barbara 和 Yolanda 在浴室和書房。

線索三:帶包的那個人不是 Barbara 和 George,也不在浴室和飯廳。

線索四:書房裡面是一個帶繩子的女人。

線索五:起房間裡面那件兇器,與 John 或 George 在一起。

線索六:刀子不在飯廳。

線索七:書房和食品儲藏室裡面的兇器,沒跟 Yolanda 在一起。

線索八:George 所在的那間屋子有火槍。

線索九:Boddy 先生死在食品儲藏室裡,那裡的兇器是瓦斯。

直接上代碼:

其中一些輔助函數:

<code>k.Is(a, s)</code>: <code>a</code>是集合<code>s</code>的成員。

<code>k.Noto(g1, g2, ...)</code>: <code>g1</code>、<code>g2</code>……都不成立。NMiniKanren并沒有支援“非”運算,這裡用<code>If</code>方法模拟的,僅在一定場合下成立。

<code>k.Distincto(a, b, c, ...)</code>: <code>a</code>、<code>b</code>、<code>c</code>……兩兩不相等。

完整代碼在https://github.com/sKabYY/NMiniKanren/blob/master/NMiniKaren.Tests/Crime.cs

另外,最後使用<code>k.All</code>整合所有條件時,并不是按照順序寫的。了解NMiniKanren運作原理後會知道,這是因為不同順序會影響運作速度。大體上來說,應該盡可能讓分支較少的放前面。

點選運作,等待幾十秒,輸出結果:

兇手是Christine。

繼續閱讀