【问题标题】:Recognize A^n B^n language in Prolog with no arithmetics在 Prolog 中识别 A^n B^n 语言,无需算术
【发布时间】:2013-05-07 09:55:04
【问题描述】:

如何在没有算术的情况下识别 Prolog 中的 A^n B^n 语言以及对于 A != B 的任何 A、B?

已知 A = a 和 B = b 我们可以写

% For each 'a' save 'b' in a list, then check 
% whether constructed list is equal to the rest of input list

anbn(L) :- anbn(L, []). 

anbn(L, L). 

anbn([a|L],A) :- anbn(L, [b|A]).

对于任何 A 和 B,我都在考虑以

开头的解决方案
anbn(L) :- anbn(L, []).

anbn([H|L],[]) :- anbn(L,[H]). % save an element

anbn([H|L], [H|A]) :- anbn(L, [H,H|A]). % make sure front elements are the same

所以第一个元素都是相同的,但是我没有看到一种优雅的方法来检查列表其余部分中的所有元素是否与前面的元素相同和不同。

我可以检查其余的是否与存储的列表一样长,然后检查它是否仅包含第二种类型的元素,但我相信我使问题过于复杂,并且存在一个简短而简单的解决方案。

【问题讨论】:

  • 你为什么不使用定句语法?
  • @larsmans 我尝试了一个使用 DCG 的解决方案,但是任意 A 和 B 的要求并且没有算术使得该解决方案并不比普通符号好多少。你能展示你的解决方案吗?
  • 我可能错了,但是 a^n b^n 它不是 常规 语言。
  • @Boris: s --> []. s --> [a], s, [b]. 然后将两个参数添加到 s 并对第二条规则进行两个小改动。 (我尽量不泄露答案。)
  • @CapelliC:不,不是,为什么?

标签: prolog grammar dcg automata


【解决方案1】:

使用明确的从句语法。

s(_, _) --> [].
s(A, B) --> [A], s(A, B), [B].

演示:

?- phrase(s(1, 2), X).
X = [] ;
X = [1, 2] ;
X = [1, 1, 2, 2] ;
X = [1, 1, 1, 2, 2, 2] .

【讨论】:

  • 非常好,+1。与此处发布的其他解决方案相比,您的解决方案也适用于最一般的查询?- phrase(s(X,Y), Ls).。请注意,尽管您尚未满足 OP 的要求,即 XY 是不同的。在第一条规则中使用dif/2。应该始终使用phrase/2(或phrase/3)接口来连接 DCG,因为 DCG 到 Prolog 谓词的转换可能会根据 Prolog 实现或版本而改变。
  • 唯一不会灼伤我眼睛的解决方案。 :) +1
  • @mat:我将 A!=B 解读为解决方案在这种情况下有效的要求,而不是实际执行的要求。不过,我删除了没有phrase/2 的用法示例。
  • @mat:另外,我刚刚尝试了您将dif 放在第一条规则中的建议,并且在phrase(s(1,1),S) 上永远回溯。约束实际上应该在语法/递归之外处理。
  • @mat “工作正常……还不满足”,这是自相矛盾的。 “带有未实例化 Ls 的最一般查询 phrase(s(X,Y), Ls) 与声明的要求相矛盾 X\=Y。实例化 Ls 后,我(可能还有其他人)的答案可以正常工作。
【解决方案2】:

编辑:回到原来的解决方案,并坚持下去:

anbn(List) :- List = [] -> true; List = [A|Rest], a(Rest, A, 0).

a([A|Rest], A, N) :- !, a(Rest, A, s(N)).
a([B|Rest], _, N) :- b(Rest, B, N).

b([B|Rest], B, s(N)) :- b(Rest, B, N).
b([], _, 0).

它是迭代的,它不会创建选择点,很明显,而且如果列表的所有元素都是接地的,它是正确的。

【讨论】:

  • 工作正常。你的,就像我的(和 larsmans 的)一样,接受[1,1,1,2,2,X]
  • @WillNess 是的,还有 [A,a,b,B] 等等。我不知道如何解决这个没有添加nonvar 要求的问题。
  • 或者这可能不需要解决。 :)(CapelliC 的回答也是)。
  • @Boris 这就是我一直在寻找的 :) 有点长,但仍然很优雅。
【解决方案3】:

对于 DCG 来说,裸变量被重新包装是很常见的 在翻译过程中作为短语/3。这样就可以实现 A^n B^n 不仅适用于 A 和 B 是终结点,而且适用于 当 A 和 B 是任意 DCG 目标时。

下面是代码:

 s(_,_) --> [].
 s(A,B) --> A, s(A,B), B.

这里可以看到由 SWI-Prolog 完成的翻译。 可以看到裸变量已被转换 短语/3 个目标:

 ?- listing.
 s(_, _, A, A).
 s(A, C, B, F) :-
    phrase(A, B, D),
    s(A, C, D, E),
    phrase(C, E, F).

这是一个运行示例,用于终端 A 和 B:

 ?- phrase(s("alfa","beta"),X), atom_codes(Y,X).
 X = [],
 Y = '' ;
 X = [97, 108, 102, 97, 98, 101, 116, 97],
 Y = alfabeta ;
 X = [97, 108, 102, 97, 97, 108, 102, 97, 98|...],
 Y = alfaalfabetabeta ;
 X = [97, 108, 102, 97, 97, 108, 102, 97, 97|...],
 Y = alfaalfaalfabetabetabeta .

这是一个示例运行,对于一些 DCG 目标作为 A 和 B:

  bit --> "0".
  bit --> "1".

  ?- length(L,8), phrase(s(("(",bit),(bit,")")),L), atom_codes(R,L).
  L = [40, 48, 40, 48, 48, 41, 48, 41],
  R = '(0(00)0)' ;
  L = [40, 48, 40, 48, 48, 41, 49, 41],
  R = '(0(00)1)' ;
  L = [40, 48, 40, 48, 49, 41, 48, 41],
  R = '(0(01)0)' ;
  Etc..

再见

【讨论】:

    【解决方案4】:

    我认为它比那更简单:

    anbn(L) :- append(As, Bs, L), maplist(ab, As, Bs).
    ab(a, b).
    

    编辑:这很容易推广到任意文字。

    anbn(L) :- L = [A|_], append(As, Bs, L), maplist(ab(A), As, Bs).
    ab(A, A, B) :- A \== B.
    

    编辑: Will Ness 注意到这是错误的:我的意思是

    anbn(L) :- append([A|As], [B|Bs], L), A \= B, maplist(ab(A, B), As, Bs).
    ab(A, B, A, B).
    

    【讨论】:

    • dif/2 这是一个相当复杂的内置库。在不可用的地方肯定更难实现,WRT maplist/3
    • 也许我们在强调 StackOverflow 移动得太快 :)
    【解决方案5】:
    anbn( [] ) :- !.
    anbn( L ) :- L=[A|_], copy_half( L,L, Z,Z, A,_V). % Z is second half
    copy_half( [A|B], [_,_|C], [V|D], Z, A,V) :- !, copy_half( B,C, D,Z, A,V).
    copy_half( Z,     [],      [],    Z, A,V) :- A \== V.
    

    相当于

    anbn_verboten(L):- L = [] ;
      length(L,N), N2 is N div 2, length(X,N2), length(Y,N2), append(X,Y,L), 
      L=[P|_], Y=[Q|_], P \= Q.`.
    

    【讨论】:

      猜你喜欢
      • 2014-02-12
      • 1970-01-01
      • 1970-01-01
      • 2016-04-27
      • 1970-01-01
      • 2022-06-28
      • 2021-12-11
      • 1970-01-01
      • 2014-05-18
      相关资源
      最近更新 更多