s --> np(subject), vp. 
np(_) --> det, n.                   
np(X) --> pro(X). 
vp --> v, np(object). 
vp --> v. 
det --> [the].               
det --> [a]. 
n --> [woman].        
n --> [man].  
v --> [shoots]. 
pro(subject) --> [he]. 
pro(subject) --> [she]. 
pro(object) --> [him]. 
pro(object) --> [her]. 

prolog(Goal) :- once(look(Goal,How)), leap(How).

look(true,skip).
look((X,Y),and(X,Y)).
look(X,    call(X)) :- predicate_property(X,built_in).
look(X,    do(X,L)) :- clauses(X,L).

leap(skip).
leap(and(X,Y)) :- prolog(X), prolog(Y).
leap(call(X)) :- call(X).
leap(do(X,L)) :- member(X/Body,L), prolog(Body).

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).

clauses(X,Bodies) :-
	findall(X/Body, clause(X,Body), Bodies0),
	shuffle(Bodies0,Bodies).

demo :- forall(between(1,10,_), demo1).
s --> np(subject), vp. 
np(_) --> det, n.                   
np(X) --> pro(X). 
vp --> v, np(object). 
vp --> v. 
det --> [the].               
det --> [a]. 
n --> [woman].        
n --> [man].  
v --> [shoots]. 
pro(subject) --> [he]. 
pro(subject) --> [she]. 
pro(object) --> [him]. 
pro(object) --> [her]. 

prolog(Goal) :- once(look(Goal,How)), leap(How).

look(true,skip).
look((X,Y),and(X,Y)).
look(X,    call(X)) :- predicate_property(X,built_in).
look(X,    do(X)).

leap(skip).
leap(and(X,Y)) :- prolog(X), prolog(Y).
leap(call(X)) :- call(X).
leap(do(X)) :- clause(X,Body), prolog(Body).

demo :-
	s(Sentence1,[]),
	prolog(s(Sentence2,[])),
	format('1 : ~p\n2 : ~p\n',[Sentence1,Sentence2]).
	

demo1 :-
	s(Sentence1,[]),
	prolog(s(Sentence2,[])),
	format('\n1 : ~p\n2 : ~p\n',[Sentence1,Sentence2]).
	
