代码之家  ›  专栏  ›  技术社区  ›  Amir Rachum

Prolog-在矩阵中查找单词

  •  5
  • Amir Rachum  · 技术社区  · 14 年前

    给予 nxn 字母矩阵和单词列表,程序应该找到所有出现在矩阵中的单词及其位置。

    它们可以出现在上下、左右和对角线上(在所有8个方向上)。一个单词可以出现任意次数(包括零次),它们可以重叠(就像单词一样) bad adult )甚至是彼此的一个子集(比如 坏的 ad

    2 回复  |  直到 7 年前
        1
  •  2
  •   Bolo    14 年前

    编辑

    % word(X) iff X is a word
    word("foo").
    word("bar").
    word("baz").
    
    % prefix(?A, +B) iff A is a prefix of B
    prefix([], _).
    prefix([A|B], [A|C]) :- prefix(B, C).
    
    % sublist(?A, +B) iff A is a sublist of B
    sublist(A, B) :- prefix(A, B).
    sublist(A, [_|B]) :- sublist(A, B).
    
    % reversed(?A, +B) iff A is reversed B
    reversed(A, B) :- reversed(B, [], A).
    reversed([A|B], C, D) :- reversed(B, [A|C], D).
    reversed([], A, A).
    
    % rowsreversed(?A, +B) iff matrix A is matrix B with reversed rows
    rowsreversed([A|B], [C|D]) :- reversed(A, C), rowsreversed(B, D).
    rowsreversed([], []).
    
    % transposed(+A, ?B) iff matrix B is transposed matrix A
    transposed(A, B) :- transposed(A, [], B).
    transposed(M, X, X) :- empty(M), !.
    transposed(M, A, X) :- columns(M, Hs, Ts), transposed(Ts, [Hs|A], X).
    
    % empty(+A) iff A is empty list or a list of empty lists
    empty([[]|A]) :- empty(A).
    empty([]).
    
    % columns(+M, ?Hs, ?Ts) iff Hs is the first column
    %   of matrix M and Ts is the rest of matrix M
    columns([[Rh|Rt]|Rs], [Rh|Hs], [Rt|Ts]) :- columns(Rs, Hs, Ts).
    columns([[]], [], []).
    columns([], [], []).
    
    % inmatrix(+M, ?W) iff word W is in the matrix M
    inmatrix(M, W) :- inrows(M, W).
    inmatrix(M, W) :- incolumns(M, W).
    inmatrix(M, W) :- inleftdiagonals(M, W).
    inmatrix(M, W) :- inrightdiagonals(M, W).
    
    % inrows(+M, ?W) iff W or reversed W is in a row of M
    inrows([R|_], W) :- word(W), sublist(W, R).
    inrows([R|_], W) :- word(W), reversed(V, W), sublist(V, R).
    inrows([_|Rs], W) :- inrows(Rs, W).
    
    % incolumns(+M, ?W) iff W or reversed W is in a column of M
    incolumns(M, W) :- transposed(M, N), inrows(N, W).
    
    % inleftdiagonals(+M, ?W) iff W or reversed W is in a left diagonal of M
    inleftdiagonals(M, W) :- inupperleftdiagonals(M, W).
    inleftdiagonals(M, W) :- transposed(M, N), inupperleftdiagonals(N, W).
    
    % inupperleftdiagonals(+M, ?W) iff W or reversed W is in an upper left diagonal of M
    inupperleftdiagonals(M, W) :- upperdiags(M, N), inrows(N, W).
    
    % upperdiags(+M, ?X) iff X is a list of upper diagonals of matrix M
    upperdiags(M, X) :- upperdiags(M, [], Y), reversed(Z, Y), transposed(Z, X).
    upperdiags([R|Rs], A, X) :- columns(Rs, _, T), upperdiags(T, [R|A], X).
    upperdiags([], X, X).
    
    % inrightdiagonals(+M, ?W) iff W or reversed W is in a right diagonal of M
    inrightdiagonals(M, W) :- rowsreversed(N, M), inleftdiagonals(N, W).
    
        2
  •  2
  •   Community CDub    7 年前

    以下是水平和垂直直线和反向查找的部分解决方案:

    count_hits(Word, Matrix, Result):-
            atom_chars(Word, Chars),
            reverse(Chars, C2),
            transpose_matrix(Matrix, M2),
            findall(1, find_chars_in_matrix(Chars,Matrix), A),
            findall(1, find_chars_in_matrix(Chars,M2), B),
            findall(1, find_chars_in_matrix(C2,Matrix), C),
            findall(1, find_chars_in_matrix(C2,M2), D),
            length(A, X1),
            length(B, X2),
            length(C, X3),
            length(D, X4),
            Result is X1 + X2 + X3 + X4.
    
    transpose_matrix([],[]).
    transpose_matrix([[ULCorner|Header]|Body], [[ULCorner|NewHeader]|NewBody]) :- 
            collect_heads_and_tails(Body, NewHeader, Kernel),
            collect_heads_and_tails(NewBody, Header, X2),
            transpose_matrix(Kernel, X2).
    
    collect_heads_and_tails([], [], []).
    collect_heads_and_tails([[H|T]|TT], [H|X], [T|Y]):-collect_heads_and_tails(TT, X, Y).
    
    find_chars_in_matrix(Chars, [H|_]):-
            sublist(Chars, H).
    
    find_chars_in_matrix(Chars, [_|T]):-
            find_chars_in_matrix(Chars, T).
    
    sublist(L, [_|T]) :- sublist(L, T).
    sublist(A, B) :- prefix(A, B).
    
    prefix([H|T], [H|T2]) :- prefix(T, T2).
    prefix([], _).
    
    
    % test data
    matrix([[e,t,r,e],
            [r,r,t,r],
            [t,r,t,t],
            [e,e,t,e]]).
    go :- matrix(M), count_hits(etre, M, X), write(X).
    :-go.
    

    两个缺点:(a)回文词被发现两次,一个字母的词被发现四次——从数学上讲是合理的,但从常识的角度来看可能是不需要的(b) 对角线匹配根本找不到,因为您需要更复杂的递归和至少一个额外的计数参数。

    this