0

这是以下问题的后续问题:限制 Prolog 中的搜索 - Magic Sqare

感谢Isabelle Newbie迄今为止的帮助。

在 Isabelle Newbie 的帮助下,我的代码可以正常工作,但遗憾的是仅适用于 4x4 Squares。

我对 Prolog 很陌生,所以也许我错过了一些明显的东西。

下面的代码基本上很快就生成了一个 4x4 的幻方。我以某种方式实现了所有规则,它们也应该适用于更高尺寸的正方形,如 8x8 或 12x12,但由于某种原因它不起作用。

:- use_module(library(clpfd)).

diag2_sum(0, _, _, _, _).
diag2_sum(I0, N, C1, Row1, Row3) :-
    I0 > 0,
    nth1(I0,Row1,A),
    V1 is N - 2,
    (I0 =:= V1 -> I2 = N ; I2 is mod(I0 + 2,N)),
    nth1(I2,Row3,B),
    C1 #= A + B,
    I1 is I0 - 1,
    diag2_sum(I1, N, C1, Row1, Row3).

diag_sum([_,_], _, _).
diag_sum([Row1|Tail], C1, N) :-
    nth1(2,Tail,Row3),
    diag2_sum(N, N, C1, Row1,Row3),
    diag_sum(Tail, C1, N).

square_sum_x(_, _, _, 0, _).
square_sum_x(Row1, Row2, C2, I0, N) :-
    V1 is N - 1,
    (I0 =:= V1 -> I2 = N ; I2 is mod(I0 + 1,N)),
    nth1(I0,Row1,Elem1),
    nth1(I2,Row1,Elem2),
    nth1(I0,Row2,Elem3),
    nth1(I2,Row2,Elem4),
    C2 #= Elem1 + Elem2 + Elem3 + Elem4,
    I1 is I0 - 1,
    square_sum_x(Row1, Row2, C2, I1, N).


square_sum_y(_, _, 0, _).
square_sum_y(Matrix, C2, I0, N) :-
    V1 is N - 1,
    (I0 =:= V1 -> I2 = N ; I2 is mod(I0 + 1,N)),
    nth1(I0,Matrix,Row1),
    nth1(I2,Matrix,Row2),
    
    square_sum_x(Row1,Row2, C2, N, N),
    I1 is I0 - 1,
    square_sum_y(Matrix, C2, I1, N).

magic_square_(N, Matrix) :-
    Nmax is N * N,
    C1 is Nmax + 1,
    C2 is C1 * 2,
    write(C1),nl,write(C2),nl,
    length(Matrix, N),
    maplist(same_length(Matrix), Matrix),
    append(Matrix, Vs),
    Vs ins 1..Nmax, all_different(Vs),
    diag_sum(Matrix, C1, N),
    square_sum_y(Matrix, C2, N, N).

magic_square(N, Matrix) :-
    magic_square_(N, Matrix),
    maplist(label, Matrix).

4x4 魔方(有效):

?- magic_square(4, Matrix).  
17
34
Matrix = [[1, 8, 10, 15], [12, 13, 3, 6], [7, 2, 16, 9], [14, 11, 5, 4]]

8x8 幻方(不起作用):

?- magic_square(8, Matrix). 
65
130
false.
4

1 回答 1

0

我以某种方式实现了所有规则,它们也应该适用于更高维度的正方形

我的程序返回 true。所以我假设我的规则基础是正确的。

    diag_sum(Matrix, C1, N),
    square_sum_y(Matrix, C2, N, N).

我注释掉了最后两行,并验证它确实生成了一个 8x8 矩阵和 12x12 递增值矩阵。将这些行中的任何一条添加回适用于 4x4 矩阵,但不适用于 8x8 或 12x12,这表示它们都不适用于更高维度的正方形。

生成一个 8x8 的非幻方并在其上测试 diag_sum(),从右上角到左下角的/对角线检查选择这两个值,即 8 和 18:

diag_sum([[ 1,  2,  3,  4,  5,  6,  7, *8],
          [ 9, 10, 11, 12, 13, 14, 15, 16],
          [17,*18, 19, 20, 21, 22, 23, 24],
          [25, 26, 27, 28, 29, 30, 31, 32],
          [33, 34, 35, 36, 37, 38, 39, 40],
          [41, 42, 43, 44, 45, 46, 47, 48],
          [49, 50, 51, 52, 53, 54, 55, 56],
          [57, 58, 59, 60, 61, 62, 63, 64]], 65, 8).

我认为应该选择这两个,八个和二十二个:

          [ 1,  2,  3,  4,  5,  6,  7, *8],
          [9, 10,  11, 12, 13, 14, 15, 16],
          [17, 18, 19, 20, 21,*22, 23, 24],

因为这一行:

(I0 =:= V1 -> I2 = N ; I2 is mod(I0 + 2,N)),

mod以一种仅在哪里有效4-2 =:= (4+2) mod 48-2 =\= (8+2) mod 8在这里失败的方式向右滚动。

我使用SWISH 在线跟踪(单击一行左侧设置断点并在代码运行时单步执行)来定位它。

注意。你没有问任何问题,你只是说“由于某种原因它不起作用”。这是它不起作用的第一个原因,看起来mod在 square_sum_x 中使用的相同设计可能会以相同的方式失败。该怎么做是一个不同的问题。您可能会在https://www.metalevel.at/sudoku/和视频解释中找到一些想法,了解如何更直接地表示数独网格中的较小方块。

也许构建和测试一种方法来提取对角线并在数字矩阵上测试它以查看它是否为 8x8 和 12x12 提供了正确的对角线位置,然后将这些结果分成间隔对,并对其进行测试,然后建立从那里?

于 2022-01-18T18:49:41.543 回答