Optimizing N queens puzzle - java

I'm trying to solve the problem of positioning N queens on NxN board without row, column and diagonal conflicts. I use an algorithm with minimizing the conflicts. Firstly, on each column randomly a queen is positioned. After that, of all conflict queens randomly one is chosen and for her column are calculated the conflicts of each possible position. Then, the queen moves to the best position with min number of conflicts. It works, but it runs extremely slow. My goal is to make it run fast for 10000 queens. Would you, please, suggest me some improvements or maybe notice some mistakes in my logic?
Here is my code:
public class Queen {
int column;
int row;
int d1;
int d2;
public Queen(int column, int row, int d1, int d2) {
super();
this.column = column;
this.row = row;
this.d1 = d1;
this.d2 = d2;
}
#Override
public String toString() {
return "Queen [column=" + column + ", row=" + row + ", d1=" + d1
+ ", d2=" + d2 + "]";
}
#Override
public boolean equals(Object obj) {
return ((Queen)obj).column == this.column && ((Queen)obj).row == this.row;
}
}
And:
import java.util.HashSet;
import java.util.Random;
public class SolveQueens {
public static boolean printBoard = false;
public static int N = 100;
public static int maxSteps = 2000000;
public static int[] queens = new int[N];
public static Random random = new Random();
public static HashSet<Queen> q = new HashSet<Queen>();
public static HashSet rowConfl[] = new HashSet[N];
public static HashSet d1Confl[] = new HashSet[2*N - 1];
public static HashSet d2Confl[] = new HashSet[2*N - 1];
public static void init () {
int r;
rowConfl = new HashSet[N];
d1Confl = new HashSet[2*N - 1];
d2Confl = new HashSet[2*N - 1];
for (int i = 0; i < N; i++) {
r = random.nextInt(N);
queens[i] = r;
Queen k = new Queen(i, r, i + r, N - 1 + i - r);
q.add(k);
if (rowConfl[k.row] == null) {
rowConfl[k.row] = new HashSet<Queen>();
}
if (d1Confl[k.d1] == null) {
d1Confl[k.d1] = new HashSet<Queen>();
}
if (d2Confl[k.d2] == null) {
d2Confl[k.d2] = new HashSet<Queen>();
}
((HashSet<Queen>)rowConfl[k.row]).add(k);
((HashSet<Queen>)d1Confl[k.d1]).add(k);
((HashSet<Queen>)d2Confl[k.d2]).add(k);
}
}
public static void print () {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
System.out.print(queens[i] == j ? "♕ " : "◻◻◻ ");
}
System.out.println();
}
System.out.println();
}
public static boolean checkItLinear() {
Queen r = choseConflictQueen();
if (r == null) {
return true;
}
Queen newQ = findNewBestPosition(r);
q.remove(r);
q.add(newQ);
rowConfl[r.row].remove(r);
d1Confl[r.d1].remove(r);
d2Confl[r.d2].remove(r);
if (rowConfl[newQ.row] == null) {
rowConfl[newQ.row] = new HashSet<Queen>();
}
if (d1Confl[newQ.d1] == null) {
d1Confl[newQ.d1] = new HashSet<Queen>();
}
if (d2Confl[newQ.d2] == null) {
d2Confl[newQ.d2] = new HashSet<Queen>();
}
((HashSet<Queen>)rowConfl[newQ.row]).add(newQ);
((HashSet<Queen>)d1Confl[newQ.d1]).add(newQ);
((HashSet<Queen>)d2Confl[newQ.d2]).add(newQ);
queens[r.column] = newQ.row;
return false;
}
public static Queen choseConflictQueen () {
HashSet<Queen> conflictSet = new HashSet<Queen>();
boolean hasConflicts = false;
for (int i = 0; i < 2*N - 1; i++) {
if (i < N && rowConfl[i] != null) {
hasConflicts = hasConflicts || rowConfl[i].size() > 1;
conflictSet.addAll(rowConfl[i]);
}
if (d1Confl[i] != null) {
hasConflicts = hasConflicts || d1Confl[i].size() > 1;
conflictSet.addAll(d1Confl[i]);
}
if (d2Confl[i] != null) {
hasConflicts = hasConflicts || d2Confl[i].size() > 1;
conflictSet.addAll(d2Confl[i]);
}
}
if (hasConflicts) {
int c = random.nextInt(conflictSet.size());
return (Queen) conflictSet.toArray()[c];
}
return null;
}
public static Queen findNewBestPosition(Queen old) {
int[] row = new int[N];
int min = Integer.MAX_VALUE;
int minInd = old.row;
for (int i = 0; i < N; i++) {
if (rowConfl[i] != null) {
row[i] = rowConfl[i].size();
}
if (d1Confl[old.column + i] != null) {
row[i] += d1Confl[old.column + i].size();
}
if (d2Confl[N - 1 + old.column - i] != null) {
row[i] += d2Confl[N - 1 + old.column - i].size();
}
if (i == old.row) {
row[i] = row[i] - 3;
}
if (row[i] <= min && i != minInd) {
min = row[i];
minInd = i;
}
}
return new Queen(old.column, minInd, old.column + minInd, N - 1 + old.column - minInd);
}
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
init();
int steps = 0;
while(!checkItLinear()) {
if (++steps > maxSteps) {
init();
steps = 0;
}
}
long endTime = System.currentTimeMillis();
System.out.println("Done for " + (endTime - startTime) + "ms\n");
if(printBoard){
print();
}
}
}
Edit:
Here is my a-little-bit-optimized solution with removing some unused objects and putting the queens on diagonal positions when initializing.
import java.util.Random;
import java.util.Vector;
public class SolveQueens {
public static boolean PRINT_BOARD = true;
public static int N = 10;
public static int MAX_STEPS = 5000;
public static int[] queens = new int[N];
public static Random random = new Random();
public static int[] rowConfl = new int[N];
public static int[] d1Confl = new int[2*N - 1];
public static int[] d2Confl = new int[2*N - 1];
public static Vector<Integer> conflicts = new Vector<Integer>();
public static void init () {
random = new Random();
for (int i = 0; i < N; i++) {
queens[i] = i;
}
}
public static int getD1Pos (int col, int row) {
return col + row;
}
public static int getD2Pos (int col, int row) {
return N - 1 + col - row;
}
public static void print () {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
System.out.print(queens[i] == j ? "Q " : "* ");
}
System.out.println();
}
System.out.println();
}
public static boolean hasConflicts() {
generateConflicts();
if (conflicts.isEmpty()) {
return false;
}
int r = random.nextInt(conflicts.size());
int conflQueenCol = conflicts.get(r);
int currentRow = queens[conflQueenCol];
int bestRow = currentRow;
int minConfl = getConflicts(conflQueenCol, queens[conflQueenCol]) - 3;
int tempConflCount;
for (int i = 0; i < N ; i++) {
tempConflCount = getConflicts(conflQueenCol, i);
if (i != currentRow && tempConflCount <= minConfl) {
minConfl = tempConflCount;
bestRow = i;
}
}
queens[conflQueenCol] = bestRow;
return true;
}
public static void generateConflicts () {
conflicts = new Vector<Integer>();
rowConfl = new int[N];
d1Confl = new int[2*N - 1];
d2Confl = new int[2*N - 1];
for (int i = 0; i < N; i++) {
int r = queens[i];
rowConfl[r]++;
d1Confl[getD1Pos(i, r)]++;
d2Confl[getD2Pos(i, r)]++;
}
for (int i = 0; i < N; i++) {
int conflictsCount = getConflicts(i, queens[i]) - 3;
if (conflictsCount > 0) {
conflicts.add(i);
}
}
}
public static int getConflicts(int col, int row) {
return rowConfl[row] + d1Confl[getD1Pos(col, row)] + d2Confl[getD2Pos(col, row)];
}
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
init();
int steps = 0;
while(hasConflicts()) {
if (++steps > MAX_STEPS) {
init();
steps = 0;
}
}
long endTime = System.currentTimeMillis();
System.out.println("Done for " + (endTime - startTime) + "ms\n");
if(PRINT_BOARD){
print();
}
}
}

Comments would have been helpful :)
Rather than recreating your conflict set and your "worst conflict" queen everything, could you create it once, and then just update the changed rows/columns?
EDIT 0:
I tried playing around with your code a bit. Since the code is randomized, it's hard to find out if a change is good or not, since you might start with a good initial state or a crappy one. I tried making 10 runs with 10 queens, and got wildly different answers, but results are below.
I psuedo-profiled to see which statements were being executed the most, and it turns out the inner loop statements in chooseConflictQueen are executed the most. I tried inserting a break to pull the first conflict queen if found, but it didn't seem to help much.
Grouping only runs that took more than a second:
I realize I only have 10 runs, which is not really enough to be statistically valid, but hey.
So adding breaks didn't seem to help. I think a constructive solution will likely be faster, but randomness will again make it harder to check.

Your approach is good : Local search algorithm with minimum-conflicts constraint. I would suggest try improving your initial state. Instead of randomly placing all queens, 1 per column, try to place them so that you minimize the number of conflicts. An example would be to try placing you next queen based on the position of the previous one ... or maybe position of previous two ... Then you local search will have less problematic columns to deal with.

If you randomly select, you could be selecting the same state as a previous state. Theoretically, you might never find a solution even if there is one.
I think you woud be better to iterate normally through the states.
Also, are you sure boards other than 8x8 are solvable?
By inspection, 2x2 is not, 3x3 is not, 4x4 is not.

Related

Use Recursion to print an array from [0,0,0,0] to [9,9,9,9]I

I just want to print an array from [0,0,0,0] to [9,9,9,9] using recursion.
Firstly , I wrote the code as follows:
public class PrintNumber {
public static void main(String[] args) {
int N = 4;
int[] number = new int[N];
PrintNumber printNumber = new PrintNumber();
printNumber.printNum(number,0);
}
public void printNum(int[] number, int bit) {
if (bit == number.length ) {
System.out.println(Arrays.toString(number));
return;
}
for (int i = 0; i < 10; i++) {
number[bit] = i;
/******** something goes wrong here ********/
printNum(number, ++bit);
/******** something goes wrong here ********/
}
}
}
as you can see , there not too much code , but it didn't work.
So I debugged my code and I found out ++bit (the last line of the code) should be written as bit+1. Then , it works well.
But I am really confused , why is that? ++bit and bit+1 are both to increase the bit by 1 , why it doesn't work for ++bit and it works for bit+1 ?
Thanks a lot .
There is a difference between ++bit and bit + 1. The expression ++bit desugars into what is essentially bit = bit + 1*. So your line becomes.
printNum(number, bit = bit + 1);
So the actual value of the variable bit is changing, and since you call this in a loop, the value is going to keep increasing, which is not desired. Eventually, you get an ArrayIndexOutOfBoundsException when bit becomes too big for the array.
* It actually probably desugars into a more efficient JVM instruction, but semantically, it should be equivalent.
This is a workable solution.
import java.util.Arrays;
public class TestTest {
private static int N = 4;
private static int MAX = 10;
public static void main(String[] args) {
int[] number = new int[N];
TestTest printNumber = new TestTest();
printNumber.printNum(number,0);
}
public void printNum(int[] number, int bit) {
System.out.println(Arrays.toString(number));
if (bit == MAX ) {
return;
}
for (int i = 0; i < N; i++) {
number[i] = bit;
}
printNum(number, ++bit);
}
}
There was several problems:
You mixed loop and recurection.
Wrong array sizes
Wrong array values
Wrong print if-case
Wrong function exit.
This code yeilds stackoverflow exception. but it works for N = 3:
public class TestTest {
private static int N = 3;
private static int MAX = 10;
public static void main(String[] args) {
int[] number = new int[N];
TestTest printNumber = new TestTest();
printNumber.printNum(number);
}
public void printNum(int[] number) {
System.out.println(Arrays.toString(number));
// if (bit == MAX) {
// return;
// }
boolean exit = true;
for (int i = 0; i < N; i++) {
if (number[i] != MAX - 1) {
exit = false;
}
}
if (exit) {
return;
}
number[N - 1]++;
for (int i = N - 1; i >= 0; i--) {
if (number[i] == MAX) {
if (i > 0) {
number[i - 1]++;
number[i] = 0;
}
}
}
printNum(number);
}
}
Loop solution:
public class TestTest {
private static int N = 4;
private static int MAX = 10;
public static void main(String[] args) {
int[] number = new int[N];
TestTest printNumber = new TestTest();
// printNumber.printNum(number);
printNumber.printNumLoop(number);
}
private void printNumLoop(int[] number) {
while(true) {
System.out.println(Arrays.toString(number));
number[N - 1]++;
for (int i = N - 1; i >= 0; i--) {
if (number[i] == MAX) {
if (i > 0) {
number[i - 1]++;
number[i] = 0;
}
}
}
boolean exit = true;
for (int i = 0; i < N; i++) {
if (number[i] != MAX - 1) {
exit = false;
}
}
if (exit) {
System.out.println(Arrays.toString(number));
break;
}
}
}
public void printNum(int[] number) {
// if (bit == MAX) {
// return;
// }
boolean exit = true;
for (int i = 0; i < N; i++) {
if (number[i] != MAX - 1) {
exit = false;
}
}
if (exit) {
return;
}
number[N - 1]++;
for (int i = N - 1; i >= 0; i--) {
if (number[i] == MAX) {
if (i > 0) {
number[i - 1]++;
number[i] = 0;
}
}
}
printNum(number);
}
}

IF Statement Checking (Not Working Properly)

randomEmpty() returns a random coordinate on the n x n grid that is empty (Method works). randomAdjacent() uses randomEmpty() to select an EMPTY coordinate on the map. Comparisons are then made to see if this coordinate has an VALID adjacent coordinate that is NON-EMPTY. The PROBLEM is that randomAdjacent does not always return the coordinates of space with an adjacent NON-EMPTY space. It will always return valid coordinates but not the latter. I can't spot the problem. Can someone help me identify the problem?
public int[] randomEmpty()
{
Random r = new Random();
int[] random = new int[2];
int row = r.nextInt(array.length);
int column = r.nextInt(array.length);
while(!(isEmpty(row,column)))
{
row = r.nextInt(array.length);
column = r.nextInt(array.length);
}
random[0] = row+1;
random[1] = column+1;
return random;
}
public int[] randomAdjacent()
{
int[] adjacentToX = new int[8];
int[] adjacentToY = new int[8];
int[] adjacentFrom = randomEmpty();
int count;
boolean isTrue = false;
boolean oneAdjacentNotEmpty = false;
while(!(oneAdjacentNotEmpty))
{
count = 0;
if(validIndex(adjacentFrom,1,-1))
{
adjacentToX[count] = adjacentFrom[0]+1;
adjacentToY[count] = adjacentFrom[1]-1;
count++;
}
if(validIndex(adjacentFrom,0,-1))
{
adjacentToX[count] = adjacentFrom[0];
adjacentToY[count] = adjacentFrom[1]-1;
count++;
}
if(validIndex(adjacentFrom,-1,-1))
{
adjacentToX[count] = adjacentFrom[0]-1;
adjacentToY[count] = adjacentFrom[1]-1;
count++;
}
if(validIndex(adjacentFrom,-1,0))
{
adjacentToX[count] = adjacentFrom[0]-1;
adjacentToY[count] = adjacentFrom[1];
count++;
}
if(validIndex(adjacentFrom,-1,1))
{
adjacentToX[count] = adjacentFrom[0]-1;
adjacentToY[count] = adjacentFrom[1]+1;
count++;
}
if(validIndex(adjacentFrom,0,1))
{
adjacentToX[count] = adjacentFrom[0];
adjacentToY[count] = adjacentFrom[1]+1;
count++;
}
if(validIndex(adjacentFrom,1,1))
{
adjacentToX[count] = adjacentFrom[0]+1;
adjacentToY[count] = adjacentFrom[1]+1;
count++;
}
if(validIndex(adjacentFrom,1,0))
{
adjacentToX[count] = adjacentFrom[0]+1;
adjacentToY[count] = adjacentFrom[1];
count++;
}
for(int i = 0; i < count; i++)
{
if(!(isEmpty(adjacentToX[i],adjacentToY[i])))
{
oneAdjacentNotEmpty = true;
isTrue = true;
}
}
if(isTrue)
break;
else
adjacentFrom = randomEmpty();
}
return adjacentFrom;
}
public boolean validIndex(int[] a,int i, int j)
{
try
{
Pebble aPebble = array[a[0]+i][a[1]+j];
return true;
}
catch(ArrayIndexOutOfBoundsException e)
{
return false;
}
}
public void setCell(int xPos, int yPos, Pebble aPebble)
{
array[xPos-1][yPos-1] = aPebble;
}
public Pebble getCell(int xPos, int yPos)
{
return array[xPos-1][yPos-1];
}
JUNIT Test Performed:
#Test
public void testRandomAdjacent() {
final int size = 5;
final Board board2 = new Board(size);
board2.setCell(1, 1, Pebble.O);
board2.setCell(5, 5, Pebble.O);
int[] idx = board2.randomAdjacent();
int x = idx[0];
int y = idx[1];
boolean empty = true;
for (int i = x - 1; i <= x + 1; i++) {
for (int j = y - 1; j <= y + 1; j++) {
if ((i == x && j == y) || i < 1 || j < 1 || i > size || j > size) {
continue;
}
if (board2.getCell(i, j) != Pebble.EMPTY)
empty = false;
}
}
assertFalse(empty);// NEVER gets SET TO FALSE
assertEquals(Pebble.EMPTY, board2.getCell(x, y));
}
As for the answer: I got carried away optimizing your code for readability. I'd think it's most likely
if (board2.getCell(i, j) != Pebble.EMPTY)
empty = false;
causing the problem as getCell operates in 1-based coordinates, but i, j are in 0-based.
You should think about your logic overall. The way I see it, your code might never terminate as randomEmpty() could keep returning the same field over and over again for an undetermined period of time.
I took the liberty to recode your if-if-if cascade into utility method easier to read:
public boolean hasNonEmptyNeighbor(int[] adjacentFrom) {
for(int i = -1; i <= 1; ++i) {
for(int j = -1; j <= 1; ++j) {
if(validIndex(adjacentFrom, i, j) //Still inside the board
&& // AND
!isEmpty(adjacentFrom[0]+i //not empty
,adjacentFrom[1]+j)) {
return true;
}
}
}
return false;
}
Given my previous comment about random() being not the best of choices if you need to cover the full board, your main check (give me an empty cell with a non-empty neighbor) could be rewritten like this:
public void find() {
List<Point> foundPoints = new ArrayList<Point>();
for(int i = 0; i < Board.height; ++i) { //Assumes you have stored your height
for(int j = 0; j < Board.width; ++j) { //and your width
if(isEmpty(i, j) && hasNonEmptyNeighbor(new int[]{i,j})) {
//Found one.
foundPoints.add(new Point(i, j));
}
}
}
//If you need to return a RANDOM empty field with non-empty neighbor
//you could randomize over length of foundPoints here and select from that list.
}

Code compiles and executes, but does not print anything

The time-limit-extended is the status when executing the successfully compiled class file of the following code.
import java.io.*;
public class CandidateCode {
public static int ThirstyCrowProblem(int[] input1, int input2, int input3) {
int[] arrK = new int[input3];
int minstones = 0;
for (int i = 0; i < input3; i++) //create an array of k Os.
{
int smallest = input1[0], place = 0;
for (int j = 0; j < input2; j++) {
if ((smallest >= input1[j]) && (input1[j] >= 0)) {
smallest = input1[j];
place = j;
}
}
input1[place] = -1;
arrK[i] = smallest;
}
int n = input2, i = 0;
while (i < input3)
minstones = minstones + arrK[i] * (n - i);
return minstones;
}
public static void main(String[] args) {
int[] arr = new int[] {
5, 58
};
int stones_min = CandidateCode.ThirstyCrowProblem(arr, 2, 1);
System.out.println("The result is" + stones_min);
}
}
The cursor is waiting and waiting, but I don't think there is an error in the code!??
Option A :
Change your while into an if statement :
if(i<input3) {
minstones= minstones + arrK[i]*(n-i);
}
Option B : or increment i (i++) but I don't this that's what you want
while(i<input3) {
minstones = minstones + arrK[i]*(n-i);
i++;
}
You need to increment i in your while loop.Since you are not incrementing,its going in infinite loop.
while(i<input3)
{
minstones= minstones + arrK[i]*(n-i);
i++;
}
After making this change,I got
The result is10

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0

I am trying to write a program which can solve the 8-Puzzle problem.I am using the A* algorithm to find the solution.
I have reviewed my code many times and also tried making some changes.
Even my friends tried to help me find the bug,but they couldn't. I still don't understand where i went wrong.I used javadocs to see if I did something wrong,even that din't solve my problem. I have created three classes to solve this problem.
import java.util.*;
public class Solver implements Iterable<State>
{
ArrayList<State> queue,solQueue;
public int sol[][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 0 } };
int temp[][],i;
int moves;
int leastPriority,removeIndex;
State removeTemp;
public Solver(State initial)
{
queue = new ArrayList<State>();
solQueue = new ArrayList<State>();
queue.ensureCapacity(16);
solQueue.ensureCapacity(16);
temp = new int[3][3];
i=1;
leastPriority = 100;
removeTemp=initial;
queue.add(removeTemp);
Iterator<State> qu = queue.iterator();
while(removeTemp.m!=sol)
{
leastPriority = 100;
i=0;
queue.iterator();
for (State s : queue)
{
if((s.mh + s.count) <leastPriority)
{
leastPriority = (s.mh + s.count);
removeIndex = i;
}
if(qu.hasNext())
i++;
}
for(State s : removeTemp.neighbours() )
{
queue.add(s);
}
removeTemp=queue.remove(removeIndex);
solQueue.add(removeTemp);
}
this.moves();
this.solution();
}
public int moves()
{
System.out.print("Solution found out in "+ moves+" moves");
moves = removeTemp.count;
return moves;
}
public Iterable<State> solution()
{
for(State s : solQueue)
{
System.out.println(s.m);
System.out.println("");
}
return solQueue;
}
#SuppressWarnings({ "unchecked", "rawtypes" })
#Override
public Iterator iterator() {
return null;
}
}
And the JVM is throwing an exception.
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0,Size: 0
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at Solver.<init>(Solver.java:41)
at Main.main(Main.java:13)
What i don't understand is that how can the size of the ArrayList be 1 when i have explicitly state it as 16.
The State Class has the heuristic function which is suppose to make the algorithm efficient.The following is the State Class.
import java.util.ArrayList;
import java.util.Iterator;
public class State implements Iterable<State>
{
public int sol[][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 0 } };
int m[][], bi, bj, count, priority, si, sj;
int i,j,tempm[][];
int mh = 0;
boolean isInitialState, isRepeatedState;
State previousState, tempState;
ArrayList<State> neighbourStates;
public State(State s, int c, int[][] array)
{
neighbourStates = new ArrayList<State>();
neighbourStates.ensureCapacity(16);
tempState =this;
m = new int[3][3];
m=array;
if (s == null)
{
isInitialState = true;
count = 0;
previousState =null;
}
else
{
previousState = s;
count = c+1;
}
this.findZero();
this.manhattanHeuristic();
}
private void findZero()
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
{
if(m[i][j]==0)
{
bi=i;
bj=j;
}
}
}
private void manhattanHeuristic() {
int n = 1;
mh = 0;
for (int i = 0; i < 3; i++)
Z: for (int j = 0; j < 3; j++) {
if ((i == bi) && (j == bj)) {
continue Z;
}
else if (m[i][j] == n) {
n++;
}
else {
this.getSolutionIndex();
mh = mh + Math.abs(i - si) + Math.abs(j - sj);
}
}
}
void getSolutionIndex() {
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++) {
if (m[i][j] == 0) {
si = i;
sj = j;
}
}
}
public Iterable<State> neighbours()
{
tempm = m;
this.up();
if(!(equals(tempm)))
{
tempState = new State(this,count,tempm);
neighbourStates.add(tempState);
}
this.down();
if(!(equals(tempm)))
{
tempState = new State(this,count,tempm);
neighbourStates.add(tempState);
}
this.left();
if(!(equals(tempm)))
{
tempState = new State(this,count,tempm);
neighbourStates.add(tempState);
}
this.right();
if(!(equals(tempm)))
{
tempState = new State(this,count,tempm);
neighbourStates.add(tempState);
}
return neighbourStates;
}
public boolean equals(int s[][])
{
if((isInitialState==false)&&(previousState.m == s))
return true;
else
return false;
}
#Override
public Iterator<State> iterator() {
// TODO Auto-generated method stub
return null;
}
public void up()
{
if ((bi > 1) && (bi < 2) && (bj < 3)&& (bj > 1))
{
i = bi;
i = i + 1;
this.move(i,bj);
}
}
public void down()
{
if ((bi > 2) && (bi < 3) && (bj < 3) && (bj > 1))
{
i = bi;
i = i - 1;
this.move(i,bj);
}
}
public void left()
{
if ((bi > 1) && (bi < 3) && (bj < 2)&& (bj > 1)) {
j = bj;
j = j + 1;
this.move(bi, j);
}
}
public void right()
{
if ((bi > 1) && (bi < 3) && (bj < 3) && (bj > 2)) {
j = bj;
j = j - 1;
this.move(bi, j);
}
}
public void move(int x, int y) {
{
tempm = m;
}
if ((tempm[x + 1][y] == 0) || (tempm[x - 1][y] == 0) || (tempm[x][y + 1] == 0)|| (tempm[x][y - 1] == 0)) {
tempm[bi][bj] = tempm[x][y];
tempm[x][y] = 0;
bi = x;
bj = y;
}
}
}
And the finally the class with the main function.
import java.util.Scanner;
public class Main {
public static void main(String[] args)
{
#SuppressWarnings("resource")
Scanner sc = new Scanner(System.in);
int[][] tiles = new int[3][3];
System.out.println("Enter the elements");
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
tiles[i][j] = sc.nextInt();
State initial = new State(null,0,tiles);
Solver solver = new Solver(initial);
solver.solution();
System.out.println("Minimum number of moves = " + solver.moves());
}
}
What i don't understand is that how can the size of the ArrayList be 1 when i have explicitly state it as 16.
You did not set the size of the ArrayList to 16. You've set the capacity:
queue.ensureCapacity(16);
solQueue.ensureCapacity(16);
This does not make the ArrayList have a size of 16.
An ArrayList has an array to hold its data. When you add more elements to the ArrayList and its internal array is full, it will have to allocate a larger array and copy the content of what it currently holds plus the new element.
The capacity of the ArrayList is the minimum size that the internal array has. You can use ensureCapacity to make sure that the ArrayList doesn't have to resize too often (resizing and copying the content is an expensive operation). So, ensureCapacity is a call you make to make it work effiently.
It does not make the ArrayList have 16 elements; it only makes sure that the ArrayList has room for at least 16 elements.
If you want the ArrayList to have 16 elements, you'll have to add those elements one by one.
Size of the collection and the capacity are 2 different concepts.
capacity represents the maximum size of items a collection can hold without a reallocation.
size represents the current number of items in the collection.
IndexOutOfBoundsException is saying that you are trying to access an item with index that does not exist in the collection.
please try the below code in Solver.java
if(!queue.isEmpty())
removeTemp=queue.remove(removeIndex);
else
break;

How to compare integer elements within ArrayList?

I am trying to solve a problem by fetching the maximum number from each row in a triangle. So far am able to generate a triangle but how do I fetch the max number from each row?
Here is my code
private static Integer solve(Triangle triangle)
{
//triangle is extending an ArrayList
System.out.println(triangle);
return 0;
}
This is what am producing so far:
6
3 5
9 7 1
4 6 8 4
but now I want to get the result which says:
"In this triangle the maximum total is: 6 + 5 + 9 + 8 = 26"
Here is the complete code:
public class HellTriangle {
private static final int TRIANGLE_HEIGHT = 10;
public static void start() {
Triangle triangle = generateTriangle();
//System.out.println(triangle);
long start = System.currentTimeMillis();
Integer result = solve(triangle);
long end = System.currentTimeMillis();
System.out.println("Result:" + result);
System.out.println("Resolution time: " + (end - start) + "ms");
}
private static Triangle generateTriangle() {
Triangle triangle = new Triangle();
Random random = new Random();
for (int i = 0; i < TRIANGLE_HEIGHT; i++) {
Row row = new Row();
for (int j = 0; j <= i; j++) {
row.add(random.nextInt(100));
}
triangle.add(row);
}
return triangle;
}
private static class Row extends ArrayList<Integer> {
public String toString() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < size(); i++) {
sb.append(String.format("%02d", get(i)));
//rows.add(get(i));
if (i < (size() - 1)) {
sb.append(" ");
}
}
return sb.toString();
}
}
private static class Triangle extends ArrayList<Row> {
public String toString() {
// sb is used to make modification to the String
StringBuilder sb = new StringBuilder();
for (int i = 0; i < size(); i++) {
for (int j = 0; j < (TRIANGLE_HEIGHT - 1 - i); j++) {
sb.append(" ");
}
sb.append(get(i));
if (i < (size() - 1)) {
sb.append("\n");
}
}
return sb.toString();
}
}
private static Integer solve(Triangle triangle) {
System.out.println(triangle);
return 0;
}
public static void main(String[] args) {
start();
}
}
Any help would be appreciated!
Here, just change with your solve()
private static void solve(Triangle triangle) {
System.out.println(triangle);
ArrayList<Integer> result = new ArrayList<Integer>();
int total = 0;
for(Row row : triangle){
Collections.sort(row);
total += row.get(row.size()-1);
result.add(row.get(row.size()-1));
}
for(Integer intr : result)
System.out.println("Largest elements of the rows: " + intr);
System.out.println("Total: " + total);
}
As there is no ordering in your rows and this would lead to O(n) to get the maximum value per row i would look up the maximum value during insertion. Something like that (not tested and you probably have to override the other add methods also, depending on your use case):
public class Row extends ArrayList<Integer> {
public String toString() {
...
}
private Integer max = null;
#Override
public boolean add(Integer elem) {
if (elem != null && (max == null || max < elem)) {
max = elem;
}
return super.add(elem);
}
public Integer getMax() {
return max;
}
}
Try
private static int getTriangleMax(final Triangle rows)
{
int max = 0;
for (final Row row : rows)
{
final int rowMax = getRowMax(row);
max += rowMax;
}
return max;
}
private static int getRowMax(final Row row)
{
int rowMax = Integer.MIN_VALUE;
for (final Integer integer : row)
{
if (rowMax < integer)
{
rowMax = integer;
}
}
return rowMax;
}
Simple-Solution:
1.Add the static list as here:
private static List maxRowVal=new ArrayList();
2.Replace your generateTriangle() function with this:
private static Triangle generateTriangle()
{
Triangle triangle = new Triangle();
Random random = new Random();
for (int i = 0; i < TRIANGLE_HEIGHT; i++) {
Row row = new Row();
int maxTemp=0;
for (int j = 0; j <= i; j++) {
int rand=random.nextInt(100);
row.add(rand);
if(rand>maxTemp)
maxTemp=rand; //will get max value for the row
}
maxRowVal.add(maxTemp);
triangle.add(row);
}
return triangle;
}
Simple indeed!!
This is not exactly what you asked for, but I would like to show you a different way to go about this problem. People have done this for me before, and I really appreciated seeing different ways to solve a problems. Good luck with your coding!
Below is the code in its entirety, so you can just copy, paste and run it.
public class SSCCE {
public static void main(String[] args) {
// Here you specify the size of your triangle. Change the number dim to
// whatever you want. The triangle will be represented by a 2d-array.
final int dim = 5;
int[][] triangle = new int[dim][dim];
// Walks through the triangle and fills it with random numbers from 1-9.
for (int r = 0; r < dim; r++) {
for (int c = 0; c < r + 1; c++) {
triangle[r][c] = (int) (9 * Math.random()) + 1;
}
}
// This piece just prints the triangle so you can see what's in it.
for (int r = 0; r < dim; r++) {
for (int c = 0; c < r + 1; c++) {
System.out.print(triangle[r][c] + " ");
}
System.out.println();
}
// This part finds the maximum of each row. It prints each rows maximum
// as well as the sum of all the maximums at the end.
int sum = 0;
System.out.print("\nIn this triangle the maximum total is: ");
for (int r = 0; r < dim; r++) {
int currentMax = 0;
for (int c = 0; c < r + 1; c++) {
if (triangle[r][c] > currentMax) {
currentMax = triangle[r][c];
}
}
sum += currentMax;
if (r != 0) {
System.out.print(" + ");
}
System.out.print(currentMax);
}
System.out.println(" = " + sum + ".");
}
}
Output:
9
9 2
1 7 3
1 7 3 3
5 7 5 1 9
In this triangle the maximum total is: 9 + 9 + 7 + 7 + 9 = 41.

Categories

Resources