在观看了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
提供解决此问题的示例答案 0 :(得分:3)
这是core.logic中的解决方案。它并不完全等同于picolisp算法,因为我们没有相同的原语可用,但它是一般的想法。感谢您向我介绍这个问题 - 发明permuteo
和beforeo
很有趣,我有了第一个使用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 presentation和core.logic encoding。也许这会让你知道如何使用core.logic,虽然我自己还是新手,所以肯定存在不完美之处。
在查看了picolisp解决方案之后,我认为它不会直接转换为core.logic,因为据我所知,直接否定支持尚不存在。