
% ex 8.1
ptoint(s(P), V) :-
	ptoint(P, Vp),
	V is Vp + 1.
ptoint(0, 0).


itop(0, 0).
itop(V, s(P)) :-
	Vp is V - 1,
	itop(Vp, P).

% Ex 8.3
listnumber(L) :- listnumber(L, 0).
listnumber([], _).
listnumber([H|T], N) :-
	Nn is N + 1,
	format('~p - ~p\n', [Nn,H]),
	listnumber(T, Nn).

% Ex 8.4
enumelems(L, Li, Enum) :- enumelems(L, Li, 1, Enum).
enumelems([], _, _, []).
enumelems([H|T], Li, I, Enum) :-
	member(I, Li),
	Enum = [H|Tsel],
	In is I + 1, 
	enumelems(T, Li, In, Tsel).
enumelems([_|T], Li, I, Enum) :-
	In is I + 1,
	enumelems(T, Li, In, Enum).

% Ex 8.5
isEven(N) :- X is N mod 2, X = 0.
isEven(_) :- fail.

% findallforP([1,2], isEven).
findallforP(L, P, Lp) :-
	findall(E, (member(E, L),
		    Test =.. [P,E],
		    Test),
		Lp).


% extras...

% return a list of indices that satisfies predicate P.
indices(L, P, Li) :- indices(L, P, Li, 1).
indices([], _, [], _).
indices([H|T], P, Li, I) :-
	Test =.. [P,H], Test,
	Li = [I|Tli],
	In is I + 1,
	indices(T, P, Tli, In).
indices([_|T], P, Li, I) :-
	In is I + 1,
	indices(T, P, Li, In).

% findall(X, T, L)

% \exists X \in S . F
exists(X, S, F) :-
	member(X, S), call( F ).


% \forall X \in S . F
% forall(X, S, F)
:- use_module(library(lists)).
:- use_module(library(sets)).

forall(X, S, F) :-
	list_to_set(S, Ss),
	findall(X, (
		    member(X, Ss),
		    call( F )
		   ), XsatF),
	list_to_set(XsatF, XsatFset),
	same_length(Ss, XsatFset).

% Ex 8.6.

start(1).
edge(1,2).
edge(2,2).
edge(2,3).
edge(3,4).
edge(3,5).

creach :-
	retractall(reached(_)),
	retractall(worklist(_)),
	start(Node),
	print(start(Node)), nl,
	assert(reached(Node)),
	assert(worklist(Node)),
	creach_loop.

creach_loop :-

	findall(X, reached(X), Reached),
	format('Reached = ~p\n', [Reached]),

	( findall(_, creach_step, [_|_]) ->
	  print('Step\n'),
	  creach_loop
	;
	  true
	).

creach_step :-
	retract(worklist(Node)),
	edge(Node, NodeN),
	\+ reached(NodeN),
	assert(reached(NodeN)),
	assert(worklist(NodeN)).
	