:- seqex([plausible/2, plausible1/2, printTree/4, between/3, pick/4, 
	 writeSpaces/1, seqStrategy/3, seqSbps/7, seqStrat1/10,
	createSub/16, split/3]).


split(M, H1, H2) :- H1 is M/2, H2 is M-H1.
split(M, H1, H2) :- H2 is M/2, H1 is M-H2, H1 =\= H2.

seqStrat1(Normal, PossiblyHeavy, PossiblyLight, UnKnown, Weighings, Left, 
		Right, ProbEq, ProbLeft, ProbRight ) :- 
/*	plausible(Weighings, coins(Normal, PossiblyHeavy, PossiblyLight, UnKnown)),*/
	CoinsUnWeighed = coins(0, H3, L3, U3),  
	between(0, PossiblyHeavy, H3), between(0,PossiblyLight, L3),
	between(0, UnKnown, U3),
	Weighings1 is Weighings -1,
	plausible(Weighings1, CoinsUnWeighed),
	Rest is (2*UnKnown +PossiblyHeavy +PossiblyLight - (2*U3 + H3 + L3))/2,
	plausible1(Weighings1, Rest),
	HRest is PossiblyHeavy - H3, split(HRest, H1, H2),
	LRest is PossiblyLight - L3, split(LRest, L1, L2),
	URest is UnKnown - U3, split(URest, U1, U2),
	LeftCount is H1+L1+U1, 
	N2 is LeftCount - H2+L2+U2,
	N2 >= 0,
	N3 is Normal - N2, N3 >= 0,
	N1 is 0, 
	Left = coins(0, H1, L1, U1),
	Right = coins(N2, H2, L2, U2),
	createSub(Weighings1, N1, H1, L1, U1, N2, H2, L2, U2, N3, H3, L3, U3,
		 ProbEq, ProbLeft, ProbRight ).

createSub(Weighings1, N1, H1, L1, U1, N2, H2, L2, U2, N3, H3, L3, U3,
	 ProbEq, ProbLeft, ProbRight ) :- 
/* Now, have to solve three subproblems for each of the 3 possible outcomes */
/* Check the plausibility of all the three subproblems before calling them */
/* If the pans are Equal, All weighed coins are normal. Suspect in remainder.*/

	N4 is N1+N2+N3 + H1+L1+U1 + H2+L2+U2,
	ProbEq = coins(N4, H3, L3, U3),
	plausible(Weighings1, ProbEq),

 /* If the Left pan was light, the UnWeighed ones are normal.
	The possibly_heavy on left and possibly_light on right are normal, But
	possibly_heavy on right and possibly_light on left are still suspect,
	and the unknowns on each side are possibly heavy/light */

	N5 is N1+N2+N3 	+ H3+L3+U3 /* Unweighed */ + H1 + L2,
	H5 is H2 + U2,
	L5 is L1 + U1,
	U5 is 0,
	ProbLeft = coins(N5, H5, L5, U5),
	plausible(Weighings1, ProbLeft),

 /* If the Right pan was light, the UnWeighed ones are normal.
	The possibly_heavy on right and possibly_light on left are normal, But
	The possibly_heavy on left and possibly_light on right are still suspect,
	and the unknowns on each side are possibly heavy/light */

	N6 is N1+N2+N3 	+ H3+L3+U3 /* Unweighed */ + H2 + L1,
	H6 is H1 + U1,
	L6 is L2 + U2,
	U6 is 0,
	ProbRight = coins(N6, H6, L6, U6),
	plausible(Weighings1, ProbRight).
/*
seqStrategy(coins(Normal, PossiblyHeavy, PossiblyLight, UnKnown), W, T) :- 
	 2 =:= 3.
*/
seqStrategy(coins(Normal, PossiblyHeavy, PossiblyLight, UnKnown), 0, s) :- 
	Total is  PossiblyHeavy+ PossiblyLight+ UnKnown, 
	Total < 2.

seqStrategy(coins(Normal, PossiblyHeavy, PossiblyLight, UnKnown), W, s) :- 
	W > 0,
	Total is  PossiblyHeavy+ PossiblyLight+ UnKnown, 
	Total < 4.

seqStrategy(coins(Normal, PossiblyHeavy, PossiblyLight, UnKnown), 
		Weighings, 
		t(weigh(Left,Right), Teq, TLeft, TRight) ) :-
	Weighings > 0,
	Total is  PossiblyHeavy+ PossiblyLight+ UnKnown, 
	Total > 3,
	seqStrat1(Normal, PossiblyHeavy, PossiblyLight, UnKnown, Weighings,
		Left, Right, ProbEq, ProbLeft, ProbRight),
	Weighings1 is Weighings - 1,
	seqSbps(Weighings1,ProbEq, ProbLeft, ProbRight, Teq, TLeft, TRight).

strategy(coins(Normal, PossiblyHeavy, PossiblyLight, UnKnown), W, s) :- 
	write(W), write([Normal, PossiblyHeavy, PossiblyLight, UnKnown]), nl,
	Total is  PossiblyHeavy+ PossiblyLight+ UnKnown, 
	Total < 2.

strategy(coins(Normal, PossiblyHeavy, PossiblyLight, UnKnown), W, T) :- 
	Total is  PossiblyHeavy+ PossiblyLight+ UnKnown, 
	Total >1,
	W < 4, 
	seqStrategy(coins(Normal, PossiblyHeavy, PossiblyLight, UnKnown), W, T).

strategy(coins(Normal, PossiblyHeavy, PossiblyLight, UnKnown), 
	 Weighings, s /*t(weigh(Left,Right), Teq, TLeft, TRight) */ ) :-
	Weighings > 3,
	Total is  PossiblyHeavy+ PossiblyLight+ UnKnown, 
	Total > 1,
	seqStrat1(Normal, PossiblyHeavy, PossiblyLight, UnKnown, Weighings,
		Left, Right, ProbEq, ProbLeft, ProbRight),
	Weighings1 is Weighings - 1,
	sbps(Weighings1,ProbEq, ProbLeft, ProbRight, Teq, TLeft, TRight).

seqSbps(Weighings1,coins(A1,B1,C1,D1), coins(A2,B2,C2,D2), coins(A3,B3,C3,D3), Teq, TLeft, TRight) :-
	seqStrategy(coins(A1,B1,C1,D1), Weighings1, Teq),
	seqStrategy(coins(A2,B2,C2,D2), Weighings1, TLeft),
	seqStrategy(coins(A3,B3,C3,D3), Weighings1, TRight).

sbps(Weighings1,coins(A1,B1,C1,D1), coins(A2,B2,C2,D2), coins(A3,B3,C3,D3), Teq, TLeft, TRight) :-
	( (strategy(coins(A1,B1,C1,D1), Weighings1, Teq) //
	   strategy(coins(A2,B2,C2,D2), Weighings1, TLeft)), null) //
	   strategy(coins(A3,B3,C3,D3), Weighings1, TRight).


between(M,N,M) :- N >= M.
between(M,N,X) :- N>M, M1 is M+1, between(M1,N,X).


pick(Size, coins(N1, H1, L1, U1), coins(N2, H2, L2, U2), 
	       coins(N3, H3, L3, U3)) :-
	between(0,N1,N2), between(0,H1,H2), between(0,L1,L2), 
	U2 is Size - (N2+H2+L2), U2 >= 0,between(0,U1, U2),
	N3 is N1-N2, H3 is H1-H2, L3 is L1-L2, U3 is U1-U2.


/* plausible(N,M) :- write(plaus(N,M)), nl, 2 =:= 3. */
plausible(W, coins(N,H,L,U)) :- 
	Possibilities is H+ L+ 2*U,
	plausible1(W, Possibilities).


/* plausible1(N,M) :- write(plaus1(N,M)), nl, 2 =:= 3. */

plausible1(0, MaybeFaulty) :-  MaybeFaulty < 2.
plausible1(1, MaybeFaulty) :-  MaybeFaulty < 4.
plausible1(Weighings, MaybeFaulty) :-  /* Would information theory allow it? */
				      /* Log MaybeFaulty wrt 3 */
	Weighings > 1,
	W1 is Weighings-1,
	M1 is (MaybeFaulty + 2) / 3,
	plausible1(W1,M1).


main(C,W) :- strategy(C,W,T). /* , printTree(W, 0, 'top', T).*/

printTree(W,Spaces, Symbol, T) :- 
	W < 1.

printTree(W,Spaces, Symbol, s) :- 
	W >0, 
	writeSpaces(Spaces), write(Symbol), write('--> '),
	write(done), nl.	 

printTree(W,Spaces, Symbol, t(weigh(coins(N1,H1,L1,U1),coins(N2,H2,L2,U2)), 
	    Teq, Tl, Tr) ) :-
	W>0,
	writeSpaces(Spaces), write(Symbol), write('--> '),
	 write([N1,H1,L1,U1]), write(':'), write([N2,H2,L2,U2]),nl,
	S2 is Spaces+1, W2 is W-1,
	printTree(W2,S2, ' = ', Teq),
	printTree(W2,S2, ' > ', Tl),
	printTree(W2,S2, ' < ', Tr).

writeSpaces(0).
writeSpaces(N) :- N>0, write('.....'), N1 is N-1, writeSpaces(N1).



/* ?- main(coins(1,0,0,39), 4), write(yes), nl. */
/* ?- main(coins(10,0,0,4), 2), write(yes), nl. */
?- main(coins(0,0,0,12), 3), write(yes), nl. 

