Prolog の統合機能と属性付き変数を使用してテンプレートを照合するソリューションを次に示します。
:-dynamic pattern_i/3.
test:-
retractall(pattern_i(_,_,_)),
add_pattern(abab),
add_pattern(bcbc),
add_pattern(babcbc),
add_pattern(dababd),
show_similarities.
show_similarities:-
call(pattern_i(Word, Pattern, Maps)),
match_pattern(Word, Pattern, Maps),
fail.
show_similarities.
match_pattern(Word, Pattern, Maps):-
all_dif(Maps), % all variables should be unique
call(pattern_i(MWord, MPattern, MMaps)),
Word\=MWord,
all_dif(MMaps),
append([_, Pattern, _], MPattern), % Matches patterns
writeln(words(Word, MWord)),
write('mapping: '),
match_pattern1(Maps, MMaps). % Prints mappings
match_pattern1([], _):-
nl,nl.
match_pattern1([Char-Char|Maps], MMaps):-
select(MChar-Char, MMaps, NMMaps),
write(Char), write('='), write(MChar), write(' '),
!,
match_pattern1(Maps, NMMaps).
add_pattern(Word):-
word_to_pattern(Word, Pattern, Maps),
assertz(pattern_i(Word, Pattern, Maps)).
word_to_pattern(Word, Pattern, Maps):-
atom_chars(Word, Chars),
chars_to_pattern(Chars, [], Pattern, Maps).
chars_to_pattern([], Maps, [], RMaps):-
reverse(Maps, RMaps).
chars_to_pattern([Char|Tail], Maps, [PChar|Pattern], NMaps):-
member(Char-PChar, Maps),
!,
chars_to_pattern(Tail, Maps, Pattern, NMaps).
chars_to_pattern([Char|Tail], Maps, [PChar|Pattern], NMaps):-
chars_to_pattern(Tail, [Char-PChar|Maps], Pattern, NMaps).
all_dif([]).
all_dif([_-Var|Maps]):-
all_dif(Var, Maps),
all_dif(Maps).
all_dif(_, []).
all_dif(Var, [_-MVar|Maps]):-
dif(Var, MVar),
all_dif(Var, Maps).
アルゴリズムの考え方は次のとおりです。
- 単語ごとに、バインドされていない変数のリストを生成します。ここでは、単語内の同じ文字に対して同じ変数を使用します。例: abcbc という単語の場合、リストは [X,Y,Z,Y,Z] のようになります。これは、この単語のテンプレートを定義します
- テンプレートのリストを取得したら、それぞれを取得し、そのテンプレートを他のすべての単語のサブテンプレートと統合しようとします。たとえば、abcbc と zxzx という単語がある場合、テンプレートは [X,Y,Z,Y,Z] と [H,G,H,G] になります。次に、2 番目の単語 (H=Y、G=Z) のテンプレートと統合する最初のテンプレートにサブテンプレートがあります。
- テンプレートの一致ごとに、その一致を生成するために必要な置換 (変数の名前変更) を示します。したがって、この例では、置換は z=b、x=c になります。
テストの出力 (単語 abab、bcbc、babcbc、dababd):
?- test.
words(abab,bcbc)
mapping: a=b b=c
words(abab,babcbc)
mapping: a=b b=c
words(abab,dababd)
mapping: a=a b=b
words(bcbc,abab)
mapping: b=a c=b
words(bcbc,babcbc)
mapping: b=b c=c
words(bcbc,dababd)
mapping: b=a c=b