带序言的填字游戏
crossword puzzle with prolog
目前我正在做序言tutorial。
有一个用 5 个单词解决填字游戏的练习。
我的问题是 Prolog
很早就停止了对我的解决方案的统一。
看起来是这样的:
并且给出了一个小的知识库:
word(astante, a,s,t,a,n,t,e).
word(astoria, a,s,t,o,r,i,a).
word(baratto, b,a,r,a,t,t,o).
word(cobalto, c,o,b,a,l,t,o).
word(pistola, p,i,s,t,o,l,a).
word(statale, s,t,a,t,a,l,e).
为了解决这个任务,我有一个谓词 crossword/6
。
所以我认为谓词 crossword
必须包含 6 个由变量组成的词,并且在两个词交叉的每个字段中我都设置了相同的变量。
crossword(word(H1, A1, B1, C1, D1, E1, F1, G1),
word(H2, A2, B2, C2, D2, E2, F2, G2),
word(H3, A3, B3, C3, D3, E3, F3, G3),
word(V1, _1, B1, _2, B2, _3, B3, _4),
word(V2, _5, D1, _6, D2, _7, D3, _8),
word(V3, _9, F1, _10, F2, _11, F3 _12)).
在 SWI-Prolog 中,我输入了以下请求:
?- crossword(H1, H2, H3, V1, V2, V3).
所以我问了一个填字游戏的答案。
我得到的结果是这样的:
H1 = word(_720, _722, _724, _726, _728, _730, _732, _734),
H2 = word(_738, _740, _742, _744, _746, _748, _750, _752),
H3 = word(_756, _758, _760, _762, _764, _766, _768, _770),
V1 = word(_774, _776, _724, _780, _742, _784, _760, _788),
V2 = word(_792, _794, _728, _798, _746, _802, _764, _806),
V3 = word(_810, _812, _732, _816, _750, _820, _768).
问题:为什么Prolog
这么早就停止统一了?为什么 return 没有任何解决方案?
你的代码声明了一个简单的事实:有一个crossword/6
谓词,它的参数是word/8
个谓词,并且word/8
个谓词的一些参数是相同的。特别是,由于 crossword/6
被声明为简单事实,因此 crossword/6
声明中的 word/8
谓词与知识库之间没有任何关系(就像 "astoria" 的事实一样不限制 "astante").
的事实
相反,只有文字本身才是简单的事实:
word(astante, a,s,t,a,n,t,e).
word(astoria, a,s,t,o,r,i,a).
word(baratto, b,a,r,a,t,t,o).
word(cobalto, c,o,b,a,l,t,o).
word(pistola, p,i,s,t,o,l,a).
word(statale, s,t,a,t,a,l,e).
因为这些都是没有条件的简单事实,我们总能证明有一个word/8
谓词,其第一个参数是astante/0
,第二个参数是a/0
,第三个参数是s/0
,依此类推。
你想说的是,如果这六个词的其他条件成立,那么这六个词就形成了一个有效的解决方案:
crossword( H1, H2, H3, V1, V2, V3 ) :-
<conditions for a successful crossword solution>.
接下来,定义 crossword/6
的条件,这样一个有效的解决方案是变量与 word/8
谓词的第一个参数统一,如果这些参数的第三个、第五个和第七个参数word/8
争论以正确的方式相互统一。
对于一个(不完整的)例子,如果 H1 的第二个字母是 V1 的第二个字母,H1 的第六个字母是 V3 的第二个字母,我可以说我有一个有效的填字游戏解决方案:
crossword( H1, H2, H3, V1, V2, V3 ) :-
word( H1, _, TL, _, _, _, TR, _ ),
word( V1, _, TL, _, _, _, _, _ ),
word( V3, _, TR, _, _, _, _, _ ).
这里我使用下划线 _
来避免给名称无关紧要的变量命名。我还使用 TL
和 TR
来表示 "top left" 和 "top right" 以使我自己的推理更容易。 Prolog 认为如果我们可以证明存在 word/8
个谓词,其参数以特定方式统一,则我们可以证明 crossword/6
,并搜索这样做的 word/8
个谓词的组合。 "knowledge base" 为每个可能的证明提供了公理。
你现在知道如何完成 crossword/6
定义了吗?请注意,您需要为一些下划线变量(称为 "anonymous variables")命名以完成解决方案,并在 turnstyle 的右侧引入额外的 word/8
项。
目前我正在做序言tutorial。
有一个用 5 个单词解决填字游戏的练习。
我的问题是 Prolog
很早就停止了对我的解决方案的统一。
看起来是这样的:
并且给出了一个小的知识库:
word(astante, a,s,t,a,n,t,e).
word(astoria, a,s,t,o,r,i,a).
word(baratto, b,a,r,a,t,t,o).
word(cobalto, c,o,b,a,l,t,o).
word(pistola, p,i,s,t,o,l,a).
word(statale, s,t,a,t,a,l,e).
为了解决这个任务,我有一个谓词 crossword/6
。
所以我认为谓词 crossword
必须包含 6 个由变量组成的词,并且在两个词交叉的每个字段中我都设置了相同的变量。
crossword(word(H1, A1, B1, C1, D1, E1, F1, G1),
word(H2, A2, B2, C2, D2, E2, F2, G2),
word(H3, A3, B3, C3, D3, E3, F3, G3),
word(V1, _1, B1, _2, B2, _3, B3, _4),
word(V2, _5, D1, _6, D2, _7, D3, _8),
word(V3, _9, F1, _10, F2, _11, F3 _12)).
在 SWI-Prolog 中,我输入了以下请求:
?- crossword(H1, H2, H3, V1, V2, V3).
所以我问了一个填字游戏的答案。
我得到的结果是这样的:
H1 = word(_720, _722, _724, _726, _728, _730, _732, _734),
H2 = word(_738, _740, _742, _744, _746, _748, _750, _752),
H3 = word(_756, _758, _760, _762, _764, _766, _768, _770),
V1 = word(_774, _776, _724, _780, _742, _784, _760, _788),
V2 = word(_792, _794, _728, _798, _746, _802, _764, _806),
V3 = word(_810, _812, _732, _816, _750, _820, _768).
问题:为什么Prolog
这么早就停止统一了?为什么 return 没有任何解决方案?
你的代码声明了一个简单的事实:有一个crossword/6
谓词,它的参数是word/8
个谓词,并且word/8
个谓词的一些参数是相同的。特别是,由于 crossword/6
被声明为简单事实,因此 crossword/6
声明中的 word/8
谓词与知识库之间没有任何关系(就像 "astoria" 的事实一样不限制 "astante").
相反,只有文字本身才是简单的事实:
word(astante, a,s,t,a,n,t,e).
word(astoria, a,s,t,o,r,i,a).
word(baratto, b,a,r,a,t,t,o).
word(cobalto, c,o,b,a,l,t,o).
word(pistola, p,i,s,t,o,l,a).
word(statale, s,t,a,t,a,l,e).
因为这些都是没有条件的简单事实,我们总能证明有一个word/8
谓词,其第一个参数是astante/0
,第二个参数是a/0
,第三个参数是s/0
,依此类推。
你想说的是,如果这六个词的其他条件成立,那么这六个词就形成了一个有效的解决方案:
crossword( H1, H2, H3, V1, V2, V3 ) :-
<conditions for a successful crossword solution>.
接下来,定义 crossword/6
的条件,这样一个有效的解决方案是变量与 word/8
谓词的第一个参数统一,如果这些参数的第三个、第五个和第七个参数word/8
争论以正确的方式相互统一。
对于一个(不完整的)例子,如果 H1 的第二个字母是 V1 的第二个字母,H1 的第六个字母是 V3 的第二个字母,我可以说我有一个有效的填字游戏解决方案:
crossword( H1, H2, H3, V1, V2, V3 ) :-
word( H1, _, TL, _, _, _, TR, _ ),
word( V1, _, TL, _, _, _, _, _ ),
word( V3, _, TR, _, _, _, _, _ ).
这里我使用下划线 _
来避免给名称无关紧要的变量命名。我还使用 TL
和 TR
来表示 "top left" 和 "top right" 以使我自己的推理更容易。 Prolog 认为如果我们可以证明存在 word/8
个谓词,其参数以特定方式统一,则我们可以证明 crossword/6
,并搜索这样做的 word/8
个谓词的组合。 "knowledge base" 为每个可能的证明提供了公理。
你现在知道如何完成 crossword/6
定义了吗?请注意,您需要为一些下划线变量(称为 "anonymous variables")命名以完成解决方案,并在 turnstyle 的右侧引入额外的 word/8
项。