/*******************************************************************************
* OscaR is free software: you can redistribute it and/or modify
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* OscaR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser General Public License  for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with OscaR.
******************************************************************************/
package oscar.examples.cp.hakank

import oscar.cp.modeling._

import oscar.cp.core._
import scala.math._

/**

Magic square in Oscar.

@author Hakan Kjellerstrand hakank@gmail.com
http://www.hakank.org/oscar/

*/
object MagicSquare {

def main(args: Array[String]) {

val cp = CPSolver()

val n = if (args.length > 0) args(0).toInt else 4;
val num_to_show = if (args.length > 1) args(1).toInt else 0;

val n2 = n*n

println("n:" + n + " num_to_show: " + num_to_show)

//
// variables
//
val x = Array.fill(n,n)(CPIntVar(1 to n2)(cp))
val x_t = x.transpose

// val total = CPIntVar(cp, 1 to n*n*n)
val total = (n * (n*n + 1) / 2)

//
// constraints
//

cp.solve subjectTo {

// rows and columns
for(i <- 0 until n) {
}

// diagonals
cp.add(sum( for(i <- 0 until n) yield x(i)(i)) == total)
cp.add(sum( for(i <- 0 until n) yield x(i)(n-i-1) ) == total)

// symmetry breaking

} search {

binary(x.flatten.toSeq, _.size, _.min)

} onSolution {

println("\nSolution:\ntotal " + total)
for(i <- 0 until n) {
println(x(i).map(j=>"%3d".format(j.value)).mkString(""))
}
println()

}

println(cp.start(num_to_show))
}

}