从数组元素创建列表,生成数字序列
Creating list from array elements, making sequence of numbers
问题是:
我有像(例如)3333 222 111 这样的数字。我需要编写一个程序来检查是否有可能使相同数字彼此不相邻的序列。唯一的条件是第一个和最后一个元素是已知的。在这个例子中,让我们把它设为 2 和 3。正确的顺序应该是 2 32132131 3。
我的想法是将中间元素的计数放入数组 [|3;2;3|],通过 while 循环创建列表(一种方法用于升序,另一种方法用于降序),添加第一个和最后一个元素,然后检查顺序是否正确。 main 方法中会有几个选项 - descengind、ascended、reverted 等
这是一些代码
let makeUp b e arr k=
let l = ref [] in
let i = ref 0 in
while (List.length !l<k) do
if arr.(!i) > 0 then l := !i+1 :: !l ; arr.(!i) <- arr.(!i) -1;
i := (!i + 1) mod Array.length arr;
done;
[b]@(List.rev !l)@[e];;
let rec isCorrect lista =
match lista with
[] -> true
|h::[] -> true
|h::t -> if (h = List.hd t)then false
else isCorrect t;;
问题是我正在修改数组的内容,所以我只能列出一次。像这样:
let find b e array length =
if isCorrect(makeUp b e array length) then makeUp b e array length
else if isCorrect.....
else [0]
根本行不通。我完全不知道如何解决这个任务。
好吧,为了特别解决您的问题,您可以使用 Array.copy
,这将创建数组的全新副本,如下所示:
let makeUp b e arr k =
let arr = Array.copy arr in
...
此外,尽量不要那么命令式,并以更实用的风格编写代码。不要使用 while 循环并使用递归(或共同递归)来构建东西。
例如,这是对您的 while 循环代码的机械转换(我没有尝试理解您的算法),使其更具功能性:
let make b e arr k =
let arr = Array.copy arr in
let rec loop xs i len =
let j = (i + 1) mod Array.length arr in
if i = k then List.rev (e::xs)
else if arr.(i) > 0
then
let () = arr.(i) <- arr.(i) - 1 in
loop (i + 1 :: xs) j (len + 1)
else loop xs j len in
loop [b] 1 1
根据您的代码格式,它略有不同
我假设,你在表达中变薄了:
if arr.(!i) > 0 then l := !i+1 :: !l ; arr.(!i) <- arr.(!i) -1;
这两个赋值都将在 if 保护下调用,事实上,如果您使用任何正确缩进 OCaml 的工具,您会发现您错了:
if arr.(!i) > 0 then
l := !i+1 :: !l;
arr.(!i) <- arr.(!i) - 1;
i := (!i + 1) mod Array.length arr;
只有对变量l
的赋值会在守卫下执行。所以实际上你想要的是:
if arr.(!i) > 0 then begin
l := !i+1 :: !l;
arr.(!i) <- arr.(!i) - 1;
end;
i := (!i + 1) mod Array.length arr;
如果你把列表按照每个元素集的基数降序排列,你不能一直穿插倒金字塔吗?
如果一个元素出现的数量 (+1) 大于所有其他元素的总和,您是否无法创建这样的序列?
3333 222 111
3 3 3 3
2 2 2
1 1 1
33333333 222 111
3 3 3 3 3 3 3 3
2 2 2 1 1 1 x
问题是: 我有像(例如)3333 222 111 这样的数字。我需要编写一个程序来检查是否有可能使相同数字彼此不相邻的序列。唯一的条件是第一个和最后一个元素是已知的。在这个例子中,让我们把它设为 2 和 3。正确的顺序应该是 2 32132131 3。
我的想法是将中间元素的计数放入数组 [|3;2;3|],通过 while 循环创建列表(一种方法用于升序,另一种方法用于降序),添加第一个和最后一个元素,然后检查顺序是否正确。 main 方法中会有几个选项 - descengind、ascended、reverted 等
这是一些代码
let makeUp b e arr k=
let l = ref [] in
let i = ref 0 in
while (List.length !l<k) do
if arr.(!i) > 0 then l := !i+1 :: !l ; arr.(!i) <- arr.(!i) -1;
i := (!i + 1) mod Array.length arr;
done;
[b]@(List.rev !l)@[e];;
let rec isCorrect lista =
match lista with
[] -> true
|h::[] -> true
|h::t -> if (h = List.hd t)then false
else isCorrect t;;
问题是我正在修改数组的内容,所以我只能列出一次。像这样:
let find b e array length =
if isCorrect(makeUp b e array length) then makeUp b e array length
else if isCorrect.....
else [0]
根本行不通。我完全不知道如何解决这个任务。
好吧,为了特别解决您的问题,您可以使用 Array.copy
,这将创建数组的全新副本,如下所示:
let makeUp b e arr k =
let arr = Array.copy arr in
...
此外,尽量不要那么命令式,并以更实用的风格编写代码。不要使用 while 循环并使用递归(或共同递归)来构建东西。
例如,这是对您的 while 循环代码的机械转换(我没有尝试理解您的算法),使其更具功能性:
let make b e arr k =
let arr = Array.copy arr in
let rec loop xs i len =
let j = (i + 1) mod Array.length arr in
if i = k then List.rev (e::xs)
else if arr.(i) > 0
then
let () = arr.(i) <- arr.(i) - 1 in
loop (i + 1 :: xs) j (len + 1)
else loop xs j len in
loop [b] 1 1
根据您的代码格式,它略有不同 我假设,你在表达中变薄了:
if arr.(!i) > 0 then l := !i+1 :: !l ; arr.(!i) <- arr.(!i) -1;
这两个赋值都将在 if 保护下调用,事实上,如果您使用任何正确缩进 OCaml 的工具,您会发现您错了:
if arr.(!i) > 0 then
l := !i+1 :: !l;
arr.(!i) <- arr.(!i) - 1;
i := (!i + 1) mod Array.length arr;
只有对变量l
的赋值会在守卫下执行。所以实际上你想要的是:
if arr.(!i) > 0 then begin
l := !i+1 :: !l;
arr.(!i) <- arr.(!i) - 1;
end;
i := (!i + 1) mod Array.length arr;
如果你把列表按照每个元素集的基数降序排列,你不能一直穿插倒金字塔吗?
如果一个元素出现的数量 (+1) 大于所有其他元素的总和,您是否无法创建这样的序列?
3333 222 111
3 3 3 3
2 2 2
1 1 1
33333333 222 111
3 3 3 3 3 3 3 3
2 2 2 1 1 1 x