Prolog 文字处理序言

Prolog 文字处理序言,prolog,logic,dcg,logical-purity,Prolog,Logic,Dcg,Logical Purity,我试图在序言中将一个单词按照两条不同的规则分成不同的音节 规则1:元音辅音元音(在第二个元音后打断单词) 规则2:元音-辅音-辅音-元音(两个字母之间的分词) 辅音),例如,计算器=计算器 我在Prolog中已经有了下面的代码,但是,它只分析单词的前3或4个字母 我需要它来处理和分析整个单词 vowel(a). vowel(e). vowel(i). vowel(o). vowel(u). consonant(L):- not(vowel(L)

我试图在序言中将一个单词按照两条不同的规则分成不同的音节

规则1:元音辅音元音(在第二个元音后打断单词)
规则2:元音-辅音-辅音-元音(两个字母之间的分词) 辅音),例如,计算器=计算器

我在Prolog中已经有了下面的代码,但是,它只分析单词的前3或4个字母

我需要它来处理和分析整个单词

    vowel(a).
    vowel(e).
    vowel(i).
    vowel(o).
    vowel(u).


    consonant(L):- not(vowel(L)).

    syllable(W, S, RW):- 
        atom_chars(W, [V1, C, V2|Tail]), 
        vowel(V1), 
        consonant(C), 
        vowel(V2), 
        !, 
        atomic_list_concat([V1, C, V2], S), 
        atomic_list_concat(Tail, RW).

    syllable(W, S, RW):- 
        atom_chars(W, [V1, C, C2, V2|Tail]), 
        vowel(V1), 
        consonant(C), 
        consonant(C2),
        vowel(V2), 
        !, 
        atomic_list_concat([V1, C, C2, V2], S), 
        atomic_list_concat(Tail, RW).

    syllable(W, W, _).

    break(W, B):- 
        syllable(W, B, ''), !.

    break(W, B):- 
        syllable(W, S, RW), 
        break(RW, B2), 
        atomic_list_concat([S, '-', B2], B).

我想你可以写得更简单一些。下面是我的实现:

syllable( Input, Final_Word):-
    atom_chars( Input, Char_list),
    (split(Char_list, Word)-> atom_chars( Final_Word, Word);
        Final_Word=Input).


split([],[]).
split([X,Y,Z|T],[X,Y,Z,'-'|T1]):- 
                    vowel(X),vowel(Z),
                    atom_chars( Input, T),
                    syllable(Input,T2),
                    atom_chars( T2, T1). 

split([X,Y,Z,W|T],[X,Y,'-',Z|T1]):-
                    vowel(X),\+vowel(Y),\+vowel(Z),vowel(W),
                    atom_chars( Input, [W|T]),
                    syllable(Input,T2),
                    atom_chars( T2, T1).    


split([X|T],[X|T1]):- \+vowel(X),split(T,T1). 
split/2拆分单词adding'-',该单词可以按照上述规则添加,并将列表返回到音节
atom_chars/2
将列表转换为单词。如果无法拆分单词,则输出为输入

例如:

?- syllable(calculator,L).
L = 'calcu-lato-r'.

我不明白你为什么要写“calculator=calculator”,因为它没有遵循规定的规则,因为“cal”不是元音常量元音,而是元音常量元音常量,并且对其他单词都是一样的…

首先,这一设置使得指定字符列表更加方便,如果您经常处理文本,我建议您在代码中使用:

第二,数据,以定义可在所有方向使用的方式表示:

vowel(a). vowel(e). vowel(i). vowel(o). vowel(u). consonant(C) :- maplist(dif(C), [a,e,i,o,u]). 现在重点是:由于该程序是完全纯的,并且不会过早错误地提交,因此我们可以使用它来显示还有其他允许的连字号:

?- phrase(word_breaks("calculator"), Hs). Hs = [[c, a, l], [c, u, l, a], [t, o, r]] ; Hs = [[c, a, l], [c, u, l, a, t, o], [r]] ; Hs = [[c, a, l], [c, u, l, a, t, o, r]] ; Hs = [[c, a, l, c, u, l, a], [t, o, r]] ; Hs = [[c, a, l, c, u, l, a, t, o], [r]] ; Hs = [[c, a, l, c, u, l, a, t, o, r]]. -短语(单词“计算器”),Hs)。 Hs=[[c,a,l],[c,u,l,a],[t,o,r]; Hs=[[c,a,l],[c,u,l,a,t,o],[r]; Hs=[[c,a,l],[c,u,l,a,t,o,r]; Hs=[[c,a,l,c,u,l,a],[t,o,r]; Hs=[[c,a,l,c,u,l,a,t,o],[r]]; Hs=[[c,a,l,c,u,l,a,t,o,r]]。
在Prolog中,最好保留代码的通用性,这样您就可以随时观察其他解决方案。请参阅。

我想是时候采用DCG后推解决方案了。在break//1的第二个规则中使用了push-back。这是为了反映我们看了四个字符,但只使用了两个字符:

vowel(a). vowel(e). vowel(i). vowel(o). vowel(u).

consonant(C) :- \+ vowel(C).

break([V1,C,V2]) -->
   [V1,C,V2],
   {vowel(V1), consonant(C), vowel(V2)}.
break([V1,C1]), [C2,V2] -->
   [V1,C1,C2,V2],
   {vowel(V1), consonant(C1), consonant(C2), vowel(V2)}.

syllables([L|R]) --> break(L), !, syllables(R).
syllables([[C|L]|R]) --> [C], syllables([L|R]).
syllables([[]]) --> [].
因此,整个解决方案不需要一些额外的谓词,例如append/3或reverse/2。我们还对搜索进行了删减,这是因为音节/1的第二条规则中有catchall字符

以下是一些运行示例:

Jekejeke Prolog 2, Laufzeitbibliothek 1.1.6
(c) 1985-2016, XLOG Technologies GmbH, Schweiz

?- set_prolog_flag(double_quotes, chars).
Ja

?- phrase(syllables(R), "calculator").
R = [[c,a,l],[c,u,l,a],[t,o,r]] ;
Nein

?- phrase(syllables(R), "kitchensink").
R = [[k,i,t,c,h,e,n],[s,i,n,k]] ;
Nein
注:在一些较旧的标准草案中,这种DCG技术是 被称为“右手语境”,而不是动词“推” “后退”,使用动词“前缀”。在较新的标准草案中 这被称为“文本”,而不是动词“推回”, 使用动词“恢复”


如何将“calculato-r”作为一个可接受的连字号?@Boris:根据第一条规则:“元音-辅音-元音(在第二个元音之后打断)”:
ato
:元音-辅音-元音,所以在“o”之后,我们打断!附言:这些规则不是我定的,听起来不对。我很确定这些规则是用来分解成音节的:你不能在末尾留下一个非音节,对吗?而且,只有一种方法(而且应该是!)可以拆分成音节(或者选择可能的连字符点)。或者我不知怎么搞糊涂了?@Boris:不幸的是,我无法回答你的问题,但我绝对认为这是Prolog的一个优点,因为它可以很容易地用来表明,正如你正确指出的那样,光是规定的规则就会导致歧义甚至无效的连字号。使用不纯谓词只会掩盖规则本身的固有问题。我发布我的解决方案主要是为了展示Prolog的这一优势。许多“罗马数字”的例子也是如此:所述的大多数规则都是模棱两可的,但过早地提交隐藏了这一固有问题。我认为我们可以用Prolog检测到这一点很好!不要低估断字的“规则性”!TeXbook包含了一个关于这个主题的重要章节,并指向了一些非常令人惊讶的研究论文,这些论文展示了基于规则的连字号实际上是如何跨不同语言的。这种情况下的数据库主要是规则异常数据库。。。如果有两条规则足以捕捉所有有效的连字号模式,我会感到惊讶。“cal”不是元音辅音元音,但“alcu”是元音辅音元音…没错,所以它能识别“alcu”,并在“alcu”后面加一个“-”,很清楚他是否想在“alcu”之前加“-”如果这就是你的意思…所以我不太确定正确的输出是什么样子…应该是'c-alcu-l-ato-r'?@编码器这真的很有帮助,但正如mat所说,alcu是一个元音常量元音,因为规则表明它必须在两个常量之间断开,计算器应该是计算器。。“al”和“cu”(元音常量元音..常量元音之间的拆分)和“ula”(元音常量元音..第二个元音之后的拆分)之间的一次拆分编辑了答案,尽管我不理解您的标准,因为例如,您可以使用cal-cul-ato-r,因为“ato”是有效的…它是“辅音”,而不是“constant”我刚注意到你在代码中拼写正确,但在文本中没有…这很奇怪,因为辅音不是常量。它们都表示不同的意思,尤其是“constant”“是计算机科学中非常常见的术语。至于代码与文本,这可能意味着你从没有归属的人那里复制了代码(“我已经有代码了”,嗯),这是剽窃,这不好。基本上,据我所知,你正在使用Stackoverflow作为免费的家庭作业写作服务,并取得了一些成功。我对此无能为力,只能告诉你我注意到了。这里的问题和答案代码来自哪里:现在至少它被列为“链接”,其他人也可以看到它 % rule 1: vowel-consonant-vowel (break after second vowel) rule([V1,C,V2|Rest], Bs0, Bs, Rest) :- vowel(V1), consonant(C), vowel(V2), reverse([V2,C,V1|Bs0], Bs). % rule 2: vowel-consonant-consonant-vowel (break between the consonants) rule([V1,C1,C2,V2|Rest], Bs0, Bs, [C2,V2|Rest]) :- vowel(V1), consonant(C1), consonant(C2), vowel(V2), reverse([C1,V1|Bs0], Bs). % alternative: no break at this position rule([L|Ls], Bs0, Bs, Rest) :- rule(Ls, [L|Bs0], Bs, Rest). word_breaks([]) --> []. word_breaks([L|Ls]) --> [Bs], { rule([L|Ls], [], Bs, Rest) }, word_breaks(Rest). word_breaks([L|Ls]) --> [[L|Ls]]. ?- phrase(word_breaks("calculator"), Hs). Hs = [[c, a, l], [c, u, l, a], [t, o, r]] ; Hs = [[c, a, l], [c, u, l, a, t, o], [r]] ; Hs = [[c, a, l], [c, u, l, a, t, o, r]] ; Hs = [[c, a, l, c, u, l, a], [t, o, r]] ; Hs = [[c, a, l, c, u, l, a, t, o], [r]] ; Hs = [[c, a, l, c, u, l, a, t, o, r]].
vowel(a). vowel(e). vowel(i). vowel(o). vowel(u).

consonant(C) :- \+ vowel(C).

break([V1,C,V2]) -->
   [V1,C,V2],
   {vowel(V1), consonant(C), vowel(V2)}.
break([V1,C1]), [C2,V2] -->
   [V1,C1,C2,V2],
   {vowel(V1), consonant(C1), consonant(C2), vowel(V2)}.

syllables([L|R]) --> break(L), !, syllables(R).
syllables([[C|L]|R]) --> [C], syllables([L|R]).
syllables([[]]) --> [].
Jekejeke Prolog 2, Laufzeitbibliothek 1.1.6
(c) 1985-2016, XLOG Technologies GmbH, Schweiz

?- set_prolog_flag(double_quotes, chars).
Ja

?- phrase(syllables(R), "calculator").
R = [[c,a,l],[c,u,l,a],[t,o,r]] ;
Nein

?- phrase(syllables(R), "kitchensink").
R = [[k,i,t,c,h,e,n],[s,i,n,k]] ;
Nein