:- seqex([plausible/2, plausible1/2, seqStrategy/2, seqSbps/4, partition/8,
	  createSub/16, split/3, split3/4]).


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.

split3(M, H1, H2, H3) :- H1 is M/3, M1 is M-H1, split(M1, H2, H3).
split3(M, H1, H2, H3) :- H2 is M/3, M1 is M-H2, split(M1, H1, H3), H1 =\= H2.
split3(M, H1, H2, H3) :- H3 is M/3, M1 is M-H3, split(M1, H1, H2), H1 =\= H3, 
								   H2 =\= H3.

partition(Normal, PossiblyHeavy, PossiblyLight, UnKnown, Weighings, 
	  ProbEq, ProbLeft, ProbRight ) :- 
	split3(PossiblyHeavy, H1, H2, H3),
	split3(PossiblyLight, L1, L2, L3),
	split3(UnKnown, U1, U2, U3),
	Weighings1 is Weighings -1,
	plausible(Weighings1, coins(0, H3, L3, U3)),
	N2 is H1+L1+U1 - H2+L2+U2,
	N2 >= 0,
	N3 is Normal - N2, N3 >= 0,
	createSub(Weighings1, 0, 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), 0) :- 
	PossiblyHeavy+ PossiblyLight+ UnKnown < 2.

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

seqStrategy(coins(Normal, PossiblyHeavy, PossiblyLight, UnKnown), Weighings) :-
	Weighings > 0,
	PossiblyHeavy+ PossiblyLight+ UnKnown > 3,
	split3(PossiblyHeavy, H1, H2, H3),
	split3(PossiblyLight, L1, L2, L3),
	split3(UnKnown, U1, U2, U3),
	Weighings1 is Weighings -1,
	plausible(Weighings1, coins(0, H3, L3, U3)),
	N2 is H1+L1+U1 - H2+L2+U2,
	N2 >= 0,
	N3 is Normal - N2, N3 >= 0,
	createSub(Weighings1, 0, H1, L1, U1, N2, H2, L2, U2, N3, H3, L3, U3,
		 ProbEq, ProbLeft, ProbRight ),
	seqSbps(Weighings1,ProbEq, ProbLeft, ProbRight).

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

strategy(coins(Normal, PossiblyHeavy, PossiblyLight, UnKnown), W) :- 
	PossiblyHeavy+ PossiblyLight+ UnKnown > 1,
	W < 3, 
	seqStrategy(coins(Normal, PossiblyHeavy, PossiblyLight, UnKnown), W).

strategy(coins(Normal, PossiblyHeavy, PossiblyLight, UnKnown), Weighings) :-
	Weighings > 2,
	PossiblyHeavy+ PossiblyLight+ UnKnown > 1, 	
	partition(Normal, PossiblyHeavy, PossiblyLight, UnKnown, Weighings,
		  ProbEq, ProbLeft, ProbRight),
	Weighings1 is Weighings - 1,
	sbps(Weighings1,ProbEq, ProbLeft, ProbRight).

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

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



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



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



