/*

  For more information about this file, see 
  "Choco: Constraint Programming i Java"
  http://www.hakank.org/webblogg/archives/001113.html
  



  The Seseman Convent problem.

  See 
   <a href="http://www.hakank.org/webblogg/archives/001084.html">Sesemans matematiska klosterproblem samt lite Constraint Logic Programming</a> for explanation.
    
   A more general CGI-program:
    http://www.hakank.org/seseman/seseman.cgi


  Note: In the standard distribution of Choco only 5 solution is printed.

  You can change the number of solutions to print by altering the 
  following line in AbstractSolver.java:

     public int maxNbSolutionStored = 5;

  e.g. to
     public int maxNbSolutionStored = 500;

  Then recompile the source code.

*/
import choco.Problem;
import choco.AbstractProblem.*;
import choco.Problem.*;
import choco.Solver.*;
import choco.Solver;
import choco.*;
import choco.integer.IntDomainVar;
import java.util.*;


public class Seseman {
    
    public static void main(String[] args) {
        new Seseman().puzzle();
    }

    
    public void puzzle () {

        // start = 0: allow empty rooms
        // start = 1: do not allow empty rooms
        int start = 1;

        Problem pb = new Problem();
        
        IntDomainVar A = pb.makeEnumIntVar("A", start, 9);
        IntDomainVar B = pb.makeEnumIntVar("B", start, 9);
        IntDomainVar C = pb.makeEnumIntVar("C", start, 9);
        IntDomainVar D = pb.makeEnumIntVar("D", start, 9);
        IntDomainVar E = pb.makeEnumIntVar("E", start, 9);
        IntDomainVar F = pb.makeEnumIntVar("F", start, 9);
        IntDomainVar G = pb.makeEnumIntVar("G", start, 9);
        IntDomainVar H = pb.makeEnumIntVar("H", start, 9);
        IntDomainVar[] letters = {A,B,C,D,E,F,G,H};

        // Total: Sum of all numbers
        IntDomainVar Total = pb.makeEnumIntVar("Total", 24, 24);
        // RowSum: The row sum
        IntDomainVar RowSum = pb.makeEnumIntVar("RowSum", 9, 9);


        // constraints in ECLiPSe
        /*
          LD :: [FirstNum..9],
          
          A+B+C #= Rowsum,
          A+D+F #= Rowsum,
          C+E+H #= Rowsum,
          F+G+H #= Rowsum,
          
          A+B+C+D+E+F+G+H #= Total,

         */

        pb.post(pb.eq(pb.plus(A, pb.plus(B, C)), RowSum));
        pb.post(pb.eq(pb.plus(A, pb.plus(D, F)), RowSum));
        pb.post(pb.eq(pb.plus(C, pb.plus(E, H)), RowSum));
        pb.post(pb.eq(pb.plus(F, pb.plus(G, H)), RowSum));

        // Total
        pb.post(pb.eq(pb.sum(letters), Total));


        pb.solve(true); // true: all solutions

        Solver s = pb.getSolver();
        
        System.out.println("Feasible: " + pb.isFeasible());
        System.out.println("Number of solutions: " + s.getSearchSolver().solutions.size());
        System.out.println("nbSol: " + s.getNbSolutions());
        
        // print all solutions
        for (int sol = 0; sol < s.getSearchSolver().solutions.size(); sol++) {
          Solution ss = (Solution) s.getSearchSolver().solutions.get(sol);
          System.out.println("Solution:\n");
          
          System.out.println("" + ss.getValue(0) + " " + ss.getValue(1) + " " + ss.getValue(2));
          System.out.println("" + ss.getValue(3) + " _ " + ss.getValue(4));
          System.out.println("" + ss.getValue(5) + " " + ss.getValue(6) + " " + ss.getValue(7));
          System.out.println("Total: " + ss.getValue(8) + " RowSum: " + ss.getValue(9));
        }


    } // end puzzle
  
  
} // end class
