/**
  *
  * The Seseman's Convent Problem in JaCoP.
  * 
  * Given the following matrix:
  *  
  *    A  B  C 
  *    D  _  E
  *    F  G  H
  *
  * calculate the following constraints:
  * 
  *   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
  *  
  *
  * For more information about this problem:
  * - Swedish blog post with a fuller description of the problem:
  *   "Sesemans matematiska klosterproblem samt lite Constraint Logic Programming"
  *   http://www.hakank.org/webblogg/archives/001084.html
  *
  * Compare with other (constraint programming) models of this problem:
  * - ECLiPSe: http://www.hakank.org/seseman/seseman.ecl
  * - Choco (version 1): http://www.hakank.org/constraints/Seseman.java
  * - MiniZinc solution 1: http://www.hakank.org/minizinc/seseman.mzn
  * - MiniZinc solution 2 (generalized): http://www.hakank.org/minizinc/seseman2.mzn
  * - Python (with the package constraint): http://www.hakank.org/seseman/seseman.py
  * - Matlab: The comments at http://www.hakank.org/webblogg/archives/001084.html
  *
  * A CGI-program which uses the ECLiPSe program mentioned above
  *   http://www.hakank.org/seseman/seseman.cgi
  *
  *  
  *
  * JaCoP Model by Hakan Kjellerstrand (hakank@bonetmail.com)
  * Also see http://www.hakank.org/JaCoP/
  *  
  */

import JaCoP.constraints.*;
import JaCoP.core.*;
import JaCoP.search.*;

public class Seseman {

    public static void main(String args[]) {
 
        Store store = new Store();
        
        boolean printAll = true; // print all solutions

        // int start = 0; // allow empty room
        int start = 1; // don't allow empty room
        
        // 0..9: allow empty rooms 1..9: don't allow empty rooms
        IntVar A = new IntVar(store, "A", start, 9);
        IntVar B = new IntVar(store, "B", start, 9);
        IntVar C = new IntVar(store, "C", start, 9);
        IntVar D = new IntVar(store, "D", start, 9);
        IntVar E = new IntVar(store, "E", start, 9);
        IntVar F = new IntVar(store, "F", start, 9);
        IntVar G = new IntVar(store, "G", start, 9);
        IntVar H = new IntVar(store, "H", start, 9);
        IntVar[] digits = {A,B,C,D,E,F,G,H};

        IntVar Total = new IntVar(store, "Total", 26, 36);
        IntVar RowSum = new IntVar(store, "Rowsum", 9, 9);

        // The rowsums
        store.impose(new Sum(new IntVar[]{A,B,C}, RowSum));
        store.impose(new Sum(new IntVar[]{A,D,F}, RowSum));
        store.impose(new Sum(new IntVar[]{C,E,H}, RowSum));
        store.impose(new Sum(new IntVar[]{F,G,H}, RowSum));

        // The total
        store.impose(new Sum(digits, Total));

        // HakankUtil.toXML(store, -1, ".", "Seseman.xml");

        // define all the variables that should be printed in the solution
        IntVar[] allVars = {A,B,C,D,E,F,G,H,Total, RowSum};

        //
        // Search
        //
        SelectChoicePoint select = new SimpleSelect (allVars,
                                                     new MostConstrainedStatic(), 
                                                     new IndomainMin ());
        Search label = new DepthFirstSearch ();
        label.getSolutionListener().searchAll(true);
        label.getSolutionListener().recordSolutions(true);
        boolean result = label.labeling(store, select);    


        if(result) {

            if (printAll) {
                System.out.println("\nAll solutions: \n");
                // int[][] allSolutions = label.getSolutionListener().getSolutions();
                int numSolutions = label.getSolutionListener().solutionsNo();
                System.out.println("Number of Solutions: " + numSolutions);
                for(int s = 1; s <= numSolutions; s++) {
                    Domain [] res = label.getSolutionListener().getSolution(s);
                    int len = res.length;
                    System.out.println("Solution #:" + s + " Total: " + res[8] + " RowSum: " + res[9]);
                    System.out.println(res[0] + " " + res[1] + " " + res[2]);
                    System.out.println(res[3] + " " + "_ "             + res[4]);
                    System.out.println(res[5] + " " + res[6] + " " + res[7]);                
                System.out.println();
                }
                
            } else {
                
              System.out.println("store: " + store);
           
              // The last solution
              System.out.println("Solution found.");
              System.out.println(A.value() + " " + B.value() + " " + C.value());
              System.out.println(D.value() + " " + "_ "             + E.value());
              System.out.println(F.value() + " " + G.value() + " " + H.value());
            }


        } // end if result

    } // end main

} // end class
