Arrays 如何在ECLiPSe(CLP)中将向量转换为数组?(或序言)

Arrays 如何在ECLiPSe(CLP)中将向量转换为数组?(或序言),arrays,prolog,eclipse-clp,Arrays,Prolog,Eclipse Clp,我必须以包含9个向量(每个向量的长度为9)的向量的形式解决数独难题。由于向量在Prolog中是链表,我认为如果我先将谜题转换为2D数组格式,搜索速度会更快 拼图示例: puzzle(P) :- P = [[_,_,8,7,_,_,_,_,6], [4,_,_,_,_,9,_,_,_], [_,_,_,5,4,6,9,_,_], [_,_,_,_,_,3,_,5,_], [_,_,3,_,_,7,6,_,_], [_,_,_,_,_,_,_,8,9], [_,7,_,4,_,2,_,_,5]

我必须以包含9个向量(每个向量的长度为9)的向量的形式解决数独难题。由于向量在Prolog中是链表,我认为如果我先将谜题转换为2D数组格式,搜索速度会更快

拼图示例:

puzzle(P) :- P = 
[[_,_,8,7,_,_,_,_,6],
[4,_,_,_,_,9,_,_,_],
[_,_,_,5,4,6,9,_,_],

[_,_,_,_,_,3,_,5,_],
[_,_,3,_,_,7,6,_,_],
[_,_,_,_,_,_,_,8,9],

[_,7,_,4,_,2,_,_,5],
[8,_,_,9,_,5,_,2,3],
[2,_,9,3,_,8,7,6,_]].
我正在使用EclipseCLP实现一个解算器。到目前为止,我想到的最好的方法是编写一个如下的域:

domain(P):-
  dim(P,[9,9]),
  P[1..9,1..9] :: 1..9.
和一个用于拼图的转换器(参数p是给定的拼图,数独是新定义的二维数组网格)。但我在将给定初始谜题的值链接到2D数组时遇到了问题

convertVectorsToArray(Sudoku,P):-
  ( for(I,1,9),
      param(Sudoku,P)
    do
      ( for(J,1,9),
          param(Sudoku,P,I)
        do
          Sudoku[I,J] is P[I,J]
      )
  ).
在此之前,我尝试使用array_list(),但一直出现类型错误。我以前是怎么做的:

convertVectorsToArray(Sudoku,P):-
  ( for(I,1,9),
      param(Sudoku,P)
    do
      ( for(J,1,9),
          param(Sudoku,P,I)
        do
          A is Sudoku[I],
          array_list(A,P[I])
      )
  ).
当我的数独游戏最终以以下格式输出示例拼图p时:

Sudoku = []([](_Var1, _Var2, 8, 7, ..., 6), [](4, ...), ...)
那我就高兴了

更新

我用数组列表再试了一次;它几乎适用于以下代码:

convertVectorsToArray(Sudoku,P):-
  ( for(I,1,9),
      param(Sudoku,P)
    do
      X is Sudoku[I],
      Y is P[I],
      write(I),nl,
      write(X),nl,
      write(Y),nl,
      array_list(X, Y)
  ).
写操作用于查看向量/数组的外观。出于某种原因,它在第二次迭代时停止(而不是9次),并将示例谜题的其余部分作为向量向量输出。只有第一个向量被正确分配

更新2

虽然我确信JSF给出的答案是正确的,但我也找到了自己的实现:

convertVectorsToArray(Sudoku,[],_).
convertVectorsToArray(Sudoku,[Y|Rest],Count):-
  X is Sudoku[Count],
  array_list(X, Y),
  NewCount is Count + 1,
  convertVectorsToArray(Sudoku,Rest,NewCount).

谢谢你对为什么它以前不起作用的补充解释

最简单的解决方案是通过直接以二维数组的形式编写拼图规范来避免转换。ECLiPSe“array”只是一个带有functor
“[]”/N
的结构,因此您可以编写:

puzzle(P) :- P = [](
    [](_,_,8,7,_,_,_,_,6),
    [](4,_,_,_,_,9,_,_,_),
    [](_,_,_,5,4,6,9,_,_),

    [](_,_,_,_,_,3,_,5,_),
    [](_,_,3,_,_,7,6,_,_),
    [](_,_,_,_,_,_,_,8,9),

    [](_,7,_,4,_,2,_,_,5),
    [](8,_,_,9,_,5,_,2,3),
    [](2,_,9,3,_,8,7,6,_)).
然后,您可以直接使用此二维数组作为域变量的容器:

sudoku(P) :-
    puzzle(P),
    P[1..9,1..9] :: 1..9,
    ...
但是,如果要保留列表列表,并将其转换为数组格式,可以使用
array\u list/2
。但由于这仅适用于一维阵列,因此必须单独转换嵌套级别:

listoflists_to_matrix(Xss, Xzz) :-
    % list of lists to list of arrays
    ( foreach(Xs,Xss), foreach(Xz,Xzs) do
        array_list(Xz, Xs)
    ),
    % list of arrays to array of arrays
    array_list(Xzz, Xzs).
至于您自己的代码不起作用的原因:这是由于下标符号
p[I]
。这个

  • 需要
    P
    作为数组(您在列表中使用了它)
  • 仅适用于需要算术表达式的上下文,例如
    的右侧为/2
    、算术约束等