作者Schelfaniel (Schelfaniel)
看板PLT
标题[闲聊] 排列
时间Sun Apr 4 10:06:29 2010
※ 引述《plko (我饿了)》之铭言:
> ※ 引述《yoco (道德勇气)》之铭言:
> > 喔... 「假设」我有一个函数,只是假设,
> > 他可以吃一个阵列,然後帮我把这个阵列所有的排序印出来,比方说:
> 感谢<(_ _)>
> 本来想不通的点,这样就很清楚了...
上面的 Clojure 版是 "组合",如果是要排列的,大致说明如下
1. 使用阵列 Index 来排,其次使用 map 去对应,实际的阵列的内容
如一个阵列有 3 个值好了:
user=> (lex-permutations (range 3))
([0 1 2] [0 2 1] [1 0 2] [1 2 0] [2 0 1] [2 1 0])
它排出来的结果,上面的 0 1 2 其实是阵列的索引值,
也就是接下来再用这个索引值去对应实际的阵列内容。
( 这 lex-permutations 是 lazy 阵列 )
2. 对应的方法如下:
(defn permutations
"All the permutations of items, lexicographic by index"
[items]
(let [v (vec items)]
(map #(map v %) (lex-permutations (range (count v))))))
^^^^^^^^^^^^^^^^ 产生索引值阵列
这边有两层的 map 让它对应实际的排列值。同上 map 亦为 lazy。
3. 而 lex-permutations 的运作原理是,
每次根据 "目前的索引阵列值" 产生 "下一个索引阵列值",
如果产生不出来表示是最後一个了....
其公式如下 : ( 程式就不贴了 )
如 [0 1 2] 的下一个是 [0 2 1]
y <- 从右往左找出第一个顺向排列的 (这边 1 < 2 顺向),
无 y 时为最後一个
z <- 从右往左找出第一个大於 (v y) 之值的
交换 (v y) 及 (v z) 产生 [0 2 1]
接下来是一个回圈并令 y = y+1,且 z 从阵列最後开始,
loop 条件 y<z,每次,交换(v y) (v z),然後 y=y+1, z=z-1
这边一开始就 y 和 z 的值相同,所以不同交换了。
而 [0 2 1] 下一个是 [2 0 1] 亦同
y
z
交换产生 [1 2 0]
y
z
回圈交换 [1 0 2]
z y ( 因为 y > z 跳出 loop )
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 114.32.74.159