从数组元素创建列表,生成数字序列

时间:2015-12-16 15:01:44

标签: arrays algorithm ocaml

问题在于: 我有类似的数字(例如)3333 222 111.我需要编写一个程序来检查是否有可能使序列中的相同数字不是彼此的邻居。唯一的条件是第一个和最后一个元素是已知的。在这个例子中,让它为2和3.正确的顺序可以是2 32132131 3.

我的想法是将中间元素的数量放入数组[| 3; 2; 3 |],通过while循环创建列表(一个用于升序,另一个用于降序),添加第一个和最后一个元素然后检查是否顺序是正确的。 main方法中有一些选项 - descengind,ascending,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]

简直无法工作。我根本不知道如何解决这个任务。

2 个答案:

答案 0 :(得分:1)

如果您按照每个元素集的基数的降序对列表进行排序,那么您是否只能将倒金字塔中间的点缀在一起?

如果一个元素出现的数字大于其他所有元素(+ 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

答案 1 :(得分: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 guard下调用,事实上,如果你使用任何正确缩进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;