import java.util.*;
import java.io.*;
import java.util.ArrayList;
import org.jacop.core.*;
import org.jacop.constraints.*;
import org.jacop.search.*;
public class Hidato {
static Store store = new Store();
static IntVar[][] matrix = new IntVar[0][0];
static int hidato_width = 0;
static int hidato_height = 0;
static int max_value = 0;
public static void main (String[] args) {
String file_path = "";
if (args.length != 1) {
System.out.println("execute $ java -classpath .:jacop-4.1.0.jar Hidato <path_to_file>");
System.exit(-1);
} else {
file_path = args[0];
}
read_file(file_path);
/* Todos los elementos deben ser distintos*/
ArrayList<IntVar> all_elements = new ArrayList<IntVar>();
for(int i=0; i<hidato_height; i++){
for(int j=0; j<hidato_width; j++){
if (matrix[i][j]!=null){
all_elements.add(matrix[i][j]);
}
}
}
store.impose(new Alldiff(all_elements));
ArrayList<PrimitiveConstraint> computed_cells;
for(int i=0; i<hidato_height; i++){
for (int j=0; j<hidato_width; j++) {
if(matrix[i][j]!=null){
/*se comprueban todas las casillas adyacentes a cada posicion*/
computed_cells = new ArrayList<PrimitiveConstraint>();
for(int n=i-1; n<=i+1; n++){
for(int m=j-1; m<=j+1; m++){
if(!(n<0 || m<0 || n>=hidato_height || m>=hidato_width) && matrix[n][m]!=null){ /*casilla adyacente dentro de los limites de la matriz y distinto de null*/
if(matrix[i][j].value()!=max_value && (i!=n || m!=j)){ /*no comprobamos para la casilla central ni para la ultima casilla*/
computed_cells.add(new XplusCeqZ(matrix[i][j], 1, matrix[n][m])); /*restriccion de que la casilla adyacente tenga valor+1 que la central*/
}
}
}
}
if (computed_cells.size() > 0) {
Collections.shuffle(computed_cells);
store.impose(new Or(computed_cells));/*al menos una de las restricciones de las casillas adyacentes se debe cumplir*/
}
}
}
}
/* Quitamos los nulls y pasamos a array la matriz*/
IntVar[] array_from_matrix = new IntVar[max_value];
int l = 0;
for(int i=0; i<hidato_height; i++){
for(int j=0; j<hidato_width; j++){
if(matrix[i][j] != null){
array_from_matrix[l] = matrix[i][j];
l++;
}
}
}
Search<IntVar> label = new DepthFirstSearch<IntVar>();
SelectChoicePoint<IntVar> select = new SimpleSelect<IntVar>(array_from_matrix, new SmallestDomain<IntVar>(),
new IndomainMin<IntVar>());
Boolean result = label.labeling(store, select);
if (result) {
for(int i=0; i<hidato_height; i++){
for(int j=0; j<hidato_width; j++){
System.out.print(((matrix[i][j]==null)?"#":matrix[i][j].value()) + "\t");
}
System.out.println();
}
} else{
System.out.println("Error");
}
}
public static void read_file(String file_path){
int i = 0;
File file = new File(file_path);
BufferedReader reader = null;
String[] headers;
hidato_width = 0;
hidato_height = 0;
Integer[][] step_matrix = new Integer[0][0];
try {
reader = new BufferedReader(new FileReader(file));
String text = null;
while ((text = reader.readLine()) != null) {
if(i==0){
headers = text.split(" ");
hidato_width = Integer.parseInt(headers[0]);
hidato_height = Integer.parseInt(headers[1]);
step_matrix = new Integer[hidato_width][hidato_height];
text = reader.readLine();
}
String[] raw_line = text.split(" ");
for(int j=0; j<hidato_width; j++){
String letter = raw_line[j];
if(letter.equals("#")){
step_matrix[i][j] = null;
}else if (letter.equals("_")){
step_matrix[i][j] = 0;
}else{
step_matrix[i][j] = Integer.parseInt(letter);
if(Integer.parseInt(letter)>max_value){
max_value = Integer.parseInt(letter);
}
}
}
++i;
}
/* Escribir sobre la matrix de IntVar*/
matrix = new IntVar[hidato_width][hidato_height];
for(i=0; i<hidato_height; i++){
for(int j=0; j<hidato_width; j++){
if (step_matrix[i][j]==null){
matrix[i][j] = null;
} else if (step_matrix[i][j]==0){
matrix[i][j] = new IntVar(store, 1, max_value);
} else{
matrix[i][j] = new IntVar(store, step_matrix[i][j], step_matrix[i][j]);
}
}
}
} catch (FileNotFoundException e) {
System.out.println("File not found.");
System.exit(-1);
} catch (IOException e) {
System.out.println("Unknown error.");
System.exit(-1);
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
System.out.println("Unknown error.");
System.exit(-1);
}
}
}
}