我在这里有一些F#代码用于递归函数,它将列表向左旋转n
个位置。我是F#的新手,我正在寻找一种修改此代码的方法,不仅可以通过n
位置输出一次旋转,还可以输出所有可能的旋转。
例如,假设我有清单:
let list1 = [1; 2; 3; 4]
我想在此列表上调用rotate,以便输出为:
[ [1; 2; 3; 4]; [2; 3; 4; 1]; [3; 4; 1; 2]; [4; 1; 2; 3] ]
我所做的左移n的代码是:
let rec rotate xs k =
match xs, k with
|[], _ -> []
|xs, 0 -> xs
|x::xs, k when k > 0 -> rotate(xs @ [x])(k-1)
|xs, k -> rotate xs (List.length xs + k)
我不知道如何编辑它来执行上面列出的步骤。任何帮助或资源将不胜感激。我应该补充一点,我真的希望函数是递归的。感谢。
答案 0 :(得分:7)
如果我正确理解了这个问题,你也可以使用内置的List.permute
函数编写函数:
let rotate xs =
let length = xs |> List.length
let perm n = xs |> List.permute (fun index -> (index + n) % length)
[1 .. length] |> List.rev |> List.map perm
示例输出(稍微格式化以提高可读性):
> [1 .. 4] |> rotate;;
val it : int list list =
[[1; 2; 3; 4];
[2; 3; 4; 1];
[3; 4; 1; 2];
[4; 1; 2; 3]]
答案 1 :(得分:2)
我会从原始列表中创建无限循环序列开始。然后使用List.init
获取所有轮换。
let rotations list =
let rec cyclic sequence = seq {
yield! sequence
yield! cyclic sequence }
let cyclic = cyclic list
let length = List.length list
List.init length (fun i -> cyclic |> Seq.skip i |> Seq.take length |> List.ofSeq)
重要的是,序列是懒惰的,因此可以无限。
答案 2 :(得分:1)
使用您已编写的rotate
函数:
let rotations xs = List.init (List.length xs) (rotate xs)
顺便说一下,您可以将rotate
功能缩短为:
let rec rotate xs k =
match xs, k with
|[], _ -> []
|xs, 0 -> xs
|x::xs, k -> rotate (xs @ [x]) (k-1)
模式自上而下匹配,因此保护when k > 0
不是必需的。原始解决方案的最后一行永远不会匹配,所以我删除了它。
答案 3 :(得分:0)
由于我想使用递归和匹配来完成这个特定的问题,我设法弄清楚了,这就是我提出的:
let rotate xs =
let n = List.length xs
let rec rotation xs n =
match xs, n with
|[], _ -> []
|xs, 0 -> xs
|x::xs, n -> rotation (xs @ [x]) (n-1)
let rec rotateList xs n = //we are compiling a list of different rotations
match xs, n with
|xs, 0 -> []
|xs, n -> (rotation xs ((List.length xs)-n))::rotateList xs (n-1)
rotateList xs n
我还特别想要一个输入参数,即列表