2014-10-18 3 views
3

мне нужно отфильтровать список [#,d,e,#,f,g] таким образом, что я получаю результат, как [[d,e],[f,g]],
я застрял при создании нового списка каждый раз, когда я сталкиваюсь с «#», есть ли способ сделать это? Я попытался код ниже,список фильтров в отдельные списки

filterL([],List) :-[]. 
filterL([Head|Tail],X) :- 
    ( Head \='#'-> 
     append(X,Head,List), 
     filterL(Tail,List) 
    ; filterL(Tail,X) 
    ). 
+0

'%' является комментарием, так что используйте кавычки, как '[ '%', д, e, '%', f, g] ' – false

+2

... иначе неясно, что означает ваша программа. «Список» в первом предложении не имеет никакого смысла. Вероятно, вам нужен предикат arity 3 not 2. В Prolog нет операторов возврата. – false

+1

@false он должен просто вернуть пустой список. – sand

ответ

4

Ваша проблема не очень хорошо определены. Разрешены ли пустые последовательности или нет? Должно быть [#] связано с [[],[]] (есть пустая последовательность до и после) или []? Вы говорите, что это должно быть []. Итак:

list_splitbyhash(Xs, Xss) :- 
    phrase(splitby(Xss,#), Xs). 

splitby([],_E) --> 
    []. 
splitby(Xss,E) --> 
    [E], 
    splitby(Xss,E). 
splitby([Xs|Xss],E) --> 
    {Xs = [_|_]}, 
    all_seq(dif(E),Xs), 
    splitby(Xss,E). 

all_seq(_, []) --> []. 
all_seq(C_1, [C|Cs]) --> 
    [C], 
    {call(C_1,C)}, 
    all_seq(C_1, Cs). 
3

Вот еще одна версия, которая использует еще более общий подход:

list_splitbyhash(Xs, Xss) :- 
    phrase(by_split(=(#), Xss), Xs). 

=(X,X,true). 
=(X,Y,false) :- dif(X,Y). 

by_split(_C_2, []) --> []. 
by_split(C_2, Xss) --> 
    [E], 
    {call(C_2,E,T)}, 
    ( { T = true }, 
     by_split(C_2, Xss) 
    | { T = false, Xss = [[E|Xs]|Xss1] }, 
     all_seq(callfalse(C_2),Xs), 
     el_or_nothing(C_2), 
     by_split(C_2, Xss1) 
    ). 

callfalse(C_2,E) :- 
    call(C_2,E,false). 

el_or_nothing(_) --> 
    call(nil). 
el_or_nothing(C_2), [E] --> 
    [E], 
    {call(C_2,E,true)}. 

nil([], []). 

С lambdas, это может быть выражено более компактно. Вместо

all_seq(callfalse(C_2),Xs) 

и определения для callfalse/3, теперь можно написать

all_seq(C_2+\F^call(C_2,F,false)) 
+1

Можно ли получить только одно решение из числа решений, созданных прологом-предикатом? Например, например: list_splitbyhash ([#, 1,2,3, #], X). дает только [[1,2,3]]. – sand

+0

Вы правы! Исправлено, даже если это уже не так хорошо, как раньше. – false

+0

Спасибо, мне было просто любопытно. – sand

2

с мета-предиката splitlistIf/3 и овеществленного предикату равенства (=)/3, задача под рукой становится один лайнер - - это эффективный и логически чистый!

?- splitlistIf(=(#),[#,d,e,#,f,g],Xs). 
Xs = [[d,e],[f,g]].      % succeeds deterministically 

Поскольку код монотонной, логическая обоснованность обеспечивается даже при весьма общих запросов:

?- Xs = [A,B,C], splitlistIf(=(X),Xs,Yss). 
Xs = [A,B,C],  X=A ,  X=B ,  X=C , Yss = [  ] ; 
Xs = [A,B,C],  X=A ,  X=B , dif(X,C), Yss = [ [C]] ; 
Xs = [A,B,C],  X=A , dif(X,B),  X=C , Yss = [ [B] ] ; 
Xs = [A,B,C],  X=A , dif(X,B), dif(X,C), Yss = [ [B,C]] ; 
Xs = [A,B,C], dif(X,A),  X=B ,  X=C , Yss = [[A] ] ; 
Xs = [A,B,C], dif(X,A),  X=B , dif(X,C), Yss = [[A],[C]] ; 
Xs = [A,B,C], dif(X,A), dif(X,B),  X=C , Yss = [[A,B] ] ; 
Xs = [A,B,C], dif(X,A), dif(X,B), dif(X,C), Yss = [[A,B,C]]. 
Смежные вопросы