【问题标题】:Learn Prolog Now! DCG Practice Example立即学习 Prolog! DCG 实践示例
【发布时间】:2010-06-08 01:28:29
【问题描述】:

我一直在自学通过Learn Prolog Now!,现在正在学习定从句语法。我在实践会议的一项任务中遇到了一些困难。 The task 阅读:

形式语言anb2mc2mdn由以下形式的所有字符串组成: 一个完整的 as 块,后面是一个完整的 bs 块,然后是一个完整的 cs 块,然后是一个完整的 bs 块ds,使得 ad 块的长度完全相同,而 cd 块的长度也完全相同,并且分别由偶数个 cd 组成。比如εabbccdaaabbbbccccddd都属于anb2mc2mdn。编写一个生成这种语言的 DCG。

我能够编写生成 andn、b2mc2m 和甚至 anb2m 和 c2mdn... 但我似乎无法加入所有将这些规则转化为 anb2mc2mdn。以下是我可以生成andn和b2mc2m的规则。

s1 --> [].
s1 --> a,s1,d.
a --> [a].
d --> [d].

s2 --> [].
s2 --> c,c,s2,d,d.
c --> [c].
d --> [d].

anb2mc2mdn真的是CFG吗,能写吗仅使用课程中所教内容的 DCG(没有额外的参数或代码等)?如果是这样,任何人都可以为我提供一些指导,我可以如何加入这些,以便我可以解决给定的任务?

【问题讨论】:

    标签: prolog grammar dcg


    【解决方案1】:

    @Timothy,您的答案有效,但会产生重复:

    ?- length(S,_), s(S,[]).
    S = [] ;
    S = [a, d] ;
    S = [a, d] ;            % XXX
    S = [b, b, c, c] ;
    S = [a, a, d, d] ;
    S = [a, a, d, d] ;      % XXX
    

    这可以通过删除一个子句来解决,留下 DCG:

    s --> x.
    s --> a,s,d.
    
    x --> [].
    x --> b,b,x,c,c.
    
    % a, b, c, d the same
    

    这会生成:

    ?- length(S,_), s(S,[]).
    S = [] ;
    S = [a, d] ;
    S = [b, b, c, c] ;
    S = [a, a, d, d] ;
    S = [a, b, b, c, c, d] ;
    S = [a, a, a, d, d, d] ;
    S = [b, b, b, b, c, c, c, c] ;
    S = [a, a, b, b, c, c, d, d] ;
    S = [a, a, a, a, d, d, d, d] ;
    

    【讨论】:

      【解决方案2】:

      我相信我想通了......

      s --> x.
      s --> a,d.
      s --> a,s,d.
      
      x --> [].
      x --> b,b,x,c,c.
      
      a --> [a].
      b --> [b].
      c --> [c].
      d --> [d].
      
      ?- s([],[]).
      Yes
      
      ?- s([a,b,c,c,d],[]).
      No
      
      ?- s([a,a,a,b,b,c,c,d,d,d],[]).
      Yes
      

      看着解决方案并想,“我绞尽脑汁想那个是很有趣的?”但我想这只是学习新东西的一半乐趣,尤其是当它像来自命令式编程背景的逻辑编程时。

      【讨论】:

      • 这很难,但有回报。逻辑编程(和惰性 FP)知识,尤其是。在学习 C++、Java 和 Python 中的迭代器概念时为我服务。
      【解决方案3】:

      怎么样:

      n(L,N) --> n(L,N,0).
      
      n(_,N,N) --> [], !.
      n(L,N,K) --> L, {K1 is K + 1}, n(L, N, K1).
      
      abbccd(N,M) -->
          {M1 is 2*M},
          n("a",N),
          n("b",M1),
          n("c",M1),
          n("d",N).
      
      gen :-
          forall((
                 between(1,4,N),
              between(1,4,M),
              phrase(abbccd(N,M),S),
              string_to_atom(S,A)
                 ),
                 writeln(A)).
      

      执行:

       ?- gen.
      abbccd
      abbbbccccd
      abbbbbbccccccd
      abbbbbbbbccccccccd
      aabbccdd
      aabbbbccccdd
      aabbbbbbccccccdd
      aabbbbbbbbccccccccdd
      aaabbccddd
      aaabbbbccccddd
      aaabbbbbbccccccddd
      aaabbbbbbbbccccccccddd
      aaaabbccdddd
      aaaabbbbccccdddd
      aaaabbbbbbccccccdddd
      aaaabbbbbbbbccccccccdddd
      true.
      

      【讨论】:

      • 谢谢你,Xonix。这行得通,但不幸的是,它使用了后来才涵盖的概念(代码块、剪切等)。老实说,我认为仅使用简单的规则是不可能的……或者,如果是,那么不值得付出努力,因为在“现实世界”中,人们会像您在示例中所做的那样利用其他概念。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-30
      • 1970-01-01
      相关资源
      最近更新 更多