【Clojure】在loop-recur中实现多重循环
来源:互联网 发布:淘宝网邮票真假 编辑:程序博客网 时间:2024/06/04 18:12
问题
在loop-recur中实现多重循环(里:如何造一个轮子)
描述
在loop-recur中使用一个N重循环是很痛苦的(脑细胞在燃烧),这时候可以使用一个生成N重循环下标列表的工具,在loop-recur中实现多重循环
代码
(defn smooth [cur config] (let [cur (reverse cur) config (reverse config) ps (map #(list % %2) cur config)] (loop [carry 0 head (first ps) tail (rest ps) ret '()] (if (nil? head) ret (let [[x y] head the-carry (quot (+ carry x) y) the-rest (mod (+ carry x) y)] (recur the-carry (first tail) (rest tail) (conj ret the-rest))))))); only for test!(smooth (map + [1 2 3] [3 9 9]) [10 10 10]) (smooth (map + [1 2 3] [1 1 1]) [10 10 10]) (smooth [0 2 2] [2 2 2]) (defn smooth-ex [numbers limits] (let [numbers (reverse numbers) limits (reverse limits) pairs (map #(list % %2) numbers limits)] (loop [carry 0 head (first pairs) tail (rest pairs) ret '()] (if (nil? head) ret (let [[number limit] head the-carry (quot (+ carry number) limit) the-rest (mod (+ carry number) limit)] (recur the-carry (first tail) (rest tail) (conj ret the-rest)))))))(defn looper-unit [looper] (if (= (count looper) 0) '() (let [zero-cnt (dec (count looper))] (into '(1) (repeat zero-cnt 0)))))(defn is-looper-end? [looper looper-end] (= (map inc looper) looper-end))(defn looper-next [looper looper-end] (smooth (map + looper (looper-unit looper)) looper-end))(defn looper-demo [looper-end] (loop [looper (repeat (count looper-end) 0) ret []] (let [[i j] looper looper-string (str "row:" i " " "col:" j)] (if (is-looper-end? looper looper-end) (ret conj looper-string) (recur (looper-next looper looper-end) (conj ret looper-string)))))); just for test!(map println (looper-demo [3 3]))
说明
smooth
: 类似大数加法中的进位操作,处理循环中下标的进位操作
smooth-ex
: smooth
的容易阅读的版本 …
looper-unit
: 生成循环的递增单位,即一个形如 (0 ... 0 1)
的列表, 可能不含0
其他函数顾名思义,不解释了
核心思想即产生一系列列表,例如一个二重循环:
for(int i = 0; i < 2; ++i) for(int j = 0; j < 2; ++j) { /* excuse me */}
其下标对应的序列为:
[ (0 0) (0 1) (1 0) (1 1) ]
那么对于任意循环,我们只需要生成该列表组就可以进行循环操作, 那么在哪里可以买到呢:
注意 (0 0)
到 (0 1)
的变化过程:
(= '(0 1) (map + '(0 0) '(0 1)))
而 (0 1)
到 (1 0)
的变化过程则较为复杂,但这一变化可以看作二进制下 01 + 01 => 10
的过程
宗上可以看出,生成列表的过程可以看作是一个N进制数字自增的过程,特别的是这里的每一个位可能对应不同的进制(比如上面那个循环把j的限制改成 j < 100
, 就变成了i是2进制,j是100进制的自增过程)
利用这一性质产生了如上的编码(轮子),具体使用方法参考 looper-demo
, 配合解构操作可以顺利获得各循环变量, 然后瞎鸡巴乱搞
最后需要注意的是,对循环的限制是左闭右开区间, (looper-end [5 5])
得到的是一个 0-4 的二重循环
clojure多行注释太麻烦了,最后补上 (map println (looper-demo [3 3]))
的输出结果
; 不是代码 仅供参考=> (map println (looper-demo [3 3]))row:0 col:0row:0 col:1row:0 col:2row:1 col:0row:1 col:1row:1 col:2row:2 col:0row:2 col:1row:2 col:2(nil nil nil nil nil nil nil nil nil); 最后的一串nil是prinln的返回值被map收集了, 因为这里我们需要的是副作用
0 0
- 【Clojure】在loop-recur中实现多重循环
- 5.3在Debug中跟踪用loop指令实现的循环程序
- 在C语言中跳出多重循环
- 在Java中,如何跳出多重循环
- oracle中使用游标实现多重循环
- 汇编中loop循环
- 如何在Oracle中使用游标来实现多重循环?[原创]
- ORACLE存储过程如何在LOOP循环中处理异常
- discuz中在[loop]循环中 加入变量 显示数据递增 获取第几次循环
- 在JAVA中,如何跳出当前的多重嵌套循环?
- 在JAVA中如何跳出当前的多重嵌套循环?
- 在JAVA中如何跳出当前的多重嵌套循环?
- 在JAVA中如何跳出当前的多重嵌套循环
- 在JAVA中如何跳出当前的多重嵌套循环?
- 在JAVA中如何跳出当前的多重嵌套循环?
- 在Java中如何跳出当前的多重循环
- 在java中如何跳出当前的多重循环嵌套?
- 在JAVA中如何跳出当前的多重嵌套循环
- MultiByteToWideChar和WideCharToMultiByte用法详解
- 【弱的C艹之路。。未完待续】
- 大数乘法,大数加法,大数减法
- 第一天
- 用jetty跑maven项目(详细版,适合小白)
- 【Clojure】在loop-recur中实现多重循环
- hihocoder#1051 : 补提交卡....惊了..这题竟然被我发现测试数据的漏洞....
- 对于block的理解及用法的注意
- jquery validate对于多个同样名称的name进行验证
- 如何解决错误:A script behaviour has a different serialization layout when loading
- [leetcode] 373. Find K Pairs with Smallest Sums 解题报告
- Two Sum III – Data structure design
- 设置RecyclerView项目之间的间距
- Ubuntu 16.04中如何修改mysql的编码为utf-8