如何从循环中返回延迟序列,并在Clojure中使用条件? [英] How to return a lazy sequence from a loop recur with a conditional in Clojure?
问题描述
对于Clojure和编程来说还是很新的事物,所以可以原谅这个愚蠢的问题.
Still very new to Clojure and programming in general so forgive the stupid question.
问题是:
找到n和k,直到n的数字总和(等于)等于n + 1到k的数字总和.
Find n and k such that the sum of numbers up to n (exclusive) is equal to the sum of numbers from n+1 to k (inclusive).
我的解决方案(效果很好)是定义以下功能:
My solution (which works fine) is to define the following functions:
(defn addd [x] (/ (* x (+ x 1)) 2))
(defn sum-to-n [n] (addd(- n 1)))
(defn sum-to-k [n=1 k=4] (- (addd k) (addd n)))
(defn is-right[n k]
(= (addd (- n 1)) (sum-to-k n k)))
然后运行以下循环:
(loop [n 1 k 2]
(cond
(is-right n k) [n k]
(> (sum-to-k n k) (sum-to-n n) )(recur (inc n) k)
:else (recur n (inc k))))
这仅返回一个答案,但是如果我手动设置n和k,则可以得到不同的值.但是,我想定义一个函数,该函数返回所有值的惰性序列,以便:
This only returns one answer but if I manually set n and k I can get different values. However, I would like to define a function which returns a lazy sequence of all values so that:
(= [6 8] (take 1 make-seq))
我如何尽可能有效地做到这一点?我已经尝试过各种方法,但是运气不太好.
How do I do this as efficiently as possible? I have tried various things but haven't had much luck.
谢谢
:修改:
我想我想出了一种更好的方法,但是它返回的"let应该是一个向量".Clojure文档并没有太大帮助...
I think I came up with a better way of doing it, but its returning 'let should be a vector'. Clojure docs aren't much help...
在这里输入新代码:
(defn calc-n [n k]
(inc (+ (* 2 k) (* 3 n))))
(defn calc-k [n k]
(inc (+ (* 3 k)(* 4 n))))
(defn f
(let [n 4 k 6]
(recur (calc-n n k) (calc-k n k))))
(take 4 (f))
推荐答案
如果您不想自己动手",这是另一种解决方案.我还通过重命名/重新格式化对算法进行了一些整理.
If you don't feel like "rolling your own", here is an alternate solution. I also cleaned up the algorithm a bit through renaming/reformating.
主要区别是您将循环重复视为 t/lazy-gen
形式内的无限循环.找到要保留的值时,可以使用 t/yield
表达式创建输出的惰性序列.就像Python中一样,此结构是 生成器函数 的Clojure版本.
The main difference is that you treat your loop-recur as an infinite loop inside of the t/lazy-gen
form. When you find a value you want to keep, you use the t/yield
expression to create a lazy-sequence of outputs. This structure is the Clojure version of a generator function, just like in Python.
(ns tst.demo.core
(:use tupelo.test )
(:require [tupelo.core :as t] ))
(defn integrate-to [x]
(/ (* x (+ x 1)) 2))
(defn sum-to-n [n]
(integrate-to (- n 1)))
(defn sum-n-to-k [n k]
(- (integrate-to k) (integrate-to n)))
(defn sums-match[n k]
(= (sum-to-n n) (sum-n-to-k n k)))
(defn recur-gen []
(t/lazy-gen
(loop [n 1 k 2]
(when (sums-match n k)
(t/yield [n k]))
(if (< (sum-to-n n) (sum-n-to-k n k))
(recur (inc n) k)
(recur n (inc k))))))
有结果:
-------------------------------
Clojure 1.10.1 Java 13
-------------------------------
(take 5 (recur-gen)) => ([6 8] [35 49] [204 288] [1189 1681] [6930 9800])
您可以找到所有详细信息在图珀洛图书馆.
You can find all of the details in the Tupelo Library.
这篇关于如何从循环中返回延迟序列,并在Clojure中使用条件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!