%Lab 6

%1
add_last(X,[],[X]).
add_last(X,[H|T],[H|T1]) :- add_last(X,T,T1).

%2 add one to all the numbers in a list
%?- add_one([1,3,5],L).
%L = [2, 4, 6] 

%?- add_one([1,a, 3, b, c, 5],L).
%L = [2, a, 4, b, c, 6] 

add_one([],[]).
add_one([H|T],[H1|T1]):-number(H), H1 is H+1, add_one(T,T1).
add_one([H|T],[H|T1]):-not(number(H)), add_one(T,T1).

%3 add one to the first number in a list

%?- add_one_first([a, 1,2,3],L).
%L = [a, 2, 2, 3] 

%?- add_one_first([a, b, 2, c, 5],L).
%L = [a, b, 3, c, 5] 

add_one_first([],[]).
add_one_first([H|T],[H1|T]):-number(H), H1 is H+1.
add_one_first([H|T],[H|T1]):-not(number(H)), add_one_first(T,T1).


%4
nested_member(X,[X|_]).
nested_member(X,[H|T]):- H\=X, not(is_list(H)), nested_member(X,T).
nested_member(X,[H|T]):- H\=X, is_list(H), 
                        (nested_member(X,H); nested_member(X,T)).


%5. Delete all occurrences of one element from a nested list (any level )

del(_, [], []).
del(X, [X | Tail], Tail_1) :- del(X, Tail, Tail_1).
del(X, [Y | Tail], [Y | Tail_1]) :-  X\=Y,  not(is_list(Y)), del(X, Tail, Tail_1).
del(X, [Y | Tail], [Z | Tail_1]) :-  X\=Y,  is_list(Y), 
                     del(X,Y,Z), del(X, Tail, Tail_1).
% \= needed to avoid multiple solutions whne there shoudl be only one


%6.  
% Count element occurrences.
%    countAll(L,E,N) holds if the list L contains E N times on any level.
%    Precondition: L and E are instantiated. L is a possibly nested list.

%?- countAll([1,2,1,[2,[1]],3],1,N).
%N = 3 

countAll([],_,0).
countAll([E|Rest],E,N) :- countAll(Rest,E,N1), N is N1 + 1.
countAll([X|Rest],E,N) :- X \= E, is_list(X),
                          countAll(X, E, N1),
                          countAll(Rest, E, N2), N is N1+N2.
countAll([X|Rest],E,N) :- X \= E, not(is_list(X)), 
countAll(Rest, E, N).


%*** is_list holds if the argument is a list.

%*** the predicate works if we skip X \= E and 
%not(is_list(X)). We get the first solution ok.  
%But when we ask for more solutions, we get some more,
%and we shouldn't.