How to check array for possible divisors? - java

Creating the array, I am letting the user choose the length:
StartNum = scan.nextInt();
int[] NumBox = new int[StartNum];
for (int i = 1; i < NumBox.length+1; i++)
{NumBox[i - 1] = i;}
NumBox[0]=0;
Assuming there are other methods that can change cells in NumBox to 0, how would I use a for loop to check each cells in the array for any divisor? If there are no divisors for the cell in the array, it will then become a 0. For example, if the array is [0,2,0,4,0,6,7,8,9] 9,2 and 7 would become a 0.
The code below is what I tired but didn't get far.
boolean NoDiv=false;
for (int a=1; a < NumBox.length+1; a++)
{
a++
for (int check=1; a < NumBox.length+1; check++)
{
if (NumBox[a-1]% check == 0 && NumBox[a-1] !=0)
{
NumBox[a-1] = 0;
}
}
}

for (int i = 0; i < NumBox.length; i++) {
if (NumBox[i] == 0) continue;
boolean hasDivisor = false;
for (int j = 0; j < i; j++) {
if (NumBox[j] == 0) continue;
if (NumBox[i] % NumBox[j] == 0) {
hasDivisor = true;
break;
}
}
if (!hasDivisor) NumBox[i] = 0;
}

Related

How to add a condition so I don't go inside the loop

I am working on a code where you subtract respective elements of array 'a' from array'b' till you get all elements in array 'a' equal.
Condition is that a[i]>b[i] for subtraction.
But not every time getting all elements equal is possible, so in that case I would like my code to print '-1', how can I achieve it. I really tried hard to figure it out, don't give complex solutions as I am a beginner. you can subtract as many times you want.
Scanner sc = new Scanner(System.in);
short n = sc.nextShort();
short a[] = new short[n];
short b[] = new short[n];
for (short i = 0; i < n; i++) {// taking elements input
a[i] = sc.nextShort();
}
for (short i = 0; i < n; i++) {// taking elements input
b[i] = sc.nextShort();
}
short minimumOfArraya = 0;
for (short i = 0; i < n; i++) {// finding smallest element in array 'a'
for (short j = 0; j < n; j++) {
if (a[i] < a[j]) {
minimumOfArraya = a[i];
}
}
}
boolean allequal = false;
int counter = 0;
while (!allequal) {
for (short i = 0; i < n; i++) {// subtracting elements
if (a[i] == minimumOfArraya)
continue;
if (a[i] >= b[i]) {
a[i] -= b[i];
counter++;
}
}
for (short i = 0; i < n; i++) {
if (a[0] == a[i]) {
allequal = true;
} else {
allequal = false;
break;
}
}
}
for (int i = 0; i < n; i++) {// printing array 'a'
System.out.print(a[i] + " ");
}
System.out.println();
System.out.println(counter);
4
5 7 4 3//infinite loop
4 1 0 0
working input
5
5 7 10 5 15
2 2 1 3 5
output
5 5 5 5 5
8
The minimum can be found faster:
short minimumOfArraya = Short.MAX_VALUE;
for (short i = 0; i < n; i++) {// finding smallest element in array 'a'
if (a[i] < minimumOfArraya]) {
minimumOfArraya = a[i];
}
}
The for loop to check whether all are equal should initially have an allequal true,
and on finding a false, break. The initial setting to true was missing.
boolean allequal = false;
int counter = 0;
while (!allequal) {
for (short i = 0; i < n; i++) {// subtracting elements
if (a[i] == minimumOfArraya)
continue;
if (a[i] >= b[i]) {
a[i] -= b[i];
counter++;
}
}
allequal = true;
for (short i = 0; i < n; i++) {
allequal = a[0] == a[i];
if (!allequal) {
break;
}
}
}
If counter was not increased inside the while, the code may very well stay looping till overflow. If the minimum was 100 and 102 got 98 for instance.
If some of iterations producing number which is less than minimum, it clearly shows that you cannot make all elements equal. Check that after subtracting
while (!allequal) {
boolean impossible = false;
for (short i = 0; i < n; i++) {
if (a[i] < mimimumofArraya) {
impossible = true;
break;
}
if (a[i] == minimumOfArraya) continue;
if (a[i] >= b[i]) {
a[i] -= b[i];
counter++;
}
}
if (impossible) {
counter = -1;
break;
}
// The rest of your loop
...
}

How do I replace zeros in a matrix?

Replace the elements with a value of 0.0 with the average of the adjacent elements: previous and / or next in the same row.
Here's my code. Can u help me to solve it?
public void replaceZeros(double[][] array){
for (int i = 0; i < array.length; i++){
for(int j = 0; i < array[i].length; j++){
if(array[i][j] == 0){
if(array[i][0] == 0){
array[i][j] = array[i+1][j];
} else if(j == array[i].length-1){
array[i][j] = array[i-1][j];
} else {
array[i][j] = (array[i+1][j]+array[i-1][j])/2;
}
}
}
}
}
If I understand correctly, you want to replace elements of an array that are 0 with the average of a neighbour to the left and right. In the code you provided, you increase and decrease second array argument which is the column. Try this code:
public void replaceZeros(double[][] array) {
for (int i = 0; i < array.length; i++) {
for (int j = 0; i < array[i].length; j++) {
if (array[i][j] == 0) {
//check if its first element in a row
if (j == 0) {
array[i][j] = array[i][j + 1];
}
//check if its last element in a row
else if (j == array[i].length - 1) {
array[i][j] = array[i][j - 1];
}
//proceed with calculating average
else {
array[i][j] = (array[i][j + 1] + array[i][j - 1]) / 2;
}
}
}
}
}
Your for loop had minor issues, below for loop should work :
public void replaceZeros(double[][] array){
for (int i = 0; i < array.length; i++){
for(int j = 0; j < array[i].length; j++){
if(array[i][j] == 0) { // If element is 0
if (j == 0) { // If element is in 1st column, any row
array[i][j] = array[i][j+1];
} else if(j == array[i].length-1) { // If element is in last column, any row
array[i][j] = array[i][j-1];
} else { // If element is not in 1st or last column, any row
array[i][j] = (array[i][j-1]+array[i][j+1])/2;
}
}
}
}
}

Java: Sudoku- increase number of empty spaces causes my code to throw an exception

I'm trying to make a Sudoku game for my project but if i increase the number of empty spaces in the Sudoku Grid the code just throws an exception arrayoutofbounds but can't figure out where it's coming from. k is the number of empty spaces in the grid.
I haven't tried anything because can't figure out what can be done at this kind of problem
Here is the code:
package sudoku.puzzle;
import java.util.*;
public class SudokuPuzzle {
int[] mat[];
int N; // number of columns/rows.
int SRN; // square root of N
int K; // No. Of missing digits
// Constructor
SudokuPuzzle(int N, int K) {
this.N = N;
this.K = K;
// Compute square root of N
Double SRNd = Math.sqrt(N);
SRN = SRNd.intValue();
mat = new int[N][N];
}
// Driver code
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("Select Level Of Difficulty \n 1.Easy\n 2.Medium\n 3.Hard");
String Choice = in .next(); in .close();
if ("1".equals(Choice) || "Easy".equals(Choice) || "easy".equals(Choice) || "e".equals(Choice) || "E".equals(Choice)) {
int N = 9, K = 40;
SudokuPuzzle sudoku = new SudokuPuzzle(N, K);
sudoku.fillValues();
sudoku.printSudoku();
}
if ("2".equals(Choice) || "Medium".equals(Choice) || "medium".equals(Choice) || "m".equals(Choice) || "M".equals(Choice)) {
int N = 9, K = 60;
SudokuPuzzle sudoku = new SudokuPuzzle(N, K);
sudoku.fillValues();
sudoku.printSudoku();
}
if ("3".equals(Choice) || "Hard".equals(Choice) || "hard".equals(Choice) || "h".equals(Choice) || "H".equals(Choice)) {
int N = 9, K = 72;
SudokuPuzzle sudoku = new SudokuPuzzle(N, K);
sudoku.fillValues();
sudoku.printSudoku();
}
}
// Sudoku Generator
public void fillValues() {
// Fill the diagonal of SRN x SRN matrices
fillDiagonal();
// Fill remaining blocks
fillRemaining(0, SRN);
// Remove Randomly K digits to make game
removeKDigits();
}
// Fill the diagonal SRN number of SRN x SRN matrices
void fillDiagonal() {
for (int i = 0; i < N; i = i + SRN)
// for diagonal box, start coordinates->i==j
fillBox(i, i);
}
// Returns false if given 3 x 3 block contains num.
boolean unUsedInBox(int rowStart, int colStart, int num) {
for (int i = 0; i < SRN; i++)
for (int j = 0; j < SRN; j++)
if (mat[rowStart + i][colStart + j] == num)
return false;
return true;
}
// Fill a 3 x 3 matrix.
void fillBox(int row, int col) {
int num;
for (int i = 0; i < SRN; i++) {
for (int j = 0; j < SRN; j++) {
do {
num = randomGenerator(N);
}
while (!unUsedInBox(row, col, num));
mat[row + i][col + j] = num;
}
}
}
// Random generator
int randomGenerator(int num) {
return (int) Math.floor((Math.random() * num + 1));
}
// Check if safe to put in cell
boolean CheckIfSafe(int i, int j, int num) {
return (unUsedInRow(i, num) &&
unUsedInCol(j, num) &&
unUsedInBox(i - i % SRN, j - j % SRN, num));
}
// check in the row for existence
boolean unUsedInRow(int i, int num) {
for (int j = 0; j < N; j++)
if (mat[i][j] == num)
return false;
return true;
}
// check in the row for existence
boolean unUsedInCol(int j, int num) {
for (int i = 0; i < N; i++)
if (mat[i][j] == num)
return false;
return true;
}
// A recursive function to fill remaining
// matrix
boolean fillRemaining(int i, int j) {
// System.out.println(i+" "+j);
if (j >= N && i < N - 1) {
i = i + 1;
j = 0;
}
if (i >= N && j >= N)
return true;
if (i < SRN) {
if (j < SRN)
j = SRN;
} else if (i < N - SRN) {
if (j == (int)(i / SRN) * SRN)
j = j + SRN;
} else {
if (j == N - SRN) {
i = i + 1;
j = 0;
if (i >= N)
return true;
}
}
for (int num = 1; num <= N; num++) {
if (CheckIfSafe(i, j, num)) {
mat[i][j] = num;
if (fillRemaining(i, j + 1))
return true;
mat[i][j] = 0;
}
}
return false;
}
// Remove the K no. of digits to
// complete game
public void removeKDigits() {
int count = K;
while (count != 0) {
int cellId = randomGenerator(N * N);
// System.out.println(cellId);
// extract coordinates i and j
int i = (cellId / N);
int j = cellId % 9;
if (j != 0)
j = j - 1;
// System.out.println(i+" "+j);
if (mat[i][j] != 0) {
count--;
mat[i][j] = 0;
}
}
}
// Print sudoku
public void printSudoku() {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++)
System.out.print(mat[i][j] + " ");
System.out.println();
}
System.out.println();
}
}
What you got is probably a ArrayIndexOutOfBoundsException. That means at some point you try to access a field of an array outside its boundaries.
But I canĀ“t see where K could be responsible for that. Can you provide more information about the error? E.g. at which value you get it or in which line.
EDIT: The variable i int the removeKDigits() function exceeds the boundaries of the array if the random generator spits out the value 81.

Sudoku Generator Algorithm Malfunction

I have a project at school where I have to create a Sudoku Program. I have managed to get a Solver algorithm working but not a Generator. I spent a lot of time online to see if people had found ways to make a working one and I found a man named Mark Fredrick Graves, Jr. (https://www.youtube.com/user/mfgravesjr) who provided a very detailed code on the creation of a sudoku grid on his GitHub (https://github.com/mfgravesjr/finished-projects/tree/master/SudokuGridGenerator). However, I felt that using a one dimensional array was unnecessarily difficult in terms of finding the equations to access lines, columns and boxes. I therefore tried to translate his code into a two dimensional array but I am running into issues with some of his sorting methods and what some variables represent like "int step = (a%2==0? rowOrigin + j: colOrigin + j*9);". What I would like to know is how to translate the methods he uses from one dimensional arrays into two dimensional arrays. Below are the methods (code snippets) in question and my half attempt at translating it myself.
public int[] generateGrid(){
ArrayList<Integer> arr = new ArrayList<Integer>(9);
solvedGrid = new int[81];
for(int i = 1; i <= 9; i++) arr.add(i);
//loads all boxes with numbers 1 through 9
for(int i = 0; i < 81; i++){
if(i%9 == 0) {
Collections.shuffle(arr);
}
int perBox = ((i / 3) % 3) * 9 + ((i % 27) / 9) * 3 + (i / 27) * 27 + (i % 3);
solvedGrid[perBox] = arr.get(i%9);
}
//tracks rows and columns that have been sorted
boolean[] sorted = new boolean[81];
for(int i = 0; i < 9; i++){
boolean backtrack = false;
//0 is row, 1 is column
for(int a = 0; a<2; a++){
//every number 1-9 that is encountered is registered
boolean[] registered = new boolean[10]; //index 0 will intentionally be left empty since there are only number 1-9.
int rowOrigin = i * 9;
int colOrigin = i;
ROW_COL: for(int j = 0; j < 9; j++){
//row/column stepping - making sure numbers are only registered once and marking which cells have been sorted
int step = (a%2==0? rowOrigin + j: colOrigin + j*9);
int num = solvedGrid[step];
if(!registered[num]) {
registered[num] = true;
}else {
//if duplicate in row/column
//box and adjacent-cell swap (BAS method)
//checks for either unregistered and unsorted candidates in same box,
//or unregistered and sorted candidates in the adjacent cells
for(int y = j; y >= 0; y--){
int scan = (a%2==0? i * 9 + y: i + 9 * y);
if(solvedGrid[scan] == num){
//box stepping
for(int z = (a%2==0? (i%3 + 1) * 3: 0); z < 9; z++){
if(a%2 == 1 && z%3 <= i%3) {
continue;
}
int boxOrigin = ((scan % 9) / 3) * 3 + (scan / 27) * 27;
int boxStep = boxOrigin + (z / 3) * 9 + (z % 3);
int boxNum = solvedGrid[boxStep];
if((!sorted[scan] && !sorted[boxStep] && !registered[boxNum]) || (sorted[scan] && !registered[boxNum] && (a%2==0? boxStep%9==scan%9: boxStep/9==scan/9))){
solvedGrid[scan] = boxNum;
solvedGrid[boxStep] = num;
registered[boxNum] = true;
continue ROW_COL;
}else if(z == 8) {
//if z == 8, then break statement not reached: no candidates available
//Preferred adjacent swap (PAS)
//Swaps x for y (preference on unregistered numbers), finds occurence of y
//and swaps with z, etc. until an unregistered number has been found
int searchingNo = num;
//noting the location for the blindSwaps to prevent infinite loops.
boolean[] blindSwapIndex = new boolean[81];
//loop of size 18 to prevent infinite loops as well. Max of 18 swaps are possible.
//at the end of this loop, if continue or break statements are not reached, then
//fail-safe is executed called Advance and Backtrack Sort (ABS) which allows the
//algorithm to continue sorting the next row and column before coming back.
//Somehow, this fail-safe ensures success.
for(int q = 0; q < 18; q++){
SWAP: for(int b = 0; b <= j; b++){
int pacing = (a%2==0? rowOrigin+b: colOrigin+b*9);
if(solvedGrid[pacing] == searchingNo){
int adjacentCell = -1;
int adjacentNo = -1;
int decrement = (a%2==0? 9: 1);
for(int c = 1; c < 3 - (i % 3); c++){
adjacentCell = pacing + (a%2==0? (c + 1)*9: c + 1);
//this creates the preference for swapping with unregistered numbers
if((a%2==0 && adjacentCell >= 81)
|| (a%2==1 && adjacentCell % 9 == 0)) {
adjacentCell -= decrement;
}else {
adjacentNo = solvedGrid[adjacentCell];
if(i%3!=0
|| c!=1
|| blindSwapIndex[adjacentCell]
|| registered[adjacentNo]) {
adjacentCell -= decrement;
}
}
adjacentNo = solvedGrid[adjacentCell];
//as long as it hasn't been swapped before, swap it
if(!blindSwapIndex[adjacentCell]){
blindSwapIndex[adjacentCell] = true;
solvedGrid[pacing] = adjacentNo;
solvedGrid[adjacentCell] = searchingNo;
searchingNo = adjacentNo;
if(!registered[adjacentNo]){
registered[adjacentNo] = true;
continue ROW_COL;
}
break SWAP;
}
}
}
}
}
//begin Advance and Backtrack Sort (ABS)
backtrack = true;
break ROW_COL;
}
}
}
}
}
}
if(a%2==0) {
for(int j = 0; j < 9; j++) {
sorted[i*9+j] = true; //setting row as sorted
}
}else if(!backtrack) {
for(int j = 0; j < 9; j++) {
sorted[i+j*9] = true; //setting column as sorted
}
}else {//reseting sorted cells through to the last iteration
//backtrack = false;
for(int j = 0; j < 9; j++) {
sorted[i*9+j] = false;
}
for(int j = 0; j < 9; j++) {
sorted[(i-1)*9+j] = false;
}
for(int j = 0; j < 9; j++) {
sorted[i-1+j*9] = false;
}
for(int j = 0; j < 81; j++) {
sorted[j] = false;
}
i-=2;
}
}
}
if(!isPerfect(solvedGrid)) {
throw new RuntimeException("ERROR: Imperfect grid generated.");
}
return solvedGrid;
}
My code (unfinished)
public int[][] generateGrid(){
ArrayList<Integer> arr = new ArrayList<Integer>(9);
ArrayList<Integer> values = new ArrayList<Integer>(9);
solvedGrid = new int[9][9];
for(int i = 1 ; i <= 9; i++) {
arr.add(i);
values.add(i);
}
//Fill all boxes with number 1 to 9
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
if(j == 0) {
Collections.shuffle(arr);
}
solvedGrid[(i/3)*3+(j/3)][(i%3)*3+(j%3)] = arr.get(j);
}
}
//boolean[][] sorted = new boolean[9][9];
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
int[] rowColValues = new int[9];
rowColValues[j] = solvedGrid[0][j];
ArrayList<Integer> occurence = new ArrayList<Integer>();
for(int k = 0; k < rowColValues.length; k++) {
occurence.add((k+1), occurence.get(k+1)+1);
if(occurence.get(k+1) != 1) {
//swap with number in the box that isn't already in rowColValues
//Not sure how to do this...
//Create a method that takes the correct variables as parameters ?
break;
}
}
//Read the sudoku row then column wise and swap values that already exist in the column or row.
}
}
print2DGrid(solvedGrid);
return solvedGrid;
}

2d array that looks for the most repeated number within the array

I did try using an if/else statement which I left in but commented out so you can still see it. I realized the problem with the if/else is not only is it a brute force method but I don't think I'm covering every possible case. I figured there had to be a more elegant loop solution, but loops have never been my strong suit and I need help with writing it.
public class stuff {
public static int getMostRepeatedNumber(int[][] array) {
int num = 100;
if(array.length == 0){
num = -1;
}
int [] numberOfTimes = new int[9];
for(int i = 0; array.length > i; i++){
for(int j = 0; array[i].length > j; j++){
if(array[i][j] == 0){
numberOfTimes[0]++;
}
else if(array[i][j] == 1){
numberOfTimes[1]++;
}else if(array[i][j] == 2){
numberOfTimes[2]++;
}else if(array[i][j] == 3){
numberOfTimes[3]++;
}else if(array[i][j] == 4){
numberOfTimes[4]++;
}else if(array[i][j] == 5){
numberOfTimes[5]++;
}else if(array[i][j] == 6){
numberOfTimes[6]++;
}else if(array[i][j] == 7){
numberOfTimes[7]++;
}else if(array[i][j] == 8){
numberOfTimes[8]++;
}else if(array[i][j] == 9){
numberOfTimes[9]++;
}
}
}
for(int x = 0; x < array.length; x++){
while(numberOfTimes[x] > numberOfTimes[x+1]){
num = x;
break;
}
/* if(numberOfTimes[x] >= numberOfTimes[x+1] ){
num = 0;
}else if(numberOfTimes[x+1] >= numberOfTimes[x+2]){
num = 1;
}else if(numberOfTimes[x+2] >= numberOfTimes[x+3]){
num = 2;
}else if(numberOfTimes[x+3] >= numberOfTimes[x+4]){
num = 3;
}else if(numberOfTimes[x+4] >= numberOfTimes[x+5]){
num = 4;
}else if(numberOfTimes[x+5] >= numberOfTimes[x+6]){
num = 5;
}else if(numberOfTimes[x+6] >= numberOfTimes[x+7]){
num = 6;
}else if(numberOfTimes[x+7] >= numberOfTimes[x+8]){
num = 7;
}else if(numberOfTimes[x+8] >= numberOfTimes[x+9]){
num = 8;
}
else{
num = 9;
}*/
}
return num;
}
}
An array that has 100 rows such that each row is empty is an empty array; your program returns 100 in cases like that. You do not need a special case for that if you structure your program correctly.
Since you have single-digit positive numbers, all you need is an array of ten counts:
int[] counts = new int[10];
for (int r = 0 ; r != array.length ; r++) {
for (int c = 0 ; c != array[r].length ; c++) {
counts[array[r][c]]++;
}
}
At this point, you've got an array of ten counters. Look for the highest one:
int max = 0;
int val = -1;
for (int i = 0 ; i != 10 ; i++) {
if (counts[i] > max) {
max = counts[i];
val = i;
}
}
// If you did not see any number because the array was empty, val remains -1.
System.out.println(val);
You can replace the first if-else thing with this line of code:
numberOfTimes[array[i][j]]++;
As for your problem, you can use this code:
int max = 0;
for (int i = 0, i > numberOfTime.length, i++)
if (numberOfTimes[i] > max) {
max = numberOfTimes[i];
num = i;
}
It loops over the array looking for the biggest value, which is stored in max. It also stores the array index of the largest value in num, which is the final result.
If we're not guaranteed that the numbers are between 0 and 9,can it be done with less than 3 loops,like I did below
int maxCounter =0;
int counter = 0;
int currentElementRow = 0, currentElementCol = 0;
int maxOccurrence = 0;
for(int k = 0; k < arr.length * arr[0].length; k++){ //traverse the matrix as many times as elements you have in it- you check each element for number of occurrences
for(int i = 0; i < arr.length; i++){
for(int j = 0; j < arr[0].length; j++){
if(arr[i][j] == arr[currentElementCol][currentElementCol]){
counter++;
}
}
}
if(counter > maxCounter){
maxCounter = counter;
counter = 0;
maxOccurrence = arr[currentElementRow][currentElementCol];
}
if(currentElementCol <arr[0].length - 1){
currentElementCol++;
}
else{
currentElementCol = 0;
currentElementRow++;
}
counter = 0;
}
Your first loops can be simplified as simply:
for(int i = 0; array.length > i; i++){
for(int j = 0; array[i].length > j; j++){
numberOfTimes[array[i][j]]++;
}
}
.... because you have a pre-written guarantee that the values in the 2D array are between 0 and 9 (inclusive)

Categories