arrays - 如何在 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],
[8,_,_,9,_,5,_,2,3],
[2,_,9,3,_,8,7,6,_]].

我正在使用 ECLiPSe CLP 来实现求解器。到目前为止,我想出的最好的方法是编写这样的域:
domain(P):-
  dim(P,[9,9]),
  P[1..9,1..9] :: 1..9.

和拼图转换器(参数 P 是给定的拼图,Sudoku 是新定义的带有二维数组的网格)。但是我无法将给定初始谜题中的值链接到我的二维数组。
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 ( http://eclipseclp.org/doc/bips/kernel/termmanip/array_list-2.html ),但我一直收到类型错误。我以前是怎么做的:
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, ...), ...)

那我会很开心的。

更新

我再次尝试使用 array_list;它几乎适用于以下代码:
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

虽然我确定 jschimpf 给出的答案是正确的,但我也想出了我自己的实现:
convertVectorsToArray(Sudoku,[],_).
convertVectorsToArray(Sudoku,[Y|Rest],Count):-
  X is Sudoku[Count],
  array_list(X, Y),
  NewCount is Count + 1,
  convertVectorsToArray(Sudoku,Rest,NewCount).

感谢您补充解释为什么它之前不起作用!

最佳答案

最简单的解决方案是通过将拼图规范直接编写为二维数组来完全避免转换。 ECLiPSe“数组”只是一个带有仿函数的结构'[]'/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_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成为一个数组(你在列表中使用它)
  • 仅适用于需要算术表达式的上下文,例如is/2的右手边, 在算术约束等中
  • 关于arrays - 如何在 ECLiPSe (CLP) 中将向量转换为数组? (或序言),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35957101/

    相关文章:

    javascript - 如何在数组数组中找到元素的索引?

    php - 使用动态创建的复选框和数组维护复选框值

    javascript - 在javascript中动态创建具有累积和的对象数组

    Prolog 在限定时间内找到所有解决方案

    Prolog - 将数字合并为数字

    prolog - 3 行逻辑谜题 : optimisation for sequence constraints in lists/arrays

    prolog - 如何使用 ECLiPSe Prolog 中的模块自由断言/撤回事实?

    PHP Array Speed : Is 10, 000 个元素太多无法及时访问关联数组?

    prolog - 如何将整数创建为字符代码常量?

    list - 如何向 Prolog 指定列表的所有元素必须为 1 或 0?