2014-11-22 2 views
4

Я хотел бы разбить список слов, разделенных целыми числами, в список списков.Пролог: Разделить список на целое число в списке списков

Пример запроса и ожидаемый результат:

?- separatewords([h,e,l,l,o,1,o,v,e,r,3,t,h,e,r,e], X). 
X = [[h,e,l,l,o],[o,v,e,r],[t,h,e,r,e]]. 

следующие вещи, которые я уже достигнутые Нарезка список в один список до первого целого числа и один после первого целого:

Пример запроса с результатом :

?- take1word([h,e,l,l,o,1,o,v,e,r,3,t,h,e,r,e], X, Y). 
X = [h,e,l,l,o], Y = [o,v,e,r,3,t,h,e,r,e].     % OK 

Мой код:

take1word([H|T],[],T) :- 
    integer(H). 
take1word([H|T],[H|Hs],Y) :- 
    ( float(H), take1word(T,Hs,Y) 
    ; atom(H), take1word(T,Hs,Y) 
    ). 

Для разделения слов мой код выглядит следующим образом:

separatewords([],[]). 
separatewords([H|T],L) :- separatewords(T,[take1word([H|T],)|L]). 

Это только дать мне false как результат, но я не знаю, что я делаю неправильно.

ответ

2

У вас есть проблема с take1word/3: она займет слово, если в списке есть целое число, но последнее слово не займет. Вам нужно добавить еще один базовый пункт к нему:

take1word([], [], []). 
take1word([H|T],[],T) :- integer(H). 
take1word([H|T],[H|Hs],Y) :- float(H), take1word(T,Hs,Y); atom(H), take1word(T,Hs,Y). 

Теперь ваш separatewords/2 будет работать:

separatewords([],[]). 
separatewords(L, [W|T]) :- take1word(L,W,R), separatewords(R,T). 

Demo.

+0

Это сработало - спасибо! –

2

Вот как вы могли бы перейти в логически чистой моды.

Использовать splitlistIf/3 в тандеме с тестовым предикатом типа reified integer_t/2!

integer_t(X,Truth) :- integer(X), !, Truth = true. 
integer_t(X,Truth) :- nonvar(X), !, Truth = false. 
integer_t(X,true) :- freeze(X, integer(X)). 
integer_t(X,false) :- freeze(X,\+integer(X)). 

Посмотрим на них как в действии!

 
?- Xs=[ h,e,l,l,o,1,o,v,e,r,3,t,h,e,r,e ], splitlistIf(integer_truth,Xs,Yss). 
Xs = [ h,e,l,l,o,1,o,v,e,r,3,t,h,e,r,e ], 
Yss = [[h,e,l,l,o],[o,v,e,r],[t,h,e,r,e]]. % succeeds deterministically 

Поскольку реализация является монотонной, ее можно безопасно использовать, когда мы работаем с неземными условиями.

Рассмотрите следующие два логически эквивалентных запроса: в процедуре они различаются в отношении создания элементов в Xs на момент, когда цель splitListIf(integer_t,Xs,Yss) доказана.

 
?- Xs = [_,_,_,_,_], Xs = [a,b,0,b,a], splitlistIf(integer_t,Xs,Yss). 
Xs = [a,b,0,b,a], Yss = [[a,b],[b,a]].  % succeeds deterministically 

?- Xs = [_,_,_,_,_], splitlistIf(integer_t,Xs,Yss), Xs = [a,b,0,b,a]. 
    Xs = [a,b,0,b,a], Yss = [[a,b],[b,a]] % succeeds leaving behind choicepoint 
; false. 

Реализация достаточно умен, чтобы оставить позади точки (точки) выбора только при необходимости.

+0

Является ли 'isInteger' хорошим именем? – false

+0

[Соответствует] (http://stackoverflow.com/questions/27306453/safer-type-tests-in-prolog) для поиска имени. – false

+0

CamelCase не очень Prolog-ish. 'int' не является типом. 'Integer_truth/2'. Ссылаться на состояние экземпляра ('Nonvar') не нужно: реализация без ограничений корректно создала бы ошибку создания. – false

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