【问题标题】:Prolog algorithm works for 4x4 but not for higher dimensionsProlog 算法适用于 4x4,但不适用于更高维度
【发布时间】:2022-01-17 19:29:16
【问题描述】:

这是Restrict search in 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.

【问题讨论】:

    标签: algorithm search prolog perfect-square


    【解决方案1】:

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

    我的程序返回 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 online跟踪(单击一行左侧设置断点并在代码运行时单步执行)来定位它。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-15
      • 2015-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-20
      • 2011-02-10
      相关资源
      最近更新 更多