【问题标题】:Prolog recursing through list of listsProlog通过列表列表递归
【发布时间】:2016-09-07 17:36:56
【问题描述】:

我正在尝试一个序言问题,说明如下:


幻方是由不同数字(1 到 9 之间)组成的 3×3 矩阵,使得所有行和列的总和都相同(但不一定是对角线)。例如: 2 7 6 9 5 1 4 3 8 是一个魔方。 我们将 Prolog 中的正方形表示为 3 × 3 矩阵,即列表 [R1, R2, R3] 的列表,其中每个 R_i 是三个数字的列表。例如, 上述幻方的表示是 [[2,7,6],[9,5,1],[4,3,8]]

定义一个谓词 magic/1 来测试一个地面 3 × 3 矩阵(即 其中所有条目都是数字)是一个魔方。


我是通过以下方式做到这一点的,如果我在考试中也这样做,我很确定这是允许的,但对我来说这似乎是一种 hack:

magic([[A,B,C], [D,E,F], [G,H,I]]) :- 
                Y is A + B + C, 
                Y is D + E + F, 
                Y is G + H + I, 
                Y is A + D + G,
                Y is B + E + H,
                Y is C + F + I.

我想要的方法是递归遍历外部列表中的每个列表,然后总结。对于外部列表中的每个列表,它们的总和应该是相同的值(我认为 15 实际上是这个“神奇”矩阵的唯一可能的解决方案)。同样,我对列做同样的事情(取每个列表的第一个、第二个和第三个并分别加起来)。但是,我不完全确定如何做后者,因为我没有经常使用列表列表。如果有人能就如何一般地完成这类计算给出一个简洁的解决方案,我将不胜感激。

谢谢

【问题讨论】:

    标签: recursion prolog


    【解决方案1】:

    请注意,您的解决方案不会检查 A、..、I 值是否不同且在 1..9 范围内。这是 N > 2 的 NxN 平方的解决方案:

    magic(L) :-
        magic_range(L),
        magic_sum(S, L),
        magic_line(S, L),
        transpose(L, T),
        magic_line(S, T).
    
    % S value from https://oeis.org/A006003
    magic_sum(S, L) :-
        length(L, N),
        S is N * (N*N + 1) / 2.
    
    magic_range(L) :-
        flatten(L, F),
        sort(F, S),
        length(L, N),
        N2 is N * N,
        numlist(1, N2, S).
    
    magic_line(_, []).
    magic_line(S, [A | As]) :-
        sumlist(A, S),
        magic_line(S, As).
    
    % https://github.com/SWI-Prolog/swipl-devel/blob/9452af09962000ebb5157fe06169bbf51af5d5c9/library/clp/clpfd.pl#L6411
    transpose(Ls, Ts) :-
        must_be(list(list), Ls),
        lists_transpose(Ls, Ts).
    
    lists_transpose([], []).
    lists_transpose([L|Ls], Ts) :-
        foldl(transpose_, L, Ts, [L|Ls], _).
    
    transpose_(_, Fs, Lists0, Lists) :-
        maplist(list_first_rest, Lists0, Fs, Lists).
    
    list_first_rest([L|Ls], L, Ls).
    

    一些查询

    ?- magic([[1,1,1],[1,1,1],[1,1,1]]).
    false.
    
    ?- magic([[2,7,6],[9,5,1],[4,3,8]]).
    true ;
    false.
    
    ?- magic([[16,3,2,13], [5,10,11,8], [9,6,7,12], [4,15,14,1]]).
    true ;
    false.
    

    transpose 谓词是最复杂的部分。请参阅here 了解一些替代方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多