使用clojure的core.logic / core.match解决Dinesman的多住宅示例

时间:2012-06-29 04:55:14

标签: clojure clojure-core.logic

在观看了Sussman的演讲http://www.infoq.com/presentations/We-Really-Dont-Know-How-To-Compute后,我受到启发,给予core.logic和core.match一个去。我所知道的唯一例子是我以前做过的那些约束问题求解器。这个是SICP课程中使用的一个例子,也在谈话中提到:

  

Baker,Cooper,Fletcher,Miller和Smith住在一栋只有五层楼的公寓楼的不同楼层。贝克不住在顶楼。库珀不住在底层。弗莱彻不住在顶层或底层。米勒生活在比库珀更高的楼层。史密斯不住在弗莱彻附近的地板上。弗莱彻并不住在库珀附近的地板上。每个人住在哪里?

我在rosettacode网站上发现了这个: http://rosettacode.org/wiki/Dinesman%27s_multiple-dwelling_problem#PicoLisp

但不太确定如何转化为clojure。我希望有人可以使用core.logic或core.match

提供解决此问题的示例

2 个答案:

答案 0 :(得分:3)

这是core.logic中的解决方案。它并不完全等同于picolisp算法,因为我们没有相同的原语可用,但它是一般的想法。感谢您向我介绍这个问题 - 发明permuteobeforeo很有趣,我有了第一个使用conda的借口。 修改:使用conda时出现了可怕和错误,我现在回到了conde。哦,有一天。

(ns dwelling.core
  (:refer-clojure :exclude [==])
  (:use clojure.core.logic))

(defn rembero [x l out]
  (fresh [head tail]
    (conso head tail l)
    (conde [(== x head) (== out tail)]
           [(fresh [new-out]
              (conso head new-out out)
              (rembero x tail new-out))])))

(defn permuteo [a b]
  (conde [(emptyo a) (emptyo b)]
         [(fresh [head tail b-tail]
            (conso head tail a)
            (rembero head b b-tail)
            (permuteo tail b-tail))]))

(defn beforeo [x y l]
  (fresh [head tail]
    (conso head tail l)
    (conde [(== x head) (fresh [more-tail]
                          (rembero y tail more-tail))]
           [(beforeo x y tail)])))

(defn not-adjacento [x y l]
  (fresh [head tail more]
    (conso head tail l)
    (resto tail more)
    (conde [(== x head) (membero y more)]
           [(== y head) (membero x more)]
           [(not-adjacento x y tail)])))

(run* [tenants]
  (fresh [a b c d e]
    (== [a b c d e] tenants)
    (permuteo tenants '[Cooper Baker Fletcher Miller Smith])
    (!= e 'Baker)
    (!= a 'Cooper)
    (!= a 'Fletcher)
    (!= e 'Fletcher)
    (beforeo 'Cooper 'Miller tenants)
    (not-adjacento 'Smith 'Fletcher tenants)
    (not-adjacento 'Fletcher 'Cooper tenants)))

;; ([Smith Cooper Baker Fletcher Miller])

答案 1 :(得分:2)

我刚刚开始自己​​进入LP,我的第一个努力是https://github.com/amalloy/doors,是http://rooms.jmpup.com自动生成的逻辑谜题的解算器。现在我已经定义了一些通常对所有谜题都有用的关系,但是我还没有做过任何关于以编程方式将特定谜题翻译成core.logic的工作。您可以看到我手动翻译的一个谜题 - webpage presentationcore.logic encoding。也许这会让你知道如何使用core.logic,虽然我自己还是新手,所以肯定存在不完美之处。

修改

在查看了picolisp解决方案之后,我认为它不会直接转换为core.logic,因为据我所知,直接否定支持尚不存在。