% predykat deldiff(Element,List1,List2) usuwa z listy atomów "List1" wszystkie 
% elementy różne od "Element" i w efekcie powstaje lista "List2"

deldiff(_,[],[]).
deldiff(E,[E|T],T2):- !, deldiff(E,T,T2). % kiedy głowa jest taka sama jak element wskazny, to ją pomijamy
deldiff(E,[H|T],[H|T2]):- deldiff(E,T,T2). % a w przeciwnym przypadku, przpisujemy do listy wynikowej

%------------------------------------------------------------------------------------

% Predykat allafter(List1, Element, List2) podaje listę "List2" wszystkich
% elementów z listy atomów "List1", które znajdują się za atomem "Element"

allafter([E|T],E,T).
allafter([H|T],E,L):- allafter(T,E,L).

%------------------------------------------------------------------------------------

% Predykat occur(X,L,N) jest spełniony, gdy X występuje N razy na liście L

occur(_,[],0).
occur(X,[X|T],N):- occur(X,T,M), N is M+1. 
occur(X,[Y|T],N):- X\=Y, occur(X,T,N).

%------------------------------------------------------------------------------------

% Predykat adduplist(L,K,N) tworzy listę K z listy liczb L
% poprzez sumowanie kolejnych jej elementów 
% np. adduplist([1,4,2,7,12],K) daje wynik K=[1,5,7,14,26]

adduplist(L,K):- aux(L,K,0).
aux([],[],_).
aux([X|L],[Y|K],Z):- Y is X+Z, aux(L,K,Y).

%------------------------------------------------------------------------------------

% Predykat adjacent(X,Y,L) jest spełniony, gdy elementy X i Y są obok siebie na liście
% niezależnie od kolejności między nimi

adjacent(X,Y,[X,Y|T]).
adjacent(X,Y,[Y,X|T]).
adjacent(X,Y,[H|T]):- adjacent(X,Y,T).

%------------------------------------------------------------------------------------
% Predykat sumpair(L1,L2) generuje listę liczb L2 sumując parami liczby z listy L1
% np. sumpair([1,3,2,5,8,9],Z). daje Z=[4,7,17], bo 1+3=4, 2+5=7, 8+9=17
% Jeśli L1 jest nieparzystej długości, to L2 na końcu powinno mieć jest ostatni element.
% Jeżeli L1 jest pusta, to L2 też jest pusta.

sumpair([],[]).
sumpair([X],[X]).
sumpair([X,Y|T],[Z|T2]):- Z is X+Y, sumpair(T,T2).

%------------------------------------------------------------------------------------
% Generowanie listy kolejnych liczb całkowitych od zadanego N aż do wartości -1,
% przy czym liczby parzyste mają być dodatnie, a nieparzyste - ujemne
% predykat altersign(L,N), gdzie L lista wynikowa, N- wartość początkowa

altersign([],1):- !.
altersign([X|T],N):- M is N-1, altersign(T,M), D is 2*(M mod 2)-1, X is -D*M.

%------------------------------------------------------------------------------------
% Generowanie listy głów wszystkich list składowych listy wejściowej
% predykat heads(LList,HList) gdzie LList to lista list, zaś HList to lista ich głów
% Przykładowo dla: ?- heads([[a,b,c],[b,c,d,e],[c,d,f,g,h,i]],X). otrzymamy wynik X = [a,b,c]
% Jeśli jakakolwiek z list składowych listy wejściowej jest pusta, predykat nie jest spełniony.

heads([],[]).
heads([[H|_]|L],[H|T2]):- heads(L,T2).

%------------------------------------------------------------------------------------
% Predykat prepend(E,L1,L2) dodaje do każdej listy składowej listy L1 element E na jej początku 
% w wyniku czego otrzymujemy listę L2;
% przykładowo dla: ?- prepend(m,[[a],[b,c,d],[e,f]],X) mamy wynik: X=[[m,a],[m,b,c,d],[m,e,f]]
% Jeżeli L1 jest pusta, to L2 też powinna być pusta.

prepend(_,[],[]).
prepend(X,[H|L],[[X|H]|T2]):- prepend(X,L,T2).

%------------------------------------------------------------------------------------
% Predykat starts(A,Ch) jest spełniony, gdy atom A zaczyna się od znaku Ch

starts(A,Ch):- name(Ch,[Code]), name(A,[Code|_]).

%------------------------------------------------------------------------------------
% Przekształcanie angielskich rzeczowników regularnych w liczbę mnogą

plural(Noun,Pl):- name(Noun,NList), name(s,Cs), append(NList,Cs,L), name(Pl,L).

% Uwaga! Predykat systemowy 'append' odpowiada predykatowi 'conc' z wykładu!

%------------------------------------------------------------------------------------