我有这个功能:
(defn find-max-palindrom-in-range [beg end]
(reduce max
(loop [n beg result []]
(if (>= n end)
result
(recur (inc n)
(concat result
(filter #(is-palindrom? %)
(map #(* n %) (range beg end)))))))))
我尝试像这样运行:
(find-max-palindrom-in-range 100 1000)
我得到了这个例外:
java.lang.Integer cannot be cast to clojure.lang.IFn
[Thrown class java.lang.ClassCastException]
我认为这意味着在某个地方我试图将整数作为一个函数进行评估。然而,我无法找到这个地方,更让我感到困惑的是,如果我只是像这样评估它,一切都有效:
(reduce max
(loop [n 100 result []]
(if (>= n 1000)
result
(recur (inc n)
(concat result
(filter #(is-palindrom? %)
(map #(* n %) (range 100 1000))))))))
(我刚刚删除了函数定义并用常量替换了参数)
先谢谢你的帮助,对不起,我可能会因为我的愚蠢错误而烦你。顺便说一下,我正在使用Clojure 1.1和ELPA最新的SLIME。
修改:以下是 is-palindrom?的代码。我已经将它实现为数字的文本属性,而不是数字属性。
(defn is-palindrom? [n]
(loop [num (String/valueOf n)]
(cond (not (= (first num) (last num))) false
(<= (.length num) 1) true
:else (recur (.substring num 1 (dec (.length num)))))))
答案 0 :(得分:6)
代码适用于我的REPL(1.1)。我建议你把它贴在你的身上然后再试一次 - 也许你只是错误的输入了什么?
话虽如此,您可以将此作为一个使代码更简单,更明显正确的机会。一些低调的果实(如果你认为它可能会剥夺你的Project Euler乐趣,请不要阅读,尽管你的逻辑已经记录下来,我认为它不应该):
您无需在匿名函数中包装is-palindrome?
即可将其传递给filter
。只需写下(filter is-palindrome? ...)
。
loop
中的is-palindrome?
非常复杂。此外,它不是特别有效(first
和last
首先从字符串中生成seq
,然后last
需要遍历所有字符串。 (require '[clojure.contrib.str-utils2 :as str])
并使用(= num (str/reverse num))
。
由于我提到了效率,以这种方式使用concat
有点危险 - 它会产生一个懒惰的seq,如果你堆积两个级别的懒惰可能会爆炸(这无关紧要在欧拉4的背景下,但记住它是好的)。如果您确实需要向右扩展向量,请选择into
。
为了进一步简化,您可以考虑将它们拆分为一个函数来过滤给定的序列,以便只保留回文并且单独的函数返回两个三位数字的所有产品。后者可以用例如
完成(for [f (range 100 1000)
s (range 100 1000)
:when (<= f s)] ; avoid duplication of effort
(* f s))