2016-10-28 2 views
3

Я пытаюсь сломать слово в разных слогах в прологе согласно 2 различным правилам. Правило 1: гласный-согласный-гласный (сломанное слово после второго гласного) правило 2: гласный-согласный-согласный-гласный (сломайте слово между двумя согласными), например, калькулятор = cal-cula-tor .. У меня уже есть следующий код в прологе, однако он анализирует только первые 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). 
+2

Это «согласный», а не «постоянная» –

+1

Я просто заметил, что Вы правильно написано в коде, но не в тексте ... это странно –

+0

@Boris Вы замечаете вещи, которые довольно неуместны .. согласные или постоянные, они оба означают одно и то же ... письмо, которое не является гласным .. я понятия не имею, почему мое правописание так беспокоит вас. –

ответ

2

Я думаю, вы могли бы написать это более simply.Here моя реализация:

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

разделить/2 разбивает слово, добавив «-», где он может быть добавлен следующий вышеуказанные правила, изложенные и возвращает список слогу. atom_chars/2 преобразует список в слово. Если слово не может быть разделено, выход - это вход.

Пример:

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

Я не понимаю, почему вы написали «калькулятор = кал-CULA-TOR», поскольку она не соответствует правилам, указанным, так как «кал» не vowel- константа-гласная, но константа-гласная-константа и то же самое для остальной части слова ...

+0

«cal» не гласный-согласный-гласный, а «alcu» - гласный-согласный-согласный-гласный ... – mat

+0

Да именно так он распознает «alcu» и после этого «-» ставит. на самом деле, если он хочет «-» перед «alcu», если это то, что вы имеете в виду ... поэтому я не очень уверен, как выглядит правильный результат ... если это будет «c-alcu-l-ato-r '?? – coder

+1

@coder это было действительно полезно, но так же, как сказал матовый, alcu - гласный-константа-постоянная гласная, и поскольку правило предполагает, что оно должно быть разбито между двумя константами, оно должно быть al-cu .. –

3

Во-первых, настройка, которая делает его более удобным указать списки символов и которые я рекомендую вам использовать в своих код, если вы обрабатываете текст много:

:- set_prolog_flag(double_quotes, chars). 

Во-вторых, данные, представленные таким образом, что определения могут быть использованы во всех направлениях:

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

consonant(C) :- maplist(dif(C), [a,e,i,o,u]). 

Например:

 
?- consonant(C). 
dif(C, u), 
dif(C, o), 
dif(C, i), 
dif(C, e), 
dif(C, a). 

в то время как версия вы отправили неправильно говорит, что нет согласных:

 
?- consonant(C). 
false. 

правила, которые вы контурные легко описаны в Прологе:

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

Упражнение: Почему я пишу [V2,C,V1|_] вместо [V1,C,V2|...] в вызове reverse/2?

Теперь осталось описать список из полученных слогов.Это очень просто с нотации:

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

в Прологе это хорошая практика, чтобы сохранить общности вашего кода, так что вы можете легко наблюдать Alterna решения. См. .

+1

Как «calculato-r» допустимая перенос? –

+0

@Boris: По первому правилу: «гласный-согласный-гласный (перерыв после второго гласного)»: 'ato': гласный-согласный-гласный, поэтому после« о »мы ломаемся! P.S .: Я не делал эти правила. – mat

+0

Звучит не так. Я совершенно уверен, что эти правила предназначены для разбиения на слоги: в конце вы не можете остаться с нелогичным словом, верно? И есть (и должно быть!) Только один способ взломать слоги (или выбрать возможные точки переносов). Или я как-то смущен? –

2

Я думаю, его время для решения DCG push back. Нажатие назад используется во втором правиле разрыва // 1. Это отражает, что мы смотрим на четыре символа, но потребляют только два символа:

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 или в обратном направлении/2. Мы также поместили разрез, чтобы обрезать поиск, что можно сделать из-за символа catchall во втором правиле слогов // 1.

Вот несколько примеров работает:

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 

PS: В некоторых старых проектах стандартов этот метод DCG был называется «правый контекстом», и вместо глагола «толкающего спины», то глагол "prefixing" использовался. В более новом проекте стандарта это называется «semicontext», а вместо глагола «push back», используется «восстановление» глагола.

https://www.complang.tuwien.ac.at/ulrich/iso-prolog/dcgs/dcgsdraft-2015-11-10.pdf

Смежные вопросы