我一直在努力解决Clojure中的Project Euler问题,以便变得更好,而且我已经遇到了几次素数.我的问题是它只是花了太长时间.我希望有人可以帮我找到一种以Clojure-y方式做到这一点的有效方法.
当我拳头做到这一点时,我粗暴地强迫它.这很容易做到.但是计算10001个素数在Xeon 2.33GHz上用了2分钟,对规则来说太长了,一般来说太长了.这是算法:
(defn next-prime-slow
"Find the next prime number, checking against our already existing list"
([sofar guess]
(if (not-any? #(zero? (mod guess %)) sofar)
guess ; Then we have a prime
(recur sofar (+ guess 2))))) ; Try again
(defn find-primes-slow
"Finds prime numbers, slowly"
([]
(find-primes-slow 10001 [2 3])) ; How many we need, initial prime seeds
([needed sofar]
(if (<= needed (count sofar))
sofar ; Found enough, we're done
(recur needed (concat sofar [(next-prime-slow …Run Code Online (Sandbox Code Playgroud) 我喜欢Clojure.困扰我的一个问题是我不知道如何实现懒惰的序列,或者它们是如何工作的.
我知道懒惰序列只评估序列中要求的项目.它是如何做到的?
我有一对向量x和y独特的项目,我知道每个项目都要排序.我希望有两者的交集,维持排序顺序.理想情况下,结果将是另一个向量,用于快速随机访问.
下面的代数仅仅是为了举例,我x和y将会预先分类和预先分开(它们实际上是时间样本).
(defn gen-example [c] (-> (repeatedly c #(-> c rand int)) distinct sort vec))
user=> (def x (gen-example 100000)) (count x)
#'user/x
63161
user=> (def y (gen-example 100000)) (count y)
#'user/y
63224
Run Code Online (Sandbox Code Playgroud)
我知道Clojure clojure.set/intersection可以用于sorted-set.我x和y具有相同的属性(排序不同的元素)但不是相同的类型.
问题1:是否有转换更好/更快的方式x,并y以sorted-set除S (apply sorted-set x)因为他们已经明显和排序?
user=> (time (def ssx (apply sorted-set x)))
"Elapsed time: 607.642592 msecs"
user=> (time (def ssy (apply sorted-set y)))
"Elapsed …Run Code Online (Sandbox Code Playgroud) 我试图理解clojure的lazy-seq运算符,以及懒惰评估的概念.我知道这个概念背后的基本思想:表达式的评估会延迟到需要的值.
一般来说,这可以通过两种方式实现:
使用惰性求值技术,可以构造被评估为已消耗的无限数据结构.这些无限序列利用lambdas,闭包和递归.在clojure中,这些无限数据结构是使用lazy-seq和cons形成的.
我想知道lazy-seq它是如何神奇的.我知道它实际上是一个宏.请考虑以下示例.
(defn rep [n]
(lazy-seq (cons n (rep n))))
Run Code Online (Sandbox Code Playgroud)
这里,rep函数返回一个延迟评估的类型序列LazySeq,现在可以使用序列API对其进行转换和使用(从而进行求值).这个API提供的功能take,map,filter和reduce.
在扩展形式中,我们可以看到lambda如何用于存储单元格的配方而不立即进行评估.
(defn rep [n]
(new clojure.lang.LazySeq (fn* [] (cons n (rep n)))))
Run Code Online (Sandbox Code Playgroud)
LazySeq?(reduce + (take 3 (map inc (rep 5))))
map应用于序列,take限制序列和reduce评估序列?另外,这些功能如何与a Vector或a一起使用LazySeq?
此外, …
您可以在协议中提示返回类型
(defprotocol Individual
(^Integer age [this]))
Run Code Online (Sandbox Code Playgroud)
并且编译器将使您的方法符合:
(defrecord person []
Individual
(^String age [this] "one"))
; CompilerException java.lang.IllegalArgumentException: Mismatched return type: age, expected: java.lang.Object, had: java.lang.String, ...
Run Code Online (Sandbox Code Playgroud)
但是您不必遵守类型提示:
(defrecord person []
Individual
(age [this] "one"))
(age (new person))
; "one"
Run Code Online (Sandbox Code Playgroud)
类型提示有效吗?
追求4Clojure 问题178 - 最好的手,我有这个用于将卡值从字符转换为数字:
(fn [ch]
(or
({\A 1} ch)
((zipmap "TJQK" (iterate inc 10)) ch)
(- (int ch) (int \0))))
Run Code Online (Sandbox Code Playgroud)
在zipmap每次通话表达式,总是产生{\K 13, \Q 12, \J 11, \T 10}.
我们怎样才能让编译器只评估一次?
经过多次脑力激荡,我想到了
(defmacro constant [exp] (eval exp))
Run Code Online (Sandbox Code Playgroud)
...包裹zipmap呼叫:
(constant (zipmap "TJQK" (iterate inc 10)))
Run Code Online (Sandbox Code Playgroud)
我认为这相当于
(eval '(zipmap "TJQK" (iterate inc 10)))
Run Code Online (Sandbox Code Playgroud)
......但不是eval没有引用:
(eval (zipmap "TJQK" (iterate inc 10)))
Run Code Online (Sandbox Code Playgroud)
欢迎更正,评论和改进.
Clojure 中是否有一种快速方法来检查序列是否恰好有 1 个元素?请注意,序列可能包含 nils。
如果我正确读取源代码,调用count序列需要 O(n) 时间。
替代解决方案:
(and
(not (empty? a-seq))
(empty? (rest a-seq)))
Run Code Online (Sandbox Code Playgroud)
文档说调用empty?集合与coll调用相同(not (seq coll)),但他们没有指定其效率或调用empty?序列时会发生什么。我尝试在 github 存储库中搜索其empty?实现方式,但它忽略了搜索中的问号,并且出现了大量“空”的点击。我想empty?是restO(1),但话又说回来,count不是......
在定义无限序列时,我注意到缺点是避免无限递归.但是,我不明白的是为什么.这是有问题的代码:
(defn even-numbers
([] (even-numbers 0))
([n] (cons n (lazy-seq (even-numbers (+ 2 n))))))
(take 10 (even-numbers))
;; (0 2 4 6 8 10 12 14 16 18)
Run Code Online (Sandbox Code Playgroud)
这很好用; 但由于我喜欢质疑,我开始想知道为什么需要利弊(除了包括0).毕竟,lazy-seq函数创建了一个lazy-seq.这意味着,在调用(或分块)之前,不应计算其余值.所以,我试过了.
(defn even-numbers-v2
([] (even-numbers-v2 0))
([n] (lazy-seq (even-numbers-v2 (+ 2 n)))))
(take 10 (even-numbers-v2))
;; Infinite loooooooooop
Run Code Online (Sandbox Code Playgroud)
所以,现在我知道缺点是必要的,但是我想知道为什么有必要对所谓的懒惰序列进行惰性评估
是否可以转换以下代码,使其使用defprotocol和defrecord代替defmultiand defmethod?
(defmulti test-multimethod (fn [keyword] keyword))
(defmethod test-multimethod :foo [a-map]
"foo-method was called")
(defmethod test-multimethod :bar [a-map]
"bar-method was called")
(defmulti perimeter (fn [shape] (:shape-name shape)))
(defmethod perimeter :circle [circle]
(* 2 Math/PI (:radius circle)))
(defmethod perimeter :rectangle [rectangle]
(+ (* 2 (:width rectangle)) (* 2 (:height rectangle))))
(def some-shapes [{:shape-name :circle :radius 4}
{:shape-name :rectangle :width 2 :height 2}])
(defmulti area (fn [shape] (:shape-name shape)))
(defmethod area :circle [circle]
(* Math/PI …Run Code Online (Sandbox Code Playgroud)