Sudoku count subfield - java

I am currently working on a SudokuChecker I want to check the subfields [3x3] of the sudoku. The following code does this:
int[][] field = new field[9][9];
int wrongNumbers = 0;
for (int i = 0; i < 9; i += 3) {
for (int j = 0; j < 9; j += 3) {
// Check subfield by using an array
int arr[] = new int[10];
for (int k = 0; k < 3; k++) {
for (int l = 0; l < 3; l++) {
arr[field[i + k][j + l]]++;
}
}
for (int k = 1; k < arr.length; k++) {
wrongNumbers += arr[k] > 1 ? arr[k] - 1 : 0;
}
}
}
I want to know are there any improvements for the given code?
(I am not talking about making the 3, 9, etc. constant)

I found a very good answer in Codefights from thucnguyen:
boolean sudoku(int[][] grid) {
for (int i = 0; i <9; i++) {
int row = 0, col = 0, group = 0;
for (int j = 0; j <9; j++) {
// check for row i
row += grid[i][j];
// check for col i
col += grid[j][i];
// check for sub-grid i
group += grid[i / 3 * 3 + j / 3][i % 3 * 3 + j % 3];
}
if (row != 45 || col != 45 || group != 45) return false;
}
return true;
}

Related

how to print the below pattern

for the given input I need to print the pattern. For example for input = 6 I have to print:
MMMMMMSDDDDDD
MMMMMSSSDDDDD
MMMMSSSSSDDDD
MMMSSSSSSSDDD
MMSSSSSSSSSDD
MSSSSSSSSSSSD
CSSSSSSSSSSSK
CCSSSSSSSSSKK
CCCSSSSSSSKKK
CCCCSSSSSKKKK
CCCCCSSSKKKKK
CCCCCCSKKKKKK
I have tried but couldn't go further than this could anyone help
public class tgk {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int size = sc.nextInt();
int half = ((2*size)+1)/2;
for (int i = 0; i < size ; i++)
{
for (int j = size; j > i; j--)
{
System.out.print("M");
}
for (int k = half+1 ; k > half - i; k--)
{
System.out.print("S");
}
System.out.println();
}
for(int i = size; i > 0; i--)
{
for (int j = size; j >= i; j--) {
System.out.print("C");
}
for (int k = 0; k < (i * 2 - 1); k++) {
System.out.print("S");
}
System.out.println();
}
}
}
if input = 3 it should be
MMMSDDD
MMSSSDD
MSSSSSD
CSSSSSK
CCSSSKK
CCCSKKK
You can use two sets of for loops to print each half of the pattern. Assuming input variable holds the size of the problem
int input = 3;
for (int i = 0; i < input; i++) {
for (int j = 0; j < input - i; j++) {
System.out.print('M');
}
for (int j = 0; j < 2 * i + 1; j++) {
System.out.print('S');
}
for (int j = 0; j < input - i; j++) {
System.out.print('D');
}
System.out.println();
}
for (int i = input - 1; i >= 0; i--) {
for (int j = 0; j < input - i; j++) {
System.out.print('C');
}
for (int j = 0; j < 2 * i + 1; j++) {
System.out.print('S');
}
for (int j = 0; j < input - i; j++) {
System.out.print('K');
}
System.out.println();
}
will print for input = 3:
MMMSDDD
MMSSSDD
MSSSSSD
CSSSSSK
CCSSSKK
CCCSKKK
and for input = 6:
MMMMMMSDDDDDD
MMMMMSSSDDDDD
MMMMSSSSSDDDD
MMMSSSSSSSDDD
MMSSSSSSSSSDD
MSSSSSSSSSSSD
CSSSSSSSSSSSK
CCSSSSSSSSSKK
CCCSSSSSSSKKK
CCCCSSSSSKKKK
CCCCCSSSKKKKK
CCCCCCSKKKKKK
I don't know why, but I really wanted it to work with only one set of for-loops:
int number = 8;
for (int i = 0; i < number * 2; i++) {
for (int j = 0; j < (number * 2) + 1; j++) {
System.out.print(
i < number && j+i < number ? 'M' :
i < number && j-i > number ? 'D' :
i < number ? 'S' :
i >= number && i-j >= number ? 'C' :
i >= number && j+i >= number*3 ? 'K' :
'S'
);
}
System.out.println();
}
So for 8 (like in the code) it prints:
MMMMMMMMSDDDDDDDD
MMMMMMMSSSDDDDDDD
MMMMMMSSSSSDDDDDD
MMMMMSSSSSSSDDDDD
MMMMSSSSSSSSSDDDD
MMMSSSSSSSSSSSDDD
MMSSSSSSSSSSSSSDD
MSSSSSSSSSSSSSSSD
CSSSSSSSSSSSSSSSK
CCSSSSSSSSSSSSSKK
CCCSSSSSSSSSSSKKK
CCCCSSSSSSSSSKKKK
CCCCCSSSSSSSKKKKK
CCCCCCSSSSSKKKKKK
CCCCCCCSSSKKKKKKK
CCCCCCCCSKKKKKKKK
...or for 3:
MMMSDDD
MMSSSDD
MSSSSSD
CSSSSSK
CCSSSKK
CCCSKKK

SPOJ Prime Generator, getting TLE, but approached with the best I could. (JAVA)

The problem is to generate prime in between two interval, detail problem is given in this link. SPOJ Prime Generator.
Let me explain the magic numbers and the algorithm I followed.
I have used modified Sieve Eratosthenes algorithm (modified in sense because I used the basic idea.) for implementation.
Starting number of interval, m and End number of the interval n are <= 10^9 and the difference is <=10^5 (1 <= m <= n <= 1000000000, n-m<=100000)
There is no even prime number except 2, so I considered max m and n (10^9)/2
and sqrt(max number) is around 32000 (considering both odd and even), finally 32000/2= 16,000 is the size of odd numbers list input_aray.
Finally total number range is divided into 3 regiions.
m and n both >= 32000 in this case the size of the input_aray is (n-m+1)/2 from 16001 index of array, numbers between m and n is stored (only odd numbers).
m and n <32000 in this case size of input_aray is upto n/2.
m <32000 and n>32000 in this case size of input_aray is (n-32000+1)/2.
Boolean array bol of same size as input_aray is kept to track which number is visited so that two number can't be considered twice.
for (int j = 1; j < 16001; j++) {
int flag = input_aray[j];
This loop choose n index from input_aray and check if there is any number in this array that is divisible, if so then same index of bol is initialized into false.
for (int k = j + flag; k <= 16000; k = k + flag)
This loop check for prime numbers upto 32000.
for (int k = 16001; k < input_aray.length; k++)
This one checks in between ** m and n** (when m&n >=32000)
*This is the fastest approach I could implement, but still get Time Limit Exceed. What could be the probable cause?
public static void main(String args[]){
Scanner take= new Scanner(System.in);
ArrayList<String> arrayList= new ArrayList<>();
int m,n;
int temp= take.nextInt();
take.nextLine();
if(temp>=0 && temp<=10){
for(int i=0;i<temp;i++) {
String temp1 = take.nextLine();
arrayList.add(temp1);
}
}
for(int i=0;i<arrayList.size();i++){
String[] temp_aray= arrayList.get(i).split(" ");
m= Integer.parseInt(temp_aray[0]);
n= Integer.parseInt(temp_aray[1]);
if(m>0 && n>0 && m<=10E8 && n<=10E8 && n-m<= 10E4 ) {
if (m >= 32000 && n >= 32000) {
//m & n > 32000
int start;
int[] input_aray = new int[16001 + ((n - m + 1) / 2) + 1];
boolean[] bol = new boolean[16001 + ((n - m + 1) / 2) + 1];
Arrays.fill(bol, true);
input_aray[0] = 2;
input_aray[1] = 3;
for (int j = 2; j < 16001; j++) {
input_aray[j] = input_aray[j - 1] + 2;
}
if (m % 2 == 0) {
start = m + 1;
} else {
start = m;
}
for (int j = 16001; j < input_aray.length; j++) {
input_aray[j] = start;
start += 2;
}
for (int j = 1; j < 16001; j++) {
int flag = input_aray[j];
for (int k = j + flag; k <= 16000; k = k + flag) {
if (input_aray[k] % flag == 0 && bol[k] == true) {
bol[k] = false;
}
}
for (int k = 16001; k < input_aray.length; k++) {
if (input_aray[k] % flag == 0) {
bol[k] = false;
}
}
}
int num = 1;
for (int j = 16001; j < bol.length; j++) {
if (bol[j] == true) {
System.out.println(input_aray[j]);
num++;
}
}
System.out.println();
}
if(m<32000 && n< 32000){
int[] input_aray = new int[(n/2)+1];
boolean[] bol = new boolean[(n/2)+1];
Arrays.fill(bol, true);
input_aray[0] = 2;
input_aray[1] = 3;
for (int j = 2; j < input_aray.length; j++) {
input_aray[j] = input_aray[j - 1] + 2;
}
for (int j = 1; j < Math.sqrt(n); j++) {
int flag = input_aray[j];
for (int k = j + flag; k<input_aray.length; k = k + flag) {
if (input_aray[k] % flag == 0 && bol[k] == true) {
bol[k] = false;
}
}
}
int num = 1;
for (int j = 0; j < bol.length; j++) {
if (bol[j] == true && input_aray[j] >=m && input_aray[j]<=n) {
System.out.println(input_aray[j]);
num++;
}
}
System.out.println();
}
if(m<32000 && n>32000){
int start;
int[] input_aray = new int[16001 + ((n - 32000 + 1) / 2) + 1];
boolean[] bol = new boolean[16001 + ((n - 32000 + 1) / 2) + 1];
Arrays.fill(bol, true);
input_aray[0] = 2;
input_aray[1] = 3;
for (int j = 2; j < 16001; j++) {
input_aray[j] = input_aray[j - 1] + 2;
}
start=32001;
for (int j = 16001; j < input_aray.length; j++) {
input_aray[j] = start;
start += 2;
}
for (int j = 1; j < 16001; j++) {
int flag = input_aray[j];
for (int k = j + flag; k <= 16000; k = k + flag) {
if (input_aray[k] % flag == 0 && bol[k] == true) {
bol[k] = false;
}
}
for (int k = 16001; k < input_aray.length; k++) {
if (input_aray[k] % flag == 0) {
bol[k] = false;
}
}
}
int num = 1;
for (int j = 0; j < bol.length; j++) {
if (bol[j] == true && input_aray[j]>=m && input_aray[j]<=n) {
System.out.println(input_aray[j]);
num++;
}
}
System.out.println();
}
}
}
}

Java ArrayIndexOutOfBoundsException (Minesweeper)

I am trying to make a simple minesweeper that plants n*n/3 mines in a n*n board. The mines are marked by *, and blank spaces are marked by 0. (It does not function as a game yet: I'm trying to make the 'answer sheet' of the minesweeper) And please note that I haven't used any methods on purpose.
I am constantly getting an error at the 23rd line:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 15
I have tried for hours to fix this issue, but none seems to work. Can anyone point out what is wrong and how I should fix my code? Thanks.
import java.util.Scanner;
public class Minesweeper {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
char board[][] = new char [n][n]; // makes board of n*n
int a, b;
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[i].length; j++) {
board[i][j] = '0';
}
}
for (int i = 0; i < n * n / 3; i++) { // '*' is a mine
a = (int)(Math.random() * (n - 1) + 1.0);
b = (int)(Math.random() * (n - 1) + 1.0);
board[a][b] = '*';
}
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[i].length; j++) {
for (int k = i - 1; k <= i + 1 && k >= 0 && k <= n; k++) {
for (int l = j - 1; l <= j + 1 && l >= 0 && l <= n; l++) {
if (board[k][l] == '*' && !(k == i && l == j)) {
board[i][j] = (char)(Character.getNumericValue(board[i][j]) + 1);
}
}
}
}
}
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[i].length; j++) {
System.out.println(board[i][j]);
}
}
}
}
for (int k = i - 1; k <= i + 1 && k >= 0 && k <= n; k++) {
for (int l = j - 1; l <= j + 1 && l >= 0 && l <= n; l++) {
It should be k < n and l < n. n is already outside the boundaries.
Also
for (int i = 0; i < n * n / 3; i++) { // '*' is a mine
a = (int)(Math.random() * (n - 1) + 1.0);
b = (int)(Math.random() * (n - 1) + 1.0);
board[a][b] = '*';
}
seems wrong, I think it should be
for (int i = 0; i < n * n / 3; i++) { // '*' is a mine
a = (int)(Math.random() * n);
b = (int)(Math.random() * n);
board[a][b] = '*';
}

Problems with refactoring java code

I am doing my homework right now and have a question about refactoring my code in Java.
I am working on a Sudoku right now and I need to check if the 3x3 boxes are valid or not. To do that I create a one dimensional array with all the numbers of the boxes and later I compare the value of them. It is working right now but it really isn't refactored at all. I would really like to know if there is any way to reduce all this copy paste.
public static boolean validFieldParts() {
int counter = 0;
boolean isValid = false;
int[] copyArray1 = new int[field.length];
int[] copyArray2 = new int[field.length];
int[] copyArray3 = new int[field.length];
int[] copyArray4 = new int[field.length];
int[] copyArray5 = new int[field.length];
int[] copyArray6 = new int[field.length];
int[] copyArray7 = new int[field.length];
int[] copyArray8 = new int[field.length];
int[] copyArray9 = new int[field.length];
// copy the array
// 1 große Feld
for (int i = 0; i < field.length / 3; i++) {
for (int j = 0; j < field[i].length / 3; j++) {
copyArray1[i * 3 + j] = field[i][j];
}
}
// 2 große Feld
for (int i = 0; i < field.length / 3; i++) {
for (int j = 3; j < 6; j++) {
copyArray2[i * 3 + j - 3] = field[i][j];
}
}
// 3 große Feld
for (int i = 0; i < field.length / 3; i++) {
for (int j = 6; j < 9; j++) {
copyArray3[i * 3 + j - 6] = field[i][j];
}
}
// 4 große Feld
for (int i = 3; i < 6; i++) {
for (int j = 0; j < field[i].length / 3; j++) {
copyArray4[(i - 3) * 3 + j] = field[i][j];
}
}
// 5 große Feld
for (int i = 3; i < 6; i++) {
for (int j = 3; j < 6; j++) {
copyArray5[(i - 3) * 3 + j - 3] = field[i][j];
}
}
// 6 große Feld
for (int i = 3; i < 6; i++) {
for (int j = 6; j < 9; j++) {
copyArray6[(i - 3) * 3 + j - 6] = field[i][j];
}
}
// 7 große Feld
for (int i = 6; i < 9; i++) {
for (int j = 0; j < field[i].length / 3; j++) {
copyArray7[(i - 6) * 3 + j] = field[i][j];
}
}
// 8 große Feld
for (int i = 6; i < 9; i++) {
for (int j = 3; j < 6; j++) {
copyArray8[(i - 6) * 3 + j - 3] = field[i][j];
}
}
// 9 große Feld
for (int i = 6; i < 9; i++) {
for (int j = 6; j < 9; j++) {
copyArray9[(i - 6) * 3 + j - 6] = field[i][j];
}
}
Arrays.sort(copyArray1);
Arrays.sort(copyArray2);
Arrays.sort(copyArray3);
Arrays.sort(copyArray4);
Arrays.sort(copyArray5);
Arrays.sort(copyArray6);
Arrays.sort(copyArray7);
Arrays.sort(copyArray8);
Arrays.sort(copyArray9);
for (int i = 1; i < copyArray1.length; i++) {
if (copyArray1[i] == copyArray1[i - 1])
counter++;
else
continue;
}
for (int i = 1; i < copyArray2.length; i++) {
if (copyArray2[i] == copyArray2[i - 1])
counter++;
else
continue;
}
for (int i = 1; i < copyArray3.length; i++) {
if (copyArray3[i] == copyArray3[i - 1])
counter++;
else
continue;
}
for (int i = 1; i < copyArray4.length; i++) {
if (copyArray4[i] == copyArray4[i - 1])
counter++;
else
continue;
}
for (int i = 1; i < copyArray5.length; i++) {
if (copyArray5[i] == copyArray5[i - 1])
counter++;
else
continue;
}
for (int i = 1; i < copyArray6.length; i++) {
if (copyArray6[i] == copyArray6[i - 1])
counter++;
else
continue;
}
for (int i = 1; i < copyArray7.length; i++) {
if (copyArray7[i] == copyArray7[i - 1])
counter++;
else
continue;
}
for (int i = 1; i < copyArray8.length; i++) {
if (copyArray8[i] == copyArray8[i - 1])
counter++;
else
continue;
}
for (int i = 1; i < copyArray9.length; i++) {
if (copyArray9[i] == copyArray9[i - 1])
counter++;
else
continue;
}
if (counter > 0)
isValid = false;
else
isValid = true;
return isValid;
}
Instead of using 9 different arrays and 9 different loops to represent each section of 9, I would have another nested for loop that iterates over each cluster using the same array.
//Iterate over each 'block'
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 3; col++) {
//Iterate over each cell in the block
for (int i = row*3; i < (row+1)*3; i++) {
for (int j = col*3; j < (col+1)*3; j++) {
copyArray[(i - 3) * 3 + j - 3] = field[i][j];
}
}
//Sort array and do duplication check here - return false if dupe found
}
}
return true
This would cut down on the length of your code, although it may not be more efficient.
Instead of using a counter flag, it would be much faster to instead return false whenever you would have incremented the counter, and to return true at the end. This would prevent unnecessary code from running
Here a complete refactoring. Here the improuvements:
Created two new methods: createCopy and isValid
Deleted unused variables counter and isValid
Substituted 9 arrays with one two size array.
The code as not been tested, please take a bit careful attention on method createCopy in particular.
// Creates each block of 9 digits copying digits from field
// row, col are the block position, starting from upper left 0, 0 to
// last block 2, 2
public static int[] createCopy(int[] field, int row, int col) {
int[] copy = new int[9];
for (int i = 3 * row; i < 3 * row + 3; i++) {
for (int j = 3 * col; j < 3 * col + 3; j++) {
copy[(i - 3 * row) * 3 + j - 3 * col] = field[i][j];
}
}
return copy;
}
// Check if one block is valid
private static boolean isValid(int[] copyArray) {
Arrays.sort(copyArray);
for (int i = 1; i < copyArray.length; i++) {
if (copyArray[i] == copyArray[i - 1]) {
// Exit immediately if not valid
return false;
}
}
return true;
}
// Create blocks, then validate them
// At first not valid block return false
public static boolean validFieldParts() {
int[][] copyArrays = new int[3][3];
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 3; col++) {
copyArrays[row][col] = createCopy(field, row, col);
}
}
for (int[] copyArray : copyArrays) {
if (!isValid(copyArray)) {
// Exit immediately if not valid
return false;
}
}
return true;
}

Finding the largest row and column, solution is inconsistent

Where is the logic error?.. Sometimes the solution is correct and sometimes it is not. The program is suppose to calculate the row with the greatest sum and column with the greatest sum. For example:
1 1 1 1
0 0 1 0
0 0 1 0
0 0 1 0
Then the output would be:
largest row = 0
largest column = 2 //since count starts at 0
This is what I have:
import java.util.Random;
public class LargestRowAndColumn {
public static void main(String[] args) {
Random f = new Random();
int[][] m = new int[4][4];
for (int i = 0; i < m.length; i++) {
for (int j = 0;j < m[0].length; j++) {
m[i][j] = f.nextInt(2);
}
}
for (int i = 0; i < m.length; i++) {
for (int j = 0;j < m[0].length; j++) {
System.out.print(m[i][j] + " ");
}
System.out.println();
}
System.out.println("The largest row is index: " + computeRow(m));
System.out.println("The largest column is index: " + computeColumn(m));
}
public static int computeRow(int[][] m) {
int[] count = new int[m.length];
int sum;
for (int i = 0; i < 4; i++) {
sum = 0;
for (int j = 0; j < 4; j++) {
sum = sum + m[i][j];
}
count[i] = sum;
}
int maxIndex = 0;
for (int i = 0; i < i + 1; i++) {
for (int j = count.length - 1; j >= i; j--) {
if (count[i] < count[j]) {
maxIndex = j;
break;
}
}
}
return maxIndex;
}
public static int computeColumn(int[][] m) {
int[] count = new int[m.length];
int sum = 0;
for (int i = 0; i < 4; i++) {
sum = 0;
for (int j = 0; j < 4; j++) {
sum = sum + m[j][i];
}
count[i] = sum;
}
int maxIndex = 0;
for (int i = 0; i < i + 1; i++) {
for (int j = count.length - 1; j >= i; j--) {
if (count[i] < count[j]) {
maxIndex = j;
break;
}
}
}
return maxIndex;
}
}
Your maxIndex nested loop is too complex. It should be a single loop, checking the current max value seen so far with the current item in the loop. Something like this:
int maxIndex = 0;
for (int i = 1; i < count.length; i++) {
if (count[i] > count[maxIndex]) {
maxIndex = i;
}
}
return maxIndex;
Your code is correct , but
for (int i = 0; i < m.length; i++) {
for (int j = 0;j < m[0].length; j++) {
m[i][j] = f.nextInt(2);
}
}
for (int i = 0; i < m.length; i++) {
for (int j = 0;j < m[0].length; j++) {
System.out.print(m[i][j] + " ");
}
Because of the two loops:
You are creating two random 2-dimensional array instead of one.
There is one which is being printed and the other one which is not being printed but being used for index values you require so do :
System.out.print("Index" + "\t0"+"\t1"+"\t2"+"\t3" +"\n");
System.out.print("--------------------------------------------\n");
for (int i = 0; i < m.length; i++) {
System.out.print(i+ "|\t");
for (int j = 0;j < m[0].length; j++) {
m[i][j] = f.nextInt(101);
System.out.print(m[i][j] + " \t");
}
System.out.println();
}
This will also print the index, which may assist you
Why you made your job difficult. Make 2 loops, 1 for calculating the row with biggest sum, 1 for calculating the line with the bigger sum.
You don't need an int array count[i]. In your example you calculate the row with the greatest sum, you don't need to know the sum of every row after the for loop finished, so you can use a simple int bigRow.
int bigRow = 1, sumRow = 0;
// We assume that 1st row is the biggest
// Calculate the sumRow
for (int j=0;j<n;j++)
sumRow = sumRow + m[i][j] ;
// At this moment our maximum is row 1 with its sum.
// Now we compare it with the rest of the rows
// If another row is bigger, we set him as the biggest row
for ( int i=1;i<n;i++) // We start with row 2 as we calculated the 1st row
{ int auxRow = 0;
for (int j=0;j<m;j++)
{ auxRow = auxRow + m[i][j] ; }
if (auxRow > sumRow ) { auxRow=sumRow ; bigRow = i;}
}
Do the same with lines.
int bigLine = 1, sumLine = 0 ;
Let me know if you have another problem.

Categories

Resources