我们在F#中实现这个算法.
以下是Topor(1982)关于算法使用的符号的更多信息:
形式上,a
't list
是null
(表示nil
)或者是hd
(a是't
)和atl
(是a't list
)...如果x
是列表,我们测试是否是null
通过写null x
...我们创建一个新列表,添加元素a
在现有列表的前面x
,通过写a:x
......我们表示包含该元素的单位名单a
由list(a)
...list(x) = x:nil
.
我们想知道的是如何在F#表达的nil
,null
和list(nil)
值.例如,我们应该使用Option类型,空列表还是其他什么?
let rec kpermute k (xs: 't list) =
let rec mapPerm k xs ys =
match ys with
| [] -> []
| head::tail ->
let kpermuteNext = kpermute (k-1) (removeFirst head xs)
let mapPermNext = mapPerm k xs tail
mapcons head kpermuteNext mapPermNext
match k with
| 0 -> [[]]
| _ when xs.Length < k -> []
| _ -> mapPerm k xs xs
Run Code Online (Sandbox Code Playgroud)
使用列表时,list(nil)
我们使用[[]]
和nil
使用[]
.虽然这很好,但可能有一种更具表现力的方式.还有,当我们使用时间List.empty<'t list>
和List.empty<'t>
时类型推断需要更多的信息.
本文为您提供了所有答案:nil
是[]
; null x
是否x
是空列表的测试; list(nil)
是[[]]
.
算法B到F#的简单翻译如下:
let rec minus a = function
| [] -> failwith "empty list"
| xh :: xt -> if xh = a then xt else xh :: minus a xt
let rec permute2 k x =
if k = 0 then [[]]
elif List.length x < k then []
else mapperm k x x
and mapperm k x = function
| [] -> []
| yh :: yt -> mapcons yh (permute2 (minus yh x)) (mapperm x yt)
and mapcons a ps qs =
match ps with
| [] -> qs
| ph :: pt -> a :: ph :: mapcons a pt qs
Run Code Online (Sandbox Code Playgroud)