Sudoku Solver in CPLEX - java

I am trying to solve a Sudoku program that I created.
This is the Objective Function
IloNumExpr numExpr = cplex.linearNumExpr();
cplex.addMaximize(numExpr);
What I am trying to do is to add to this either a constraint or new objective function that will allow for the four corner points in the 9x9 Sudoku matrix have special preference in the order of 5 > 7 > 4 > 6 > 8 > 2 > 3 > 9 > 1
Any ideas on what mathematical formulation is needed to complete this?

You'd impose the preference order by adding elements to your Objective Function.
Let's say you have variables of the type
choose[row][col][digit]
If choose[2][3][8] = 1 it means that the square (2,3) has the value 8.
The four corners are:
1,1; 1,9;
9,1; 9,9
Essentially, you need to add the following to your existing objective function.
9 x choose[1][1][5] + 8 x choose[1][1][7] + 7 x choose[1][1][4] + ... + 2 x choose[1][1][9] + 1 x choose[1][1][1]
9 x choose[1][9][5] + 8 x choose[1][9][7] + 7 x choose[1][9][4] + ... + 2 x choose[1][9][9] + 1 x choose[1][9][1]
9 x choose[9][1][5] + 8 x choose[9][1][7] + 7 x choose[9][1][4] + ... + 2 x choose[9][1][9] + 1 x choose[9][1][1]
9 x choose[9][9][5] + 8 x choose[9][9][7] + 7 x choose[9][9][4] + ... + 2 x choose[9][1][9] + 1 x choose[9][9][1]
In CPLEX
// Preference order: 5 > 7 > 4 > 6 > 8 > 2 > 3 > 9 > 1
int[] preferenceOrder;
preferenceOrder[1] = 9;
preferenceOrder[2] = 8;
preferenceOrder[8] = 2;
preferenceOrder[9] = 1;
cplex.addMaximize(cplex.scalProd(preferenceOrder, choose));
Why this works?
The CPLEX Solver tries to maximize the value of the obj function. All else being equal, it will first try to make choose[1][1][5] to be 1, and will next try to make it 7 and so on.

Related

For-loop output explanation needed?

I need an explanation of how the output prints 9(S), 7(S), 5(S) and 3(S).
10 > 3 is correct and goes to y 1 <= 2 which is correct so 2 x 10 - 2 = 18 but the output prints 9. I don't understand the logic here. Why does it print 9(s) instead of 18(s)?
public class Q2{
public static void main(String args[]) {
int x,y;
for(x= 10; x > 3; x = x - 2) {
for(y = 1; y <= 2 * x - 2; y = y + 2)
System.out.print("S");
System.out.print("\n");
}
}
}
Its correct Y <= 18 , but you are incrementing Y by 2, so it gets printed 9 times.
To understand, write down on a piece of paper what the values of your variables will be.
First, write down the values of x:
x: 10 8 6 4
Next, write down the calculated upper boundary value for y, i.e. the result of expression 2 * x - 2:
x : 10 8 6 4
yMax: 18 14 10 6
Last, write down the values of y:
x : 10 8 6 4
yMax: 18 14 10 6
y : 1 1 1 1
3 3 3 3
5 5 5 5
7 7 7
9 9 9
11 11
13 13
15
17
Finally, count the number of y values for each x value, i.e. the number of times S is printed:
x : 10 8 6 4
count: 9 7 5 3
Then realize that the code would have been much easier to understand if it had just been written like this:
for (int count = 9; count >= 3; count -= 2) {
for (int i = 0; i < count; i++) {
System.out.println("S");
}
}
Of course, that wouldn't have taught you what they were trying to teach you, which is:
Conclusion: If you don't understand what the code is doing, follow the logic step by step, and write down what it is doing.

Calculating Manhattan Distance within a 2d array

I am writing a program to solve an nxn 8 puzzle problem. I'm having difficulty with my Manhattan calculation function being off by two from the puzzle I'm testing my program with. This will eventually be expanded to use the A* pathfinding algorithm, but I'm not there yet.
Here is my function(which is based on the initial state of the board and not taking into account the amount of moves taken so far):
// sum of Manhattan distances between blocks and goal
public int Manhattan() // i don't think this is right yet - check with vince/thomas
{
int distance = 0;
// generate goal board
int[][] goal = GoalBoard(N);
// iterate through the blocks and check to see how far they are from where they should be in the goal array
for(int row=0; row<N; row++){
for(int column=0; column<N; column++){
if(blocks[row][column] == 0)
continue;
else
distance += Math.abs(blocks[row][column]) + Math.abs(goal[row][column]);
}
}
distance = (int) Math.sqrt(distance);
return distance; // temp
}
This is the example I'm working off of:
8 1 3 1 2 3 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
4 2 4 5 6 ---------------------- ----------------------
7 6 5 7 8 1 1 0 0 1 1 0 1 1 2 0 0 2 2 0 3
initial goal Hamming = 5 + 0 Manhattan = 10 + 0
My Hamming calculation is correct and returns 5, but my Manhattan returns 8 instead of 10. What am I doing wrong?
This is the output of my program:
Size: 3
Initial Puzzle:
8 1 3
4 0 2
7 6 5
Is goal board: false
Goal Array:
1 2 3
4 5 6
7 8 0
Hamming: 5
Manhatten distance: 8
Inversions: 12
Solvable: true
The error lies in the update of the distance.
In writing distance += Math.abs(blocks[row][column]) + Math.abs(goal[row][column]); you add all contents of the cells of initial and goal. Only one excluded in initial and goal is the cell with same coordinates as 0 in initial.
In your example this gives 2 times sum from 0 to 8 minus 5. 2 * 36 -8 = 64. Then you take the square which is 8.
Manhattan - as described by Wiktionary is calculated by distance in rows plus distance in columns.
Your algorithm must lock like (beware, pseudocode ahead!)
for (cell : cells) {
goalCell = findGoalcell(cell.row, cell.col);
distance += abs(cell.row - goalCell.row);
distance += abs(cell.col - goalCell.col);
}
And don't take the square root.

Addition in field with finite int elements?

I need to write a function (in Java) which has the following input:
int amountFieldElements
int summandOne
int summandTwo
amountFieldElement describes the amount of int numbers in a range starting from 1 (e.g. 1, 2, 3, 4 or just 1). summandOne is a int from this range, summandTwo can be any non-negative int.
The function has to add summandTwo to summandOne. If the result is bigger then amountFieldElement, it has to start over from 1.
I tried to simply use modulo: (summandOne + summandTwo) % amountFieldElements
But this is often wrong, e.g. (3 + 1) % 4 = 0 but I'd need it to be 4.
Example: If amountFieldElements = 4:
2 + 2 = 4 would stay as 4
3 + 2 = 5 would become 1
4 + 2 = 6 would become 2 etc
or for amountFieldElements = 1
1 + 0 = 1 would stay as 1
1 + 1 = 2 would also be 1
-> any result would be 1 here
something like this will work:
int result = (summandOne + summandTwo) % amountFieldElements;
if (result == 0) result = amountFieldElements;
another method, shorter but harder to understand is:
int result = (summandOne + summandTwo - 1) % amountFieldElements + 1;

Printing out a multiplication table

I'm going through the Java Tutorial on HackerRank using Java 8. The goal is to print out a multiplication table of 2 from 1 - 10.
Here is what I came up with
public static void main(String[] args) {
int x = 2;
int y = 0;
int z;
while (y < 10) {
z = x * y;
y++;
System.out.println(x + " x " + y + " = " + z);
}
Here is the output I get from the code above
2 x 1 = 0
2 x 2 = 2
2 x 3 = 4
2 x 4 = 6
2 x 5 = 8
2 x 6 = 10
2 x 7 = 12
2 x 8 = 14
2 x 9 = 16
2 x 10 = 18
I've also tried while <= 10 instead of while < 10 as shown in my code above and for that my result was:
2 x 1 = 0
2 x 2 = 2
2 x 3 = 4
2 x 4 = 6
2 x 5 = 8
2 x 6 = 10
2 x 7 = 12
2 x 8 = 14
2 x 9 = 16
2 x 10 = 18
2 x 11 = 20
Neither of this outputs is what I'm looking for. Logically I am confident my code makes sense and should work so I'm looking for someone to give me tips as to something I may have missed or maybe I've made a mistake and I'm not aware of it. I am not looking for the code to the right answer, but rather advice and/or pointers which will allow to come up with a working solution on my own.
Start your y value at 1
Don't increment your y value until after the print statement
public static void main(String[] args) {
int x = 2;
int y = 1; //starts at 1
int z;
while (y < 10) {
z = x * y;
System.out.println(x + " x " + y + " = " + z);
y++; // increment y after the print statement
}
}
Assign value of y = 1 and increment it after your system.out.println();

Determining all values that are equal & next to one another in a 2D array

I'm new to stackoverflow as well as programming so pardon me if I ask this question poorly.
So say I have a 2-D array with integer values from 1 through 4. It might look something like this:
3 3 3 1 3 1 3 1 2 1
1 3 1 3 3 1 1 1 1 1
1 4 3 3 1 3 3 4 3 4
1 4 1 1 3 3 1 4 2 4
1 1 1 4 1 3 3 1 1 3
1 2 3 3 3 3 3 3 1 1
4 1 4 3 3 2 1 1 4 1
1 3 3 3 4 1 4 2 2 3
Let me rewrite it so that I can isolate a part of the array I want us to observe:
x x x x x x x x x x
x x x x x x x x x x
x x x x x 3 3 x x x
x x x x 3 3 x x x x
x x x x x 3 3 x x x
x x 3 3 3 3 3 3 x x
x x x 3 3 x x x x x
x 3 3 3 x x x x x x
We see that the 3's shown here are not only all equal in value but also directly "next to" one another and are all "connected".
I have 4 methods that determine whether or not the space to the right, left, top, or bottom of a space in the array is equal to a given start position:
boolean isEqualRight(int row, int column) {
return array[row][column] == array[row][column + 1];
}
boolean isEqualLeft(int row, int column) {
return array[row][column] == array[row][column - 1];
}
boolean isEqualUp(int row, int column) {
return array[row][column] == array[row - 1][column];
}
boolean isEqualDown(int row, int column) {
return array[row][column] == array[row + 1][column];
}
But, even if I know if a position in the array is equal and next to a start position, I can't think of a solution to determine all of the positions in the array that are equal and connected to the start.
I tried developing a loop that would cycle through a space next to a starting 3, determine if it is next and equal to it, and if so then do the same for the 3 that is next to it, and so on, and so on. But I faced an issue when the 3's started branching. Any thoughts?
This is a standard problem in computer graphics. The algorithm is called Flood Fill and is covered in detail in Wikipedia.
There are also many Java implementations out there if you wanted to study one (just google).
Your methods seem correct but you should add come code to catch any possible IndexOutOfBoundErrors. For example if you take the first element in your array and check up or left you will get an IndexOutOfBound Error as it will reference an element that does not exist, this goes for all boundary elements. This will prevent your code from running efficiently.
Just something to always consider when dealing with arrays.

Categories