Prolog:写一个像 Watson in Jeopardy 这样的程序
Prolog: writing a program like Watson in Jeopardy
我正在尝试制作一个程序,它可以找到您可以用给定的一组字母组成的最长单词。 (有点像 Watson in Jeopardy)
到目前为止,我已经做到了,如果您指定单词的长度,它会为您提供所有可以用您给它的字母组成的那个长度的单词。
该程序包含考虑到所有英语单词的事实 word/1
,如下所示:
word(ant).
word(computer).
% ... (and many more)
首先,我创建了一个名为 word_letters/2
的谓词,它将单词转换为字母列表,就像 atom_chars/2
谓词一样。
然后,我写了一个 cover/2
谓词来查看一个列表是否包含前一个列表的所有字母:
cover([],[]).
cover([],_).
cover([Head1|Tail1],List2) :-
member(Head1,List2),
select(Head1,List2,Newlist),
cover(Tail1,Newlist).
然后我写了一个 solution/3
谓词,将一定长度的所有单词变成一个字母列表,并检查该列表是否被你先给它的字母覆盖:
solution(Letters,Word,Length) :-
word(Word),
word_letters(Word,Letters2),
length(Letters2,Length),
word_letters(Word,Letters2),
cover(Letters2,Letters).
我现在要做的是让您不必指定单词的长度。它应该只给出最长的单词,并告诉你它有多长。
它应该像这样工作:
?- topsolution([g,i,g,c,n,o,a,s,t], Word, Score).
Word = agnostic,
Score = 8
True
它看起来并不难,但我似乎无法让它发挥作用。
如果有人可以提供帮助或为我指明正确的方向,那就太好了!
您面临的问题可以分解为两个:
确定word/1
词典中所有单词的最大长度。
这是一次性的工作,每当 word/1
的定义发生变化时都需要这样做。
枚举所有可接受的分数——从最大的分数开始,而不是最小的分数。
使用 length/2
和 append/3
你可以写:
?- length(Ref,7), append(_,Part,Ref).
Ref = [_A,_B,_C,_D,_E,_F,_G], Part = [_A,_B,_C,_D,_E,_F,_G]
; Ref = [_A,_B,_C,_D,_E,_F,_G], Part = [_B,_C,_D,_E,_F,_G]
; Ref = [_A,_B,_C,_D,_E,_F,_G], Part = [_C,_D,_E,_F,_G]
; Ref = [_A,_B,_C,_D,_E,_F,_G], Part = [_D,_E,_F,_G]
; Ref = [_A,_B,_C,_D,_E,_F,_G], Part = [_E,_F,_G]
; Ref = [_A,_B,_C,_D,_E,_F,_G], Part = [_F,_G]
; Ref = [_A,_B,_C,_D,_E,_F,_G], Part = [_G]
; Ref = [_A,_B,_C,_D,_E,_F,_G], Part = []
; false.
我正在尝试制作一个程序,它可以找到您可以用给定的一组字母组成的最长单词。 (有点像 Watson in Jeopardy)
到目前为止,我已经做到了,如果您指定单词的长度,它会为您提供所有可以用您给它的字母组成的那个长度的单词。
该程序包含考虑到所有英语单词的事实 word/1
,如下所示:
word(ant).
word(computer).
% ... (and many more)
首先,我创建了一个名为 word_letters/2
的谓词,它将单词转换为字母列表,就像 atom_chars/2
谓词一样。
然后,我写了一个 cover/2
谓词来查看一个列表是否包含前一个列表的所有字母:
cover([],[]).
cover([],_).
cover([Head1|Tail1],List2) :-
member(Head1,List2),
select(Head1,List2,Newlist),
cover(Tail1,Newlist).
然后我写了一个 solution/3
谓词,将一定长度的所有单词变成一个字母列表,并检查该列表是否被你先给它的字母覆盖:
solution(Letters,Word,Length) :-
word(Word),
word_letters(Word,Letters2),
length(Letters2,Length),
word_letters(Word,Letters2),
cover(Letters2,Letters).
我现在要做的是让您不必指定单词的长度。它应该只给出最长的单词,并告诉你它有多长。 它应该像这样工作:
?- topsolution([g,i,g,c,n,o,a,s,t], Word, Score).
Word = agnostic,
Score = 8
True
它看起来并不难,但我似乎无法让它发挥作用。 如果有人可以提供帮助或为我指明正确的方向,那就太好了!
您面临的问题可以分解为两个:
确定
word/1
词典中所有单词的最大长度。这是一次性的工作,每当
word/1
的定义发生变化时都需要这样做。枚举所有可接受的分数——从最大的分数开始,而不是最小的分数。
使用
length/2
和append/3
你可以写:?- length(Ref,7), append(_,Part,Ref). Ref = [_A,_B,_C,_D,_E,_F,_G], Part = [_A,_B,_C,_D,_E,_F,_G] ; Ref = [_A,_B,_C,_D,_E,_F,_G], Part = [_B,_C,_D,_E,_F,_G] ; Ref = [_A,_B,_C,_D,_E,_F,_G], Part = [_C,_D,_E,_F,_G] ; Ref = [_A,_B,_C,_D,_E,_F,_G], Part = [_D,_E,_F,_G] ; Ref = [_A,_B,_C,_D,_E,_F,_G], Part = [_E,_F,_G] ; Ref = [_A,_B,_C,_D,_E,_F,_G], Part = [_F,_G] ; Ref = [_A,_B,_C,_D,_E,_F,_G], Part = [_G] ; Ref = [_A,_B,_C,_D,_E,_F,_G], Part = [] ; false.