this is my first Stack Overflow post, and I am fairly new to java, so I may not initially comprehend some of the feedback you give me.
With this program, I am supposed to find the determinant of a matrix recursively with a size determined by the user. When I do so, however, I get this error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at Determinant.Copy<Determinant.java:55>
at Determinant.det<Determinant.java:31>
at Determinant.main<Determinant.java:15>
I understand what this error means, but I don't understand why it's happening.
Here are the classes I am using (both printmatrix and the main method were written by my teacher, I had to complete the Copy and det methods):
import javax.swing.JOptionPane;
public class Determinant
{
public static void main(String args[])
{
String sizeStr = JOptionPane.showInputDialog("What size?");
int size = Integer.parseInt(sizeStr);
int[][] matrix = new int[size][size];
for(int i=0; i<size; i++)
for(int j=0; j<size; j++)
matrix[i][j] = (int)(Math.random()*40)-20;
printArray(matrix);
System.out.println("\nThe determinant = "+det(matrix));
}
public static int det(int[][] A)
{
int answer = 0;
int place = 0;
int[][] temp;
int[][] temp1;
if(A.length==1){
return(A[0][0]);
}
for(int i = 0; i<A.length; i++){
temp = new int[A.length-1][A[0].length-1];
temp1 = Copy(temp, i);
if(i%2==0){
place = 1;
}
else{
place = -1;
}
answer = answer + place * A[0][i] * det(temp1);
}
return answer;
}
public static int[][] Copy(int[][] B, int i)
{
int[][] C = new int[B.length-1][B.length-1];
for(int j = 1; j<B.length; j++){
for(int k = 0; k<B[0].length; k++){
if(k>i){
C[j-1][k-1]=B[j][k];
}
else{
C[j-1][k]=B[j][k];
}
}
}
return C;
}
public static void printArray(int[][] A)
{
for(int i=0; i<A.length; i++)
{
for(int j=0; j<A.length; j++)
{
int num = A[i][j];
if(num<-9)
System.out.print(" ");
else if(num<0||num>9)
System.out.print(" ");
else
System.out.print(" ");
System.out.print(A[i][j]);
}
System.out.println();
}
}
}
The error occurs at the else statement in Copy and temp1 = Copy(temp, i).
I am confused, as if either j or k = 1, shouldn't that be a position in the array? What am I missing?
The size of C array in method copy, should be same as B array.
Reason: You are copying B array into C array, they should have same size.
Try the following:
import javax.swing.JOptionPane;
public class Determinant
{
public static void main(String args[])
{
String sizeStr = JOptionPane.showInputDialog("What size?");
int size = Integer.parseInt(sizeStr);
int[][] matrix = new int[size][size];
for(int i=0; i<size; i++) {
for(int j=0; j<size; j++) {
matrix[i][j] = (int) (Math.random() * 40) - 20;
}
}
printArray(matrix);
System.out.println("\nThe determinant = "+det(matrix));
}
public static int det(int[][] A)
{
int answer = 0;
int place = 0;
int[][] temp;
int[][] temp1;
if(A.length==1){
return(A[0][0]);
}
for(int i = 0; i<A.length; i++){
temp = new int[A.length-1][A[0].length-1];
temp1 = Copy(temp, i);
if(i%2==0){
place = 1;
}
else{
place = -1;
}
answer = answer + place * A[0][i] * det(temp1);
}
return answer;
}
public static int[][] Copy(int[][] B, int i)
{
//The C array size should be same as B
int[][] C = new int[B.length][B[0].length];
for(int j = 1; j<B.length; j++){
for(int k = 0; k<B[0].length; k++){
if(k>i){
C[j-1][k-1]=B[j][k];
}
else{
C[j-1][k]=B[j][k];
}
}
}
return C;
}
public static void printArray(int[][] A)
{
for(int i=0; i<A.length; i++)
{
for(int j=0; j<A.length; j++)
{
int num = A[i][j];
if(num<-9)
System.out.print(" ");
else if(num<0||num>9)
System.out.print(" ");
else
System.out.print(" ");
System.out.print(A[i][j]);
}
System.out.println();
}
}
}
Hope this explains, enjoy!
You should declare your matrix in Copy function in this way:
int[][] C = new int[B.length][B[0].length];
Otherwise you are declaring a matrix without a row and column. The fact that you start to use from 0 doesn't mean you should declare one row in less!
Related
So I'm trying to create a program that creates a randomly generated array with numbers between 0 and 10.
Every time a number inside the 4x4 array is odd I want it to generate a brand new array and print every array discarded aswell until it creates a 4x4 array with only even numbers.
The problem right now is that I can't understand how to fix the last for and make it work properly with the boolean b that is supposed to restart the creation of the array.
import java.util.Scanner;
public class EvenArrayGenerator {
public static void main(String a[]) {
Boolean b;
do {
b = true;
int[][] Array = new int[4][4];
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++)
Array[i][j] = (int) (Math.random() * 11);
}
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
System.out.print(Array[i][j] + " ");
}
System.out.println();
}
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (Array[i][j] % 2 != 0)
b = false;
}
}
} while (b);
}
}
public class ArrayGen {
private int[][] array = new int[4][4];
private int iterations = 1; // you always start with one iteration
public static void main (String[] args) {
ArrayGen ag = new ArrayGen();
ag.reScramble();
while(!ag.isAllEven()) {
ag.reScramble();
ag.iterations++;
}
// this is just a nice visualisation
for (int i = 0; i < 4; i++) {
System.out.print("[");
for (int j = 0; j < 4; j++) {
System.out.print(ag.array[i][j] +((j != 3)? ", " : ""));
}
System.out.print("]\n");
}
System.out.println(ag.iterations + " iterations needed to get all-even array.");
}
private void reScramble () {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
array[i][j] = (int)(Math.random() * 11);
}
}
}
private boolean isAllEven () {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (array[i][j] % 2 == 1) {
return false;
}
}
}
return true;
}
}
I think this is a good solution. Refactoring your code into structured methods is never a bad idea. I hope this helps!
You are looping until you get an array that's all even. You should initialize b to be false, and update it to true in the (nested) for loop. Note that once's you've set it to false, there's no reason checking the other members of the array, and you can break out of the for loop.
Note, also, that using stream could make this check a tad more elegant:
b = Arrays.stream(arr).flatMapToInt(Arrays::stream).anyMatch(x -> x % 2 != 0)
What about generating random numbers up to 5 and double it? Then you don't have two check if they are even.
Instead of your last for loop:
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(Array[i][j] % 2!=0){
b=false;
break;
}
}
if(!b){
break;
}
}
if(!b){
break;
}
Alternatively, you could do an oddity check when you are generating the elements. Something like:
int element;
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
do{
element = (int)(Math.random()*11);
}while(element % 2 !=0)
Array[i][j] = element;
}
}
That way you don't have to check the values, they will always be even.
This should work:
import java.util.Scanner;
public class EvenArrayGenerator{
public static void main(String a[]){
boolean anyOdd;
int array = 0;
do{
System.out.println ("Array " + ++array + ":");
anyOdd=false;
int[][] Array = new int[4][4];
for(int i=0;i<4;i++) {
for(int j=0;j<4;j++) {
Array[i][j] = (int)(Math.random()*11);
}
}
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
System.out.print(Array[i][j] + " ");
}
System.out.println();
}
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
anyOdd |= Array[i][j] % 2!=0;
}
}
} while(anyOdd);
}
}
As you can see, I just modified the condition from b to anyOdd, so if there is any odd number, it will iterate again.
Also, you can check it when you generate the random numbers, so you avoid a second loop:
import java.util.Scanner;
public class EvenArrayGenerator{
public static void main(String a[]){
boolean anyOdd;
int array = 0;
do{
System.out.println ("Array " + ++array + ":");
anyOdd=false;
int[][] Array = new int[4][4];
for(int i=0;i<4;i++) {
for(int j=0;j<4;j++) {
Array[i][j] = (int)(Math.random()*11);
anyOdd |= array[i][j] % 2 != 0;
}
}
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
System.out.print(Array[i][j] + " ");
}
System.out.println();
}
} while(anyOdd);
}
}
public class EvenArrayGenerator {
public static void main(String a[]) {
int[][] arr = createAllEvenArray(4);
printArray(arr);
}
private static int[][] createAllEvenArray(int size) {
while (true) {
int[][] arr = createArray(size);
printArray(arr);
if (isAllEven(arr))
return arr;
}
}
private static int[][] createArray(int size) {
int[][] arr = new int[size][size];
for (int i = 0; i < arr.length; i++)
for (int j = 0; j < arr.length; j++)
arr[i][j] = (int)(Math.random() * 11);
return arr;
}
private static void printArray(int[][] arr) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (j > 0)
System.out.print("\t");
System.out.format("%2d", arr[i][j]);
}
System.out.println();
}
System.out.println();
}
private static boolean isAllEven(int[][] arr) {
for (int i = 0; i < arr.length; i++)
for (int j = 0; j < arr.length; j++)
if (arr[i][j] % 2 != 0)
return false;
return true;
}
}
I am building a Java Array where the odd columns will output the #1 and the even columns will output the #0. Here is what i have so far. I'm certain my mistake is trivial but if you could help it would be greatly appreciated!
import java.util.Scanner;
public class TestArray2 {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
int [][] a = new int[5][5];
for(int i=0; i<a.length;i++){
for(int j=0;j<a[0].length;j++){
int x = j;
if(x%2 == 0){
a[i][j] = 0;
}
else {
a[i][j] = 1;
}
}
input.close();
}
}
public class Array2 {
public static void printArray(int[][]a){
for(int i=0;i<a.length;i++){
for(int j=0; j<a[0].length;j++){
System.out.print(a[i][j]+" ");
}
System.out.println();
}
}
Array2.printArray(a);
}
}
Array Code
This should work, I skipped the second class
public class TestArray2 {
public static void main(String[] args){
int [][] a = new int[5][5];
for(int i=0; i<a.length;i++){
for(int j=0;j<a[i].length;j++){
int x = j;
if(x%2 == 0){
a[i][j] = 0;
}
else {
a[i][j] = 1;
}
}
}
printArray(a);
}
public static void printArray(int[][] a) {
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
System.out.print(a[i][j] + " ");
}
System.out.println();
}
}
}
Actually you have two different problems. The first one is that you are using a matrix not an array. The second one is that you are trying to call the method on the second class when it does not have the a variable defined for that.
Try the following:
import java.util.Scanner;
public class TestArray2 {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
int [] a = new int[input];
for(int i=0; i<a.length;i++){
if(i%2 == 0){
a[i] = 0;
} else {
a[i] = 1;
}
}
input.close();
printArray(a);
}
public static void printArray(int[]a){
for(int i=0;i<a.length;i++){
System.out.print(a[i]+" ");
}
System.out.println();
}
}
So I've been fiddling around with 2D arrays in java. I am practicing by using the arrays as matrices. I create 2 Matrix objects, which have a myMatrix 2D array field. In the main method, I call the first Matrix object to add itself to the second matrix if it is possible, through the addMatrix method. I have a printResultDetail method to actually print out what is happening. I want the first object's myMatrix to print out with rows and columns properly formatted. Then I want the second object's myMatrix object to print out on the right of the previous. I then want the new output matrix, given by the first object's myResultMatrix 2D array, to printed out again to the right.
How do I make the arrays print out side by side?
Note: the printResultDetail is incorrect. I was just trying to figure out how to do it.
import java.util.Arrays;
import java.util.Random;
public class Matrix {
int[][] myMatrix;
int[][] myResultMatrix;
int myMatrixRow;
int myMatrixCol;
Random rand = new Random();
public Matrix(int rowSize, int colSize, int maxVal, int minVal){
myMatrixRow = rowSize;
myMatrixCol = colSize;
myMatrix = new int[rowSize][colSize];
for(int i = 0; i < rowSize; i++){
for(int k = 0; k < colSize; k++){
myMatrix[i][k] = rand.nextInt((maxVal - minVal) + 1) + minVal; //assigns each part of array to rand #
}
}
for(int i = 0; i<myMatrixRow; i++){
System.out.print("[");
for(int j = 0; j<myMatrixCol; j++){
System.out.print(" " + myMatrix[i][j] + " ");
}
System.out.print("]");
System.out.println();
}
//System.out.println(Arrays.deepToString(myMatrix));
}
public int[][] multMatrix(Matrix matrix2){
if(canMultiply(matrix2) == true){
myResultMatrix = new int[myMatrixRow][matrix2.myMatrixCol];
for (int i = 0; i < myMatrixRow; i++) {
for (int j = 0; j < matrix2.myMatrixCol; j++) {
for (int k = 0; k < myMatrixCol; k++) {
myResultMatrix[i][j] += myMatrix[i][k] * matrix2.myMatrix[k][j];
}
}
}
return myResultMatrix;
}else{
myResultMatrix = null;
return null;
}
}
public boolean canMultiply(Matrix matrix2){ //can only multiply if the columns of
//first matrix is equal to the rows of the second
if(myMatrixCol == matrix2.myMatrixRow){
return true;
}else{
return false;
}
}
public int[][] addMatrix(Matrix matrix2){
if(myMatrixRow == matrix2.myMatrixRow && myMatrixCol == matrix2.myMatrixCol){
myResultMatrix = new int[myMatrixRow][myMatrixCol];
for(int i = 0; i < myMatrixRow; i++){
for(int k = 0; k < myMatrixCol; k++){
myResultMatrix[i][k] = myMatrix[i][k] + matrix2.myMatrix[i][k];
}
}
return myResultMatrix;
}else{
myResultMatrix = null;
return null;
}
}
public void printResultDetail(Matrix matrix2){
for(int i = 0; i<myMatrixRow; i++){
System.out.print("[");
for(int j = 0; j<myMatrixCol; j++){
System.out.print(" " + myMatrix[i][j] + " ");
}
System.out.print("] ");
System.out.println();
for(int k = 0; k<matrix2.myMatrixRow; k++){
System.out.print("[");
for(int x = 0; x<matrix2.myMatrixCol; x++){
System.out.print(" " + matrix2.myMatrix[k][x] + " ");
}
System.out.print("]");
}
}
}
public static void main(String[] args){
Matrix firstMatrix = new Matrix(3, 3, 5, 1);
Matrix secondMatrix = new Matrix(3, 3, 5, 1);
System.out.println(Arrays.deepToString(firstMatrix.addMatrix(secondMatrix)));
//System.out.println(Arrays.deepToString(firstMatrix.addMatrix(secondMatrix)));
}
}
This code below will print:
maybe you can use as sample.
public class Test {
public static void main(String[] args) {
double[][] matrixLeft = {{1,5,2,8,4,70,55,80},{3,7,4,2,6,60,30,70}};
double[][] matrixRight = {{8,1,6,4,2,10,40,60},{1,5,2,8,4,70,50,80},{3,7,4,2,6,60,30,70}};
int endOfLoop = matrixLeft.length > matrixRight.length ? matrixLeft.length : matrixRight.length;
for(int i = 0; i < endOfLoop; i++){
if(matrixLeft.length > i){
printLine(matrixLeft[i]);
System.out.print(" ");
} else {
printBlankLine(matrixLeft[0].length);
}
if(matrixRight.length > i){
printLine(matrixRight[i]);
}
System.out.println();
}
}
private static void printLine(double[] line){
for(double number : line){
System.out.print(number + " ");
}
}
private static void printBlankLine(int lenght){
for(int i=0; i < lenght; i++){
System.out.print(" ");
}
}
}
This question already has answers here:
How to find a saddle point of a matrix using Java? [closed]
(2 answers)
Closed 8 years ago.
This is my program in finding the Saddle Point of a Matrix (IntMatrix). Please help me make another method for IntMatrix m, for the Parameters inside the saddlePoints method?
public class SaddlePoint{
public void saddlePoints(IntMatrix m, int[] rows, int[] cols) {
int rows = m.length;
int cols = m[0].length;
boolean[][] flagArr = new boolean[rows][cols];
for(int i=0; i<rows; i++){
for(int j=0; j<cols; j++){
if(m[i][j]==0){
flagArr[i][j]=true;
}
}
}
for(int i=0; i<rows; i++){
for(int j=0; j<cols; j++){
if(flagArr[i][j]==true){
/*for rows*/
for(int k=0; k<rows; k++){
m[k][j]=0;
}
/*for cols*/
for(int z=0; z<cols; z++){
m[i][z]=0;
}
}
}
}
}
}
this is the requirement
but i need the saddlePoint method only because I already have the other methods
IntMatrix Class:
//represents a 2-dimensional matrix of integers
Constructor Signature:
IntMatrix(int rows, int cols, int ... elements)
//elements are provided in row major order
IntMatrixUtilityClass
Static Methods:
IntMatrix sum(IntMatrix ... matrices)
//returns the sum of its arguments
IntMatrix product(IntMatrix m1, IntMatrix m2, IntMatrix ... others)
//returns the product of its arguments
boolean[] saddlePoints(IntMatrix m, int[] rows, int[] cols)
/*for each of the row and column pairs, returns true if the specified element of m is a saddle
point for the matrix; returns false otherwise*/
this is my program, I only need the saddlePoints
public class IntMatrix {
private int[][] matrix;
private int rows;
private int cols;
private int[] elements;
public IntMatrix(int r, int c, int... e) {
this.rows = r;
this.cols = c;
this.elements = e;
matrix = new int[rows][cols];
int l = 0;
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
this.matrix[i][j] = elements[l];
l++;
}
}
}
public static IntMatrix sum(IntMatrix... matrices) {
int[] result = new int[matrices[0].rows * matrices[0].cols];
for (IntMatrix matrix : matrices) {
int l = 0;
for (int i = 0; i < matrix.rows; i++) {
for (int j = 0; j < matrix.cols; j++) {
result[l] += matrix.matrix[i][j];
l++;
}
}
}
IntMatrix m3 = new IntMatrix(matrices[0].rows, matrices[0].cols, result);
return m3;
}
public static IntMatrix product(IntMatrix m1, IntMatrix m2,
IntMatrix... others) {
int[] result = new int[m1.rows * m2.cols];
int l = 0;
for (int i = 0; i < m1.rows; i++) {
for (int j = 0; j < m2.cols; j++) {
for (int k = 0; k < m1.cols; k++) {
result[l] += (m1.matrix[i][k] * m2.matrix[k][j]);
}
l++;
}
}
IntMatrix m3 = new IntMatrix(m1.rows, m2.cols, result);
for (IntMatrix other : others) {
int length = others.length;
l = 0;
int[] result2 = new int[(m3.rows * others[length - 1].cols)];
for (int i = 0; i < m3.rows; i++) {
for (int j = 0; j < other.cols; j++) {
for (int k = 0; k < m3.cols; k++) {
result2[l] += (m3.matrix[i][k] * other.matrix[k][j]);
}
l++;
}
}
m3 = new IntMatrix(m3.rows, others[length - 1].cols, result2);
}
return m3;
}
public String toString() {
return String.valueOf(rows) + " " + " " + String.valueOf(cols)
+ Arrays.toString(elements);
}
}// end of Matrix Class
First I want to say please do some research on your own before asking. From Here How to find a saddle point of a matrix using Java? you can find accepted ans but here I tell you that is not according to Wikipedia definition
Sadle Point:
A saddle point is an element of the matrix which is both the largest element in its
column and the smallest element in its row.
OR in simple words A matrix is said to have a saddle point if some entry a[x][y] is the smallest value in the x'th row and the largest value in the y'th column. A matrix may have more than one saddle point.
This Code is according to wikipedia defination
package com.mubasher.main;
import java.util.Random;
public class SaddlePoint {
private int[][] intMatrix;
private int[] colMaxima;
private int[] rowMinima;
public SaddlePoint(int col, int row){
intMatrix = new int[row][col];
colMaxima = new int[col];
rowMinima = new int[row];
fillMatrix();
}
private void fillMatrix() {
Random random = new Random();
for(int row = 0; row<intMatrix.length;row++){
for(int col = 0;col<intMatrix[0].length;col++){
intMatrix[row][col] = random.nextInt(21) - 10;
}
}
printMatrix();
}
private void printMatrix(int[][] intMatrix) {
for(int row = 0;row<intMatrix.length;row++){
for(int col = 0; col<intMatrix[0].length;col++){
System.out.print(intMatrix[row][col]+" ");
}
System.out.println("");
}
for(int i=0;i<intMatrix[0].length;i++)
System.out.print("----");
System.out.println("");
}
public void printMatrix() {
printMatrix(intMatrix);
}
public void printArray(int[] array,boolean isHorizontaly) {
for(int i = 0;i<array.length;i++){
if(isHorizontaly){
System.out.print(array[i]+" ");
} else {
System.out.println(array[i]);
}
}
if(isHorizontaly){System.out.println("");
for(int i=0;i<array.length;i++)
System.out.print("----");
} else {
System.out.println("----");
}
System.out.println("");
}
public void run(){
int maxVal = 0,minVal=0;
//minimum in each row
for(int row = 0; row<intMatrix.length;row++){
for(int col = 0;col<intMatrix[0].length;col++){
if(col == 0 ) {
rowMinima[row]=intMatrix[row][col]; // assume first val at (row,0) is minimum
} else {
if(intMatrix[row][col]<rowMinima[row]){
rowMinima[row]=intMatrix[row][col]; // assign new minimum val
}
}
}
}
//maximum in each column
for(int col = 0; col<intMatrix[0].length;col++){
for(int row = 0;row<intMatrix.length;row++){
if(row == 0 ) {
colMaxima[col]=intMatrix[row][col]; // for
} else {
if(intMatrix[row][col]>colMaxima[col]){
colMaxima[col]=intMatrix[row][col]; // assign new max val
}
}
}
}
printArray(colMaxima,true);
printArray(rowMinima,false);
int colIndx=0,rowIndx=0;
for(int i =0;i<colMaxima.length;i++){
if(i == 0 ) {
minVal= colMaxima[i];
colIndx=i;
} else {
if(colMaxima[i]<minVal){
minVal= colMaxima[i];
colIndx=i;
}
}
}
for(int i =0;i<rowMinima.length;i++){
if(i == 0 ) {
maxVal= rowMinima[i];
rowIndx = i;
} else {
if(rowMinima[i]>maxVal){
maxVal= rowMinima[i];
rowIndx = i;
}
}
}
if(minVal == maxVal){
System.out.println("We Have Saddle Point "+maxVal+" at ("+(rowIndx+1)+","+(colIndx+1)+")");
} else {
System.out.println("There is no saddle point");
}
}
public static void main(String[] args) {
SaddlePoint sp = new SaddlePoint(3, 4);
sp.run();
}
}
you can modify run method according to your needs. run method is calculating saddle point
http://usacotraining.blogspot.com/2013/10/problem-142-clocks.html
I am attempting to use Depth First Search to solve this problem. I created a Node class based on a 3x3 array, and am using a visited array of size 4^9. However, this clearly is not working at all (it is not printing anything). My attempts of debugging (see comments) showed me that for some reason the array seems to be resetting each time, but I cannot figure out why.
Also, I am sure that my code is unnecessarily complicated, and there is a better way to perform DFS like this. Can someone show me a better way?
/*
ID: akshajk1
LANG: JAVA
TASK: clocks
*/
import java.util.*;
import java.io.*;
import java.lang.*;
import java.math.*;
class clocks {
public static boolean[] visited;
public static boolean done;
public static String[] moves = {"ABDE", "ABC", "BCEF", "ADG", "BDEFH", "CFI", "DEGH", "GHI", "EFHI"};
public static Stack<Integer> ans = new Stack<Integer>();
public static Stack<Integer> finalans = new Stack<Integer>();
public static void main(String[] args) throws Exception {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
// BufferedReader bf = new BufferedReader(new FileReader("clocks.in"));
// PrintWriter out = new PrintWriter(new FileWriter("clocks.out"));
// int n = Integer.parseInt(bf.readLine());
int[][] a = new int[3][3];
for(int i=0; i<3; i++) {
StringTokenizer st = new StringTokenizer(bf.readLine());
for(int j=0; j<3; j++) a[i][j] = Integer.parseInt(st.nextToken());
}
visited = new boolean[4*4*4*4*4*4*4*4*4];
Node x = new Node(a);
dfs(x);
for(int i : finalans)
out.println(i + " ");
out.close(); System.exit(0);
}
public static void dfs(Node a) {
if(done) return;
int n = 0;
for(int i=0; i<3; i++)
for(int j=0; j<3; j++)
n = 4*n+a.get(i, j);
if(visited[n]) return;
// for(int i=0; i<3; i++) { for(int j=0; j<3; j++) System.out.print(a.get(i, j)); System.out.print("\n"); } System.out.print("\n");
// System.out.println(Arrays.toString(ans.toArray()) + "\n");
boolean gotit = true;
for(int i=0; i<3; i++) for(int j=0; j<3; j++) if(a.get(i, j) != 0) gotit = false;
if(gotit) {
for(int i : ans)
finalans.push(i);
done = true;
return;
}
visited[n] = true;
for(int i=0; i<moves.length; i++) {
char[] x = moves[i].toCharArray();
int[][] b = new int[3][3];
for(int k=0; k<3; k++)
for(int kk=0; kk<3; kk++)
b[k][kk] = a.get(k, kk);
Node abc = new Node(b);
for(char c : x)
abc = abc.turn(c);
ans.push((i+1));
dfs(abc);
}
ans.pop();
}
}
class Node {
final private int[][] a;
public Node(int[][] aaa) {
a = new int[3][3];
for(int i=0; i<3; i++)
for(int j=0; j<3; j++)
a[i][j] = aaa[i][j];
}
public int get(int i, int j) {
return (a[i][j] % 12)/3;
}
public Node turn(char c) {
int val = c - 'A';
int[][] b = new int[3][3];
for(int i=0; i<3; i++)
for(int j=0; j<3; j++)
b[i][j] = a[i][j];
b[val/3][val%3] += 3;
if(b[val/3][val%3] > 12) b[val/3][val%3] %= 12;
if(b[val/3][val%3] == 0) b[val/3][val%3] += 12;
Node ansans = new Node(b);
for(int i=0; i<3; i++) { for(int j=0; j<3; j++) System.out.print(ansans.get(i, j)); System.out.print("\n"); } System.out.print("\n");
return ansans;
}
}
edit: Thanks for all the help! I was able to correct the copying bug, and now the print statements make more sense, but the program is still stopping after performing move 1 four times. I changed the visited array to mark the initial value as true, resulting in the following code:
import java.util.*;
import java.io.*;
import java.lang.*;
import java.math.*;
class clocks {
public static boolean[] visited;
public static boolean done;
public static String[] moves = {"ABDE", "ABC", "BCEF", "ADG", "BDEFH", "CFI", "DEGH", "GHI", "EFHI"};
public static Stack<Integer> ans = new Stack<Integer>();
public static Stack<Integer> finalans = new Stack<Integer>();
public static void main(String[] args) throws Exception {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
// BufferedReader bf = new BufferedReader(new FileReader("clocks.in"));
// PrintWriter out = new PrintWriter(new FileWriter("clocks.out"));
// int n = Integer.parseInt(bf.readLine());
int[][] a = new int[3][3];
for(int i=0; i<3; i++) {
StringTokenizer st = new StringTokenizer(bf.readLine());
for(int j=0; j<3; j++) a[i][j] = Integer.parseInt(st.nextToken());
}
visited = new boolean[4*4*4*4*4*4*4*4*4];
Node x = new Node(a);
int n = 0;
for(int xx=0; xx<3; xx++)
for(int j=0; j<3; j++)
n = 4*n+x.get(xx, j);
visited[n] = true;
dfs(x);
for(int i : finalans)
out.println(i + " ");
out.close(); System.exit(0);
}
public static void dfs(Node a) {
if(done) return;
// for(int i=0; i<3; i++) { for(int j=0; j<3; j++) System.out.print(a.get(i, j)); System.out.print("\n"); } System.out.print("\n");
// System.out.println(Arrays.toString(ans.toArray()) + "\n");
boolean gotit = true;
for(int i=0; i<3; i++) for(int j=0; j<3; j++) if(a.get(i, j) != 0) gotit = false;
if(gotit) {
for(int i : ans)
finalans.push(i);
done = true;
return;
}
for(int i=0; i<moves.length; i++) {
char[] x = moves[i].toCharArray();
int[][] b = new int[3][3];
for(int k=0; k<3; k++) {
for(int kk=0; kk<3; kk++) {
b[k][kk] = a.get(k, kk)*3;
if(b[k][kk] == 0) b[k][kk] = 12;
}
}
Node abc = new Node(b);
for(char c : x)
abc = abc.turn(c);
int n = 0;
for(int xx=0; xx<3; xx++)
for(int j=0; j<3; j++)
n = 4*n+abc.get(xx, j);
if(!visited[n]) {
visited[n] = true;
ans.push((i+1));
dfs(abc);
ans.pop();
}
}
}
}
class Node {
final private int[][] a;
public Node(int[][] aaa) {
a = new int[3][3];
for(int i=0; i<3; i++)
for(int j=0; j<3; j++)
a[i][j] = aaa[i][j];
}
public int get(int i, int j) {
return (a[i][j] % 12)/3;
}
public Node turn(char c) {
int val = c - 'A';
int[][] b = new int[3][3];
for(int i=0; i<3; i++)
for(int j=0; j<3; j++)
b[i][j] = a[i][j];
b[val/3][val%3] += 3;
if(b[val/3][val%3] > 12) b[val/3][val%3] %= 12;
if(b[val/3][val%3] == 0) b[val/3][val%3] += 12;
Node ansans = new Node(b);
// for(int i=0; i<3; i++) { for(int j=0; j<3; j++) System.out.print(ansans.get(i, j)); System.out.print("\n"); } System.out.print("\n");
return ansans;
}
}
(I also fixed another bug). This for some reason is still not working, and is yielding a stack overflow error. I understand that there is a lot of recursion, but only a maximum of 9*3 = 27 moves should be made anyways. Why is this happening?
Your copying is wrong. The line where you copy a to b. You set each oft b's values to a.get(i, j) where a.get() does not return its value but value%12 divided by 3.
Ok i figured out that for the first 6000 searches (thats when your ans-stack overflows) the algorithm always has a valid move to choose.
To prevent that you should consider breadth first search or set a maximum search depth.
I´ve added a maximum search depth and the algorithm returns, however the turns required change from situation to situation and range over a large set. Therefore sometimes 200 moves are required, so you can´t set a maximum search depth of any lower value. But then with 200 as maximum search depth. Any 200 step solution will be accepted even if better solutions exist.
My recommendation therefore is to take depth first search as your search algorithm.