我编写了一个 Clojure 程序来解决一个相当简单的问题。考虑一个我们需要用整数填充的固定大小的向量。我们必须遵守以下规则。
这是我用评论解决问题的尝试
(ns thickness-optimizer.core
(:refer-clojure :exclude [==])
(:use clojure.core.logic)
(:require [clojure.core.logic.fd :as fd]))
; This is not working properly. It seems very much directional, in that
; it matters if I use lower-upper or upper-lower. The result changes if
; I swap the order of the arguments on the last line of this function.
; I suspect it's an issue where the diff needs to be in the same domain
; as the lower and upper or that possibly negatives are not allowed?
(defn stepLimit [maxStep]
(fn [lower upper]
(let [diffDom (apply fd/domain (range (- maxStep) (+ maxStep 1)))]
(fresh [diff]
(fd/dom diff diffDom)
(fd/- lower upper diff)))))
(defn solve [minimums valids maxStep maxDistinct]
; The result is a list of integers the same length as given minimums.
(let [result (lvars (count minimums))]
(run* [q]
; I'm not sure if this is okay style, but I initialize the result
; outside as a normal list and assign to q inside here so that I
; can use 'rest and 'map on it later.
(== q result)
; Every lvar in the result list is in the domain of given valids.
(everyg #(fd/dom % (apply fd/domain valids)) result)
; Every item in result is pairwise >= the corresponding minimum.
(and* (map #(fd/>= %1 %2) result minimums))
; Between each item in result there's no more than 20 difference.
(and* (map (stepLimit maxStep) result (rest result)))
; There shpuld be no more than maxDistinct distinct values in
; the result. This is not working obviously because I cannot take
; the normal clojure list of distinct values on a list of lvars.
; I'm not really sure how to do this with clore.logic or fd.
;(<= (count (distinct result)) maxDistinct)
)))
(defn main []
(run! println
(solve
[10 10 50]
[10 20 45 50]
20
2)))
相信问题出在我对 fd/- 的使用上。遗憾的是,这个函数没有记录。我也想知道我是否可以为那个 -maxStep - maxStep 域使用间隔,但也没有记录间隔,我真的不知道它们是否可以互换。
输出只是[50 50 50]。我希望 [20 45 50] 是有效的,因为没有超过 20 的跳跃。当然,独特的功能会消除那个,但它被注释掉了。但是 [45 45 50] 也应该可以工作。不过我只得到 [50 50 50]。
我对任何关于 core.logic 风格使用的批评感兴趣,或者我如何才能做得更好。
domain
的实现,很明显它的成员不能是负数。那肯定会破坏您对stepLimit
.的实施
我不是
fd
专家,但看起来你可以只使用正数。仅构建 positive 增量的域,并使用 conde
验证 (- x y)
在该域中,或者 (- y x)
是。