带序言的填字游戏 [英] crossword puzzle with prolog

查看:118
本文介绍了带序言的填字游戏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前我正在做一个 Prolog

并且给出了一个小的知识库:

 word(astante, a,s,t,a,n,t,e).字(阿斯托利亚,a,s,t,o,r,i,a).字(巴拉托,b,a,r,a,t,t,o).字(钴,c,o,b,a,l,t,o).字(手枪,p,i,s,t,o,l,a).字(状态,s,t,a,t,a,l,e).

为了解决这个任务,我有一个谓词crossword/6.

所以我认为谓词 crossword 必须包含 6 个由变量组成的单词,并且在两个单词交叉的每个字段中我都设置了相同的变量.

crossword(word(H1, A1, B1, C1, D1, E1, F1, G1),字(H2,A2,B2,C2,D2,E2,F2,G2),字(H3,A3,B3,C3,D3,E3,F3,G3),字(V1,_1,B1,_2,B2,_3,B3,_4),字(V2,_5,D1,_6,D2,_7,D3,_8),字(V3,_9,F1,_10,F2,_11,F3 _12)).

在 SWI-Prolog 中,我输入了以下请求:

?- 填字游戏(H1、H2、H3、V1、V2、V3).

所以我问了一个填字游戏的解决方案.

我得到的结果是这样的:

H1 = word(_720, _722, _724, _726, _728, _730, _732, _734),H2 = 字(_738、_740、_742、_744、_746、_748、_750、_752),H3 = 字(_756、_758、_760、_762、_764、_766、_768、_770),V1 = 字(_774、_776、_724、_780、_742、_784、_760、_788),V2 = 字(_792、_794、_728、_798、_746、_802、_764、_806),V3 = 字(_810、_812、_732、_816、_750、_820、_768).

问题:为什么 Prolog 如此早地停止统一?为什么它不返回任何解决方案?

解决方案

您的代码声明了一个简单的事实:有一个 crossword/6 谓词,其参数为 word/8> 谓词,并且 word/8 谓词的一些参数是相同的.特别是,由于 crossword/6 被声明为一个简单的事实,crossword/6 声明中的 word/8 谓词之间没有关系和知识库(就像astoria"的事实不限制astante"的事实一样).

相反,只有单词本身才是简单的事实:

word(astante, a,s,t,a,n,t,e).字(阿斯托利亚,a,s,t,o,r,i,a).字(巴拉托,b,a,r,a,t,t,o).字(钴,c,o,b,a,l,t,o).字(手枪,p,i,s,t,o,l,a).字(状态,s,t,a,t,a,l,e).

因为这些都是没有条件的简单事实,所以我们总能证明存在一个word/8谓词,它的第一个参数是astante/0,第二个参数是a/0,第三个参数是s/0,依此类推.

你想说的是,如果这六个词在其他方面都是正确的,那么这六个词构成了一个有效的解决方案:

填字游戏(H1,H2,H3,V1,V2,V3):-<填字游戏成功的条件>.

接下来,定义 crossword/6 的条件,以便有效的解决方案是变量与 word/8 谓词的第一个参数统一,如果第三个这些 word/8 参数的第五个和第七个参数以正确的方式相互统一.

举一个(不完整的)例子,如果H1的第二个字母是V1的第二个字母,H1的第六个字母是V3的第二个字母,我可以说我有一个有效的填字游戏解决方案:

填字游戏(H1,H2,H3,V1,V2,V3):-字(H1,_,TL,_,_,_,TR,_),字(V1,_,TL,_,_,_,_,_),字(V3,_,TR,_,_,_,_,_).

这里我使用下划线 _ 来避免给名称无关紧要的变量命名.我还使用 TLTR 表示左上角"和右上角",以使自己更容易推理.Prolog 看到如果我们能证明存在 word/8 谓词的参数以特定方式统一,我们就可以证明 crossword/6,并搜索 的组合word/8 谓词这样做.知识库"为每个可能的证明提供公理.

你现在看到如何完成crossword/6定义了吗?请注意,您需要给出一些下划线变量(称为匿名变量")名称以完成解决方案,并在转弯样式的右侧引入额外的 word/8 术语.

Currently I am doing a Prolog tutorial.

There is an exercise to solve a crossword puzzle with 5 words.

My Problem is that Prolog stops unification for my solution at a very early point.

It looks like that:

And there is a small knowledge base given:

   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).

To solve that task I have a predicate crossword/6.

So I have thought that the predicate crossword must contain 6 words that are made of variables and at every field where two words cross I have set there the same variable.

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)).

In SWI-Prolog I have typed the following request:

?- crossword(H1, H2, H3, V1, V2, V3).

So I have asked for the solution of a crossword puzzle.

The result I get is like that:

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).

Question: Why does Prolog stop unification at such a early point ? And why doesn't it return any solution?

解决方案

Your code declares a simple fact: there is a crossword/6 predicate whose arguments are word/8 predicates, and some of the arguments of the word/8 predicates are the same. In particular, since crossword/6 is declared as a simple fact, there's no relationship between the word/8 predicates in the crossword/6 declaration and the knowledge base (just like the fact for "astoria" doesn't constrain the fact for "astante").

Instead, only the words themselves are simple facts:

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).

Because these are simple facts with no conditions, we can always prove that there is a word/8 predicate whose first argument is astante/0, second argument is a/0, third argument is s/0, and so on.

What you want to say is that the six words form a valid solution if other things are true of those words:

crossword( H1, H2, H3, V1, V2, V3 ) :-
  <conditions for a successful crossword solution>.

Next, define the conditions for crossword/6 so that a valid solution is one in which the variables unify with the first argument of word/8 predicates if the third, fifth, and seventh arguments of those word/8 arguments unify with each other in the right way.

For an (incomplete) example, I can say I have a valid cross-word solution if the second letter of H1 is the second letter of V1, and the sixth letter of H1 is the second letter of V3:

crossword( H1, H2, H3, V1, V2, V3 ) :-
  word( H1, _, TL, _, _, _, TR, _ ),
  word( V1, _, TL, _, _, _, _, _ ),
  word( V3, _, TR, _, _, _, _, _ ).

Here I'm using underscore _ to avoid giving names to variables whose names don't matter. I'm also using TL and TR for "top left" and "top right" to make the reasoning easier on myself. Prolog sees that we can prove crossword/6 if we can prove that there are word/8 predicates whose arguments unify in a particular way, and searches for combinations of word/8 predicates that do so. The "knowledge base" provides axioms for each possible proof.

Do you see how to complete the crossword/6 definition now? Notice that you'll need to give some of the underscore variables (called "anonymous variables") names to complete the solution, and introduce additional word/8 terms on the right-hand side of the turnstyle.

这篇关于带序言的填字游戏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆