% *** Recursion  ***

member(X,[X|Y]).
member(X,[_|Y]):-member(X,Y).

% avoid Circular definition

parent(X,Y):- child(Y,X).
child(X,Y):- parent(Y,X).
parent(ahmed,ali).
child(ali,ahmed).

% avoid facts after rules. (left  resursion)                               +

person(adam).
person(X) :- person(Y), mother(X,Y).


% **** mapping ****

change(you ,i).
change(are, [am , not]).
change(french, arabic).
change(do, no).
change(X,X).  %very important

alter([],[]). %termination condition
alter([H|T],[X|Y]):- change(H,X), alter(T,Y).

% *** recursive comparison ***

fuel_consumed(bmw, [5.2, 10.6, 16.8]).
fuel_consumed(toyota, [5, 10.4, 16.1]).

prefer(Car1, Car2):-
fuel_consumed(Car1, X), fuel_consumed(Car2, Y),
always_better(X,Y).

%always_better([],[]). % trace, then relase the comment and trace again
always_better([A|X],[B|Y]):- A<B, always_better(X,Y).

% do i need to handle empty list [] in memeber recursion above? Why?

% *** Append ****       first we try to do it together


append([],L,L).
append([X|L1],L2,[X|L3]):-append(L1,L2,L3).

% the idea is that L3 constructed in backword style

% what about -? append(X,[b,c,d], [a,b,c,d] ).

% *** list length ***

%listlen([],0).
%listlen([X|L], N):- listlen(L,OldN),N is OldN+1.



% another method as you used to do it in C with accumulator
listlen(L,N):-lenacc(L,0,N).

lenacc([],A,A).
lenacc([H|L],A,N):- NewA is A+1, lenacc(L,NewA,N).

% Where does the N instantiated?

% ---------------------------------------Bicycle
basicpart(rim).
basicpart(spoke).
basicpart(rearframe).
basicpart(handles).
basicpart(gears).
basicpart(bolt).
basicpart(nut).
basicpart(fork).

assembly(bike, [wheel, wheel, frame]).
assembly(wheel, [spoke, rim, hub]).
assembly(frame, [rearframe, frontframe]).
assembly(frontframe, [fork, handles]).
assembly(hub, [gears, axle]).
assembly(axle, [bolt, nut]).


/*
partsof(X, [X]) :- basicpart(X).
partsof(X, P) :-
    assembly(X, Subparts),
    partsoflist(Subparts, P).  %is it possible to replace with partsof(Subparts, P). with out the need to parsoflist?

partsoflist([], []).
partsoflist([H|T], P) :-
    partsof(H, Hp),
    partsoflist(T, Tp),
   append(Hp, Tp, P).
 */
 
% **** with accumulator to remove the append clause*****

%/*
partsof(X, P) :- partsacc(X, [], P).

partsacc(X, A, [X|A]) :- basicpart(X).
partsacc(X, A, P) :-
    assembly(X, Subparts),
    partsacclist(Subparts, A, P).

partsacclist([], A, A).
partsacclist([H|T], A, P) :-
    partsacc(H, A, Hp),
   partsacclist(T, Hp, P).

   %   where does the append happen??????????

%*/

% *** solving the order problem with a hole
/*
partsof(X, P) :- partsacc(X, Gap, P), Gap = [].

partsacc(X, Gap, [X|Gap]) :- basicpart(X).
partsacc(X, Gap, P) :-
        assembly(X, Subparts),
        partsacclist(Subparts, Gap, P).

partsacclist([], Gap, Gap).
partsacclist([H|T], Gap, P) :-
        partsacc(H, Hgap, P),
        partsacclist(T, Gap, Hgap).
*/
