String 识别由两个相等部分组成的单词

String 识别由两个相等部分组成的单词,string,prolog,dcg,String,Prolog,Dcg,任务是识别像“abab”这样的单词,拒绝像“aacc”这样的单词。我应该使用DCG,但是我正在读的关于Prolog的书只解释了如何在原子列表上使用它们,而不是在字符串上 ?- double("abab", []). true ?- double("xyz", []). false 这是一个“家庭作业”问题,所以如果你不愿意给我答案,请随意给我一个提示。我真的不知道用谷歌搜索什么。Prolog中的字符串是字符代码列表。因此,如果您知道如何将DCG用于列表,那么您也已经知道如何将它们用于字符串。我

任务是识别像“abab”这样的单词,拒绝像“aacc”这样的单词。我应该使用DCG,但是我正在读的关于Prolog的书只解释了如何在原子列表上使用它们,而不是在字符串上

?- double("abab", []).
true
?- double("xyz", []).
false
这是一个“家庭作业”问题,所以如果你不愿意给我答案,请随意给我一个提示。我真的不知道用谷歌搜索什么。

Prolog中的字符串是字符代码列表。因此,如果您知道如何将DCG用于列表,那么您也已经知道如何将它们用于字符串。我同意@mat的观点,即字符列表更具可读性,因此我建议您按照他在评论中的建议设置标志

也就是说,您可以使用DCG seq//1来描述任意字符串,并在DCG double//0中使用它来描述这样的字符串必须出现两次。我还建议在DCG中使用短语/2或短语/3,而不是使用DCG规则转换成的谓词(参见@mat的评论)。您可以使用短语/2定义谓词double/1,如下所示:

double(D) :-            % the list D as described by
   phrase(double,D).    % the actual DCG double//0

seq([]) -->
   [].
seq([H|T]) -->
   [H],
   seq(T).

double -->
   seq(L),
   seq(L).
查询调用谓词double/1会产生以下结果:

   ?- double("abab").
yes
   ?- double("xyz").
no
   ?- double("aacc").
no
   ?- double(D).
D = [] ? ;
D = [_A,_A] ? ;
D = [_A,_B,_A,_B] ? ;
D = [_A,_B,_C,_A,_B,_C] ? ;
...
如果您坚持,您也可以在上述代码中使用double/2的示例查询,但我再次向您推荐@mat的注释,说明为什么不建议这样做。

序言中的字符串是字符代码列表。因此,如果您知道如何将DCG用于列表,那么您也已经知道如何将它们用于字符串。我同意@mat的观点,即字符列表更具可读性,因此我建议您按照他在评论中的建议设置标志

也就是说,您可以使用DCG seq//1来描述任意字符串,并在DCG double//0中使用它来描述这样的字符串必须出现两次。我还建议在DCG中使用短语/2或短语/3,而不是使用DCG规则转换成的谓词(参见@mat的评论)。您可以使用短语/2定义谓词double/1,如下所示:

double(D) :-            % the list D as described by
   phrase(double,D).    % the actual DCG double//0

seq([]) -->
   [].
seq([H|T]) -->
   [H],
   seq(T).

double -->
   seq(L),
   seq(L).
查询调用谓词double/1会产生以下结果:

   ?- double("abab").
yes
   ?- double("xyz").
no
   ?- double("aacc").
no
   ?- double(D).
D = [] ? ;
D = [_A,_A] ? ;
D = [_A,_B,_A,_B] ? ;
D = [_A,_B,_C,_A,_B,_C] ? ;
...

如果您坚持,您也可以在上述代码中使用双引号/2的示例查询,但我再次向您推荐@mat的注释,说明为什么不建议这样做。

最好使用
:-set_prolog_标志(双引号,字符)。
在源文件中:这意味着双引号字符串是原子列表,因此,在您的案例中,您可以通过编写
“abab”
“xyz”
来方便地对列表进行推理,这很好。我强烈建议设置此标志,因为它可以非常方便地对此类列表进行推理,并且可以让顶级答案非常可读。使用字符比使用代码要好得多。最好使用
:-set_prolog\u flag(双引号,字符)。
在源文件中:这意味着双引号字符串是原子列表,因此您可以通过编写
“abab”方便地对列表进行推理
“xyz”
@mat太棒了。我强烈建议设置此标志,因为它可以非常方便地对此类列表进行推理,并且可以让顶级答案非常可读。使用字符比使用代码要好得多。书中说DCG在差异列表匹配器中被删除,所以你使用它们就像使用差异列表谓词一样,这意味着包括额外的参数。。。。这不是“原子列表”,而是“字符列表”,它们是“长度为1的原子列表”@LukaHorvat:这本书并没有给出完整的情况:这只是在Prolog系统中实现DCG的一种特殊方法。没有什么可以阻止系统使用完全不同的实现。事实上,DCG甚至不需要编译成Prolog子句,而是可以动态解释。因此,不能保证有任何额外的参数可用。在使用DCG时,始终使用
短语/[2,3]
接口谓词,就像TA那样。@LukaHorvat:当然,我很傻。我甚至没有考虑使用DCGS没有短语[/2,3]。参见mat的评论,为什么这样更好。无论如何,感谢您的澄清,我相应地更新了我的答案。@false:关于您的第一条评论:如果我没有包括
:-set_prolog\u flag(双引号,字符)。
在我的
.yaprc
中,我会得到字符串作为字符代码列表:
“ab”=[97,98]
。设置该标志后,我得到了
“ab”=[a,b]
。因此,默认情况下,字符串是字符代码列表。关于你的第二条评论:谢谢你的更正,我相应地修改了我的措辞:-)这本书说DCG在diff-list匹配器中被去除,所以你使用它们就像使用diff-list谓词一样,这意味着包括额外的参数。。。。这不是“原子列表”,而是“字符列表”,它们是“长度为1的原子列表”@LukaHorvat:这本书并没有给出完整的情况:这只是在Prolog系统中实现DCG的一种特殊方法。没有什么可以阻止系统使用完全不同的实现。事实上,DCG甚至不需要编译成Prolog子句,而是可以动态解释。因此,不能保证有任何额外的参数可用。在使用DCG时,始终使用
短语/[2,3]
接口谓词,就像TA那样。@LukaHorvat:当然,我很傻。我甚至没有考虑使用DCGS没有短语[/2,3]。参见mat的评论,为什么这样更好。无论如何,感谢您的澄清,我相应地更新了我的答案。@false:关于您的第一条评论:如果我没有包括
:-set_prolog\u flag(双引号,字符)。
在我的
.yaprc
中,我会得到字符串作为字符代码列表:
“ab”=[97,98]
。设置该标志后,我得到了
“ab”=[a,b]
。因此,默认情况下,字符串是字符co的列表