2014-09-05 8 views
1

Привет Я новичок в Прологе и пытается написать небольшую программу на Прологе, чтобы узнать его ....Проблема в Прологе Программирование

Я написал программу для удаления позиционного элемента означает удалить (Список, 2 , Ans) будут удалены все элементы позиции 2,4,6,8 .... из списка ... ниже моя логика

remove(L,N,Ans):- 
    length(L,LEN), 
    T1 is 1 mod N, 
    add(L,N,[],LEN,T1,Res). 

add(L,N,Ans,0,T,Ans). 
add([H|T],N,Ans,LEN,0,Res):- 
    LEN1 is LEN-1, 
    T1 is 1 mod N, 
    add(T,N,Ans,LEN1,T1,Res). 
add([H|T],N,Ans,LEN,T,Res):- 
    T =\= 0, LEN =\= 0, 
    LEN1 is LEN-1, 
    T1 is T1+1, 
    T2 is T1 mod N, 
    append([H],Ans,Result), 
    add(T,N,Result,LEN1,T2,Res). 

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

[trace] ?- remove([1,2,3,4,5,6,7,8],2,X). 
    Call: (6) remove([1, 2, 3, 4, 5, 6, 7, 8], 2, _G2941) ? creep 
    Call: (7) length([1, 2, 3, 4, 5, 6, 7, 8], _G3039) ? creep 
    Exit: (7) length([1, 2, 3, 4, 5, 6, 7, 8], 8) ? creep 
    Call: (7) _G3041 is 1 mod 2 ? creep 
    Exit: (7) 1 is 1 mod 2 ? creep 
    Call: (7) add([1, 2, 3, 4, 5, 6, 7, 8], 2, [], 8, 1, _G3046) ? creep 
    Fail: (7) add([1, 2, 3, 4, 5, 6, 7, 8], 2, [], 8, 1, _G3046) ? creep 
    Fail: (6) remove([1, 2, 3, 4, 5, 6, 7, 8], 2, _G2941) ? creep 
false. 

Кто-нибудь знает, где проблема?

+0

, но в этом случае последнее добавление будет выбрано путем объединения этого 1 с T. –

+1

'1 mod N' всегда' 1', если 'N> 1' не так ли? – lurker

+0

@ lurker Непонятно, когда при вызове Call: (7) добавьте ([1, 2, 3, 4, 5, 6, 7, 8], 2, [], 8, 1, _G3046)? ползучести ... почему он не справляется с этой целью или унифицирует это последним добавлением ...... –

ответ

1

Надеюсь, вы сможете найти свой путь в своем коде. Я думаю, что лучший способ изучить язык - это отладить его ... комментарий lurker уже поставил вас на правильный путь. Но я хочу показать, как использование встроенных функций может изменить вашу перспективу (это, конечно, верно для любого языка, а не только для Prolog).

remove(L,N,Ans) :- findall(E, (nth1(I,L,E), I mod N =\= 0), Ans). 

?- remove([1,2,3,4,5,6,7,8],2,X). 
X = [1, 3, 5, 7]. 

редактировать когда

Call: (7) add([1, 2, 3, 4, 5, 6, 7, 8], 2, [], 8, 1, _G3046) ? creep 

правило не могут быть согласованы, в частности, T не может быть списком и номер 1

add([H|T],N,Ans,LEN,T,Res):- 

, что сказал, я не уверен, как вы должны исправить код ...

+0

да ... это прекрасно, но я изучаю логику порлога ... и пытаюсь решить проблему со следующей ссылки http://www.ic.unicamp.br/~meidanis/courses/mc336/2009s2/prolog/problemas/ –

+0

'bagof/3' было бы более подходящим для такого решения, поскольку оно также обрабатывает переменные как и ожидалось. – false

+0

@ JatinKhurana: Конечно, вы правы. Обратите внимание, что я предлагаю в своем фрагменте выражение, которое может помочь вам исправить ваш код ... – CapelliC

1

Обычная пролог-идиома - это использование «хелперного» предиката, который фактически выполняет эту работу и несет один или несколько дополнительных аргументов, которые сохраняют состояние. В этом случае нам нужен счетчик для отслеживания нашей позиции в списке источников.

remove(Xs , N , Ys) :- 
    remove(Xs , 1 , N , Ys). % Note the additional argument (our counter) initialized to 1 

remove([]  , _ , _ , [] ) . % when we exhaust the source list, we're done. 
remove([X|Xs] , P , N , [X|Ys]) :- % otherwise, 
    P mod N =\= 0 ,     % - if the current position is NOT a multiple of N, 
    P1 is P+1 ,      % - we increment the position, 
    remove(Xs,P1,N,Ys)     % - and recurse down, adding the head of the list 
    .         % to the result. 
remove([_|Xs] , P , N , Ys ) :- % otherwise, 
    P mod N =:= 0 ,     % - if the current position is a multiple of N, 
    P1 is P1+1 ,      % - increment the position, 
    remove(Xs,P1,N1,Ys)    % - and recurse down, discarding the head of the list 
    .         % Easy! 

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

remove([] , _ , _ , []) .  % when we exhaust the source list, we're done. 
remove([X|Xs] , P , N , Ys) :- % otherwise, 
    keep_or_discard(X,P,N,Ys,Y1) , % - decided whether to keep or discard the current list head 
    P1 is P+1 ,      % - increment the counter 
    remove(Xs , P1 , N , Y1)  % - and recurse down. 
    . 

keep_or_discard(_ , P , N , Ys , Ys) :- % if P is a multiple of N 
    P mod N =:= 0 ,       % - discard X, 
    ! .          % - and eliminate the choice point. 
keep_or_discard(X , _ , _ , Ys , [X|Ys]) . % otherwise, we keep it. 

Некоторые народные невзлюбите использование разреза явно исключить выбор точек, поэтому в качестве альтернативы, мы можем сделать рефакторинг с помощью использования implication/if-then-else оператора Пролога :

remove([] , _ , _ , []) .  % when we exhaust the source list, we're done. 
remove([X|Xs] , P , N , Ys) :- % otherwise, 
    (P mod N =:= 0     % - if P is a multiple of N, 
    -> Y1 = Ys     % - then we discard the list head 
    ; [X|Y1] = Ys     % - otherwise, we add it to the result list 
) ,        % - and then ... 
    P1 is P+1 ,      % - increment the counter 
    remove(Xs , P1 , N , Y1)  % - and recurse down. 
    . 

ли любой из этих реорганизаций яснее, или проще понять, чем оригинал, конечно, личный выбор.

+0

это okkk ... но мой вопрос в том, почему он не объединяет добавление ([1, 2, 3, 4, 5, 6, 7, 8], 2, [], 8, 1, _G3046) до последнего добавить ... почему он дает ложную .... –

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