shuffle([],[]).
shuffle([H|T], [One|Rest]) :- 
    oneLess([H|T], One, Less), 
    shuffle(Less,Rest).

oneLess(L0,Pruned,L) :-
    length(L0,N0),
    N is random(N0),
    oneLess1(N,L0,Pruned,L).

oneLess1(0,  [H|T],H,T).
oneLess1(N0, [H|T],Out, [H|Rest]) :-
    N0 > 0,
    N is N0 - 1,
    oneLess1(N,T,Out,Rest).

somethingIwrote(X) :- 
	nonvar(X), 
	not(number(X)),
	callable(X),
	not(current_arithmetic_function(X)),
	not(builtin(X)) .

builtin(X) :- predicate_property(X,built_in).

walker1(N,N) :- number(N).
walker1(In,Out) :-
	nonvar(In),
	In =.. [H1,H2|T],
	member(Next,[H1,H2|T]),
	walker1(Next,Out).
walker1(In,Out) :-
	somethingIwrote(In),
	clause(In,Body),
	walker1(Body,Out).

walker2(Term,Found) :-
	walker2(Term,[],Found).

walker2(N,_,N) :- number(N).
walker2(In,Visited,Out) :-
	nonvar(In),
	In =.. [H1,H2|T],
	member(Next,[H1,H2|T]),
	walker2(Next,Visited,Out).
walker2(In,Visited,Out) :-
	somethingIwrote(In),
	functor(In,F,A),
	not(member(F/A,Visited)),
	clause(In,Body),
	walker2(Body,[F/A|Visited],Out).


walker3(Goal,Term,Found) :-
	walker3(Goal,Term,[],Found).

walker3(Goal,Term,_,Term) :- call(Goal,Term).
walker3(Goal,In,Visited,Out) :-
	nonvar(In),
	In =.. [H1,H2|T],
	member(Next,[H1,H2|T]),
	walker3(Goal,Next,Visited,Out).
walker3(Goal,In,Visited,Out) :-
	somethingIwrote(In),
	functor(In,F,A),
	not(member(F/A,Visited)),
	clause(In,Body),
	walker3(Goal,Body,[F/A|Visited],Out).

add(N,X,Y) :-number(X), Y is X + N.

walker4(Goal,Term,Found) :-
	walker4(Goal,Term,[],Found).

walker4(Goal,Term,_,Out) :- call(Goal,Term,Out).
walker4(Goal,In,Visited,Out) :-
	nonvar(In),
	In =.. [H1,H2|T],
	member(Next,[H1,H2|T]),
	walker4(Goal,Next,Visited,Out).
walker4(Goal,In,Visited,Out) :-
	somethingIwrote(In),
	functor(In,F,A),
	not(member(F/A,Visited)),
	clause(In,Body),
	walker4(Goal,Body,[F/A|Visited],Out).
