Bri*_*ian 4 combinations list clojure
作为clojure的新手,我仍在努力完成其功能.如果我有2个列表,说"1234"和"abcd"我需要制作长度为4的所有可能的有序列表.我想要的长度为4的输出是:
("1234" "123d" "12c4" "12cd" "1b34" "1b3d" "1bc4" "1bcd"
"a234" "a23d" "a2c4" "a2cd" "ab34" "ab3d" "abc4" "abcd")
Run Code Online (Sandbox Code Playgroud)
其中2 ^ n的数量取决于输入.
我编写了以下函数来通过随机遍历生成单个字符串/列表.参数[par]就像["1234""abcd"]
(defn make-string [par] (let [c1 (first par) c2 (second par)] ;version 3 0.63 msec
(apply str (for [loc (partition 2 (interleave c1 c2))
:let [ch (if (< (rand) 0.5) (first loc) (second loc))]]
ch))))
Run Code Online (Sandbox Code Playgroud)
输出将是上面16个有序列表中的1个.两个输入列表中的每一个将始终具有相等的长度,例如2,3,4,5,最多说2 ^ 38或在可用的ram内.在上面的函数中,我试图修改它以生成所有有序列表但失败了.希望有人可以帮助我.谢谢.
Mikera是正确的,你需要使用递归,但你可以做到这一点,同时更简洁和更一般 - 为什么使用两个字符串,当你可以使用N序列?
(defn choices [colls]
(if (every? seq colls)
(for [item (map first colls)
sub-choice (choices (map rest colls))]
(cons item sub-choice))
'(())))
(defn choose-strings [& strings]
(for [chars (choices strings)]
(apply str chars)))
user> (choose-strings "123" "abc")
("123" "12c" "1b3" "1bc" "a23" "a2c" "ab3" "abc")
Run Code Online (Sandbox Code Playgroud)
这种递归嵌套for是一种非常有用的模式,用于通过选择的"树"创建一系列路径.无论是实际的树,还是反复重复的相同选择,或者(如此处)一组不依赖于先前选择的N个选项,这是一个可用的便利工具.
您还可以充分利用cartesian-product从clojure.math.combinatorics包,尽管这需要你的一些数据预处理和后转化:
(ns your-namespace (:require clojure.math.combinatorics))
(defn str-combinations [s1 s2]
(->>
(map vector s1 s2) ; regroup into pairs of characters, indexwise
(apply clojure.math.combinatorics/cartesian-product) ; generate combinations
(map (partial apply str)))) ; glue seqs-of-chars back into strings
> (str-combinations "abc" "123")
("abc" "ab3" "a2c" "a23" "1bc" "1b3" "12c" "123")
>
Run Code Online (Sandbox Code Playgroud)