Java: Complete Sudoku Generator, what I am missing here? - java

I'm working on sudoku project and I found this:
http://www.codeproject.com/Articles/23206/Sudoku-Algorithm-Generates-a-Valid-Sudoku-in
I converted that code into java but I just can't see where I have made mistake...
It almost works but it still places few numbers on same lines.
I have been stuggling with this sudoku generator for some time, I just can't see where I have done mistake, first I converted that vb.net code to C# and it worked fine.
Here is my java code (I left out code that produces grid):
private static JTextField sudoku[][] = new JTextField[9][9];
public static List<Square> sudokuGrid = new ArrayList<Square>();
public static void GenerateGrid(){
Square[] Squares = new Square[81];
for(int i = 0; i <= 80; i++){
Squares[i] = new Square();
}
List<List<Integer>> available = new ArrayList<List<Integer>>();
int c = 0;
for(int x = 0; x <= 80; x++){
available.add(new ArrayList<Integer>());
for(int i = 1; i <= 9; i++){
available.get(x).add(i);
}
}
while(!(c == 81)){
if(available.get(c).size() != 0){
int i = GetRan(0, available.get(c).size() - 1);
int z = available.get(c).get(i);
if (Conflicts(Squares, Item(c, z)) == false){
Squares[c] = Item(c, z);
available.get(c).remove(i);
c += 1;
}else{
available.get(c).remove(i);
}
}else{
for (int y = 1; y <= 9; y++){
available.get(c).add(y);
}
Squares[c - 1] = new Square();
c -= 1;
}
int j = 0;
for (j = 0; j <= 80; j++)
{
sudokuGrid.add(Squares[j]);
}
}
}
private static boolean Conflicts(Square[] CurrentValues, Square test){
for (Square s : CurrentValues){
if ((s.Across != 0 && s.Across == test.Across) || (s.Down != 0 && s.Down == test.Down) || (s.Region != 0 && s.Region == test.Region)){
if (s.Value == test.Value){
return true;
}
}
}
return false;
}
private static Square Item(int n, int v){
Square functionReturnValue = new Square();
n += 1;
functionReturnValue.Across = GetAcrossFromNumber(n);
functionReturnValue.Down = GetDownFromNumber(n);
functionReturnValue.Region = GetRegionFromNumber(n);
functionReturnValue.Value = v;
functionReturnValue.Index = n - 1;
return functionReturnValue;
}
public static int GetAcrossFromNumber(int n){
int k = 0;
k = n % 9;
if (k == 0)
return 9;
else
return k;
}
public static int GetDownFromNumber(int n){
int k = 0;
if (GetAcrossFromNumber(n) == 9)
{
k = n / 9;
}
else
{
k = n / 9 + 1;
}
return k;
}
private static int GetRegionFromNumber(int n){
int k = 0;
int a = GetAcrossFromNumber(n);
int d = GetDownFromNumber(n);
if (1 <= a && a < 4 && 1 <= d && d < 4) {
k = 1;
} else if (4 <= a && a < 7 && 1 <= d && d < 4) {
k = 2;
} else if (7 <= a && a < 10 && 1 <= d && d < 4) {
k = 3;
} else if (1 <= a && a < 4 && 4 <= d && d < 7) {
k = 4;
} else if (4 <= a && a < 7 && 4 <= d && d < 7) {
k = 5;
} else if (7 <= a && a < 10 && 4 <= d && d < 7) {
k = 6;
} else if (1 <= a && a < 4 && 7 <= d && d < 10) {
k = 7;
} else if (4 <= a && a < 7 && 7 <= d && d < 10) {
k = 8;
} else if (7 <= a && a < 10 && 7 <= d && d < 10) {
k = 9;
}
return k;
}
public static int GetRan(int lower, int upper){
Random rand = new Random();
return rand.nextInt((upper - lower) + 1) + lower;
}
public void newGame() {
for (int x = 0; x <= 8; x++) {
for (int y = 0; y <= 8; y++) {
sudoku[x][y].setEditable(true);
sudoku[x][y].setText("");
}
}
sudokuGrid.clear();
GenerateGrid();
for(Square s : sudokuGrid){
for(int x = 0; x <= 8; x++){
for(int y = 0; y <= 8; y++){
int index = s.Index;
if(sudoku[x][y].getName().equals(String.valueOf(index))){
sudoku[x][y].setText(String.valueOf(s.Value));
}
}
}
}
}
class Square{
public int Across;
public int Down;
public int Region;
public int Value;
public int Index;
}
Some help please :)

If you look closely at the linked code in GenerateGrid:
int j = 0;
for (j = 0; j <= 80; j++)
{
sudokuGrid.add(Squares[j]);
}
should come after the while(c != 81) loop. In your code, it is inside the loop.
This means that you're adding too many squares to sudokuGrid. To check that this is happening, print the size of sudokuGrid at the end of the method -- it'll be a lot greater than 81.
Edit:
Also, there might be problems with the way you're displaying the board. Try this at the end of newGame, after the GenerateGrid call:
for(int x = 0; x <= 8; x++) {
for(int y = 0; y <= 8; y++) {
sudoku[x][y].setText("" + sudokuGrid.get(x * 9 + y).Value);
}
}

Related

How do I combine an Output of two for loops into a "table" format?

I used two for loops to convert miles to km and km to miles respectively for selected values. However the issue I am facing is that the output for the first for loop is not side by side with the output of the second table. Appreciate some help on this!
public static double miletoKilometer(double mile) {
double conversion = mile * 1.609;
return conversion;
}
public static double kilometerToMile(double km) {
double conversion2 = km / 1.609;
return conversion2;
}
public static void main(String[] args) {
int mileInput = 0;
double kmOutput = 0;
int kmInput = 0;
double mileOutput = 0;
int displayRow1 = 0;
int displayRow2 = 0;
System.out.print("Miles\tKilometres\tKilometres\tMiles \n");
for (int i = 0; i < 11; i++) {
if (i == 1 || i == 2 || i == 9 || i == 10) {
mileInput = i;
System.out.printf("\n" + i);
kmOutput = miletoKilometer(mileInput);
System.out.printf("\t %.3f\n", kmOutput);
}
}
for (int j = 0; j < 66; j++) {
if (j == 20 || j == 25 || j == 60 || j == 65) {
kmInput = j;
System.out.printf("\n\t\t " + j);
mileOutput = kilometerToMile(kmInput);
System.out.printf("\t\t%.3f", mileOutput);
}
}
}
Current Output:
enter image description here
Changing your loop to match the code below should put everything in the right order. Not the most elegant solution but it gets the job done.
int j = 0;
for (int i = 0; i < 11; i++) {
if (i == 1 || i == 2 || i == 9 || i == 10) {
mileInput = i;
System.out.printf("\n" + i);
kmOutput = miletoKilometer(mileInput);
System.out.printf("\t %.3f", kmOutput);
for (; j < 66; j++) {
if (j == 20 || j == 25 || j == 60 || j == 65) {
kmInput = j;
System.out.printf("\t\t " + j);
mileOutput = kilometerToMile(kmInput);
System.out.printf("\t\t%.3f\n", mileOutput);
j++;
break;
}
}
}
}

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();
}
}
}
}

Stack Overflow Error in a Self Calling Function in Java (Number of Islands)

I did some research on what causes a stack overflow errors, and I can conclude it is being caused by a recursive function in a program that is supposed to "count the number of islands" in an array. I understand what is causing the issue, but not sure why this is happening, or my main question is what to actually do about it. I found that if I slow down the program by having it repeatedly printing out something to the console, it works, but it takes forever to complete. Is there a way I can keep the program speed without the error, or a better way to solve the problem (search up "number of islands" to find the problem). Also, the array is two dimensional with a size of 1050 by 800.
public class NumOfIslands {
static boolean[][] dotMap = new boolean[1050][800];
static boolean visited[][] = new boolean[1050][800];
static int total = 0;
public static void main(String args[]) {
defineArrays();
run();
}
public static void findObjects(int xCord, int yCord) {
for(int y = yCord - 1; y <= yCord + 1; y++) {
for(int x = xCord - 1; x <= xCord + 1; x++) {
if(x > -1 && y > -1 && x < dotMap[0].length && y < dotMap.length) {
if((x != xCord || y != yCord) && dotMap[x][y] == true && visited[x][y] != true) {
visited[x][y] = true;
findObjects(x,y);
//System.out.println("test");
}
}
}
}
}
public static void defineArrays() {
for(int y = 0; y < 800; y++) {
for(int x = 0; x < 1050; x++) {
dotMap[x][y] = true;
}
}
}
public static int run() {
//dotMap = DisplayImage.isYellow;
System.out.println(dotMap.length + " " + dotMap[0].length);
int objects = 0;
for(int y = 439; y < 560/*dotMap[0].length*/; y++) {
for(int x = 70; x < 300/*dotMap.length*/; x++) {
if(dotMap[x][y] == true && visited[x][y] != true) {
visited[x][y] = true;
objects++;
findObjects(x,y);
}
}
}
System.out.println("total" + total);
System.out.println(objects);
return objects;
}
}
StackOverflowError reasons. In your example each call to findObjects adds 2 variables to the stack int x and int y from loops.
One of the fastest solution:
class Solution {
int m, n;
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0) {
return 0;
}
m = grid.length;
n = grid[0].length;
int counter = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == '1') {
visit(grid, i, j);
counter++;
}
}
}
return counter;
}
public void visit(char[][] grid, int i, int j) {
if (i < 0 || i >= m || j < 0 || j >= n) {
return;
}
if (grid[i][j] == '0') {
return;
}
grid[i][j] = '0';
visit(grid, i - 1, j);
visit(grid, i + 1, j);
visit(grid, i, j - 1);
visit(grid, i, j + 1);
}
}
All recursive algorithms can be implemented with loops. One of the example is below. The Solution implements BFS (Breadth-first search) algorithm, more details on wikipedia.
class Solution {
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0) {
return 0;
}
int nr = grid.length;
int nc = grid[0].length;
int num_islands = 0;
for (int r = 0; r < nr; ++r) {
for (int c = 0; c < nc; ++c) {
if (grid[r][c] == '1') {
++num_islands;
grid[r][c] = '0'; // mark as visited
Queue<Integer> neighbors = new LinkedList<>();
neighbors.add(r * nc + c);
while (!neighbors.isEmpty()) {
int id = neighbors.remove();
int row = id / nc;
int col = id % nc;
if (row - 1 >= 0 && grid[row-1][col] == '1') {
neighbors.add((row-1) * nc + col);
grid[row-1][col] = '0';
}
if (row + 1 < nr && grid[row+1][col] == '1') {
neighbors.add((row+1) * nc + col);
grid[row+1][col] = '0';
}
if (col - 1 >= 0 && grid[row][col-1] == '1') {
neighbors.add(row * nc + col-1);
grid[row][col-1] = '0';
}
if (col + 1 < nc && grid[row][col+1] == '1') {
neighbors.add(row * nc + col+1);
grid[row][col+1] = '0';
}
}
}
}
}
return num_islands;
}
}
the problem is in this function
public static void findObjects(int xCord, int yCord) {
for(int y = yCord - 1; y <= yCord + 1; y++) {
for(int x = xCord - 1; x <= xCord + 1; x++) {
if(x > -1 && y > -1 && x < dotMap[0].length && y < dotMap.length) {
if((x != xCord || y != yCord) && dotMap[x][y] == true && visited[x][y] != true) {
visited[x][y] = true;
findObjects(x,y);
//System.out.println("test");
}
}
}
}
}`
at here you are builiding a stack of recursive calls to findobjects and ultimately it has no termination condition so it ends up at infinite stacks of findobjects, so my solution is if you are just checking that if x and y varaibles are not equal and visited[x][y] is not true then there is no need to call for recursion just comment the recursive call, because your loop already do what you want the recursive call to do.
public static void findObjects(int xCord, int yCord) {
for(int y = yCord - 1; y <= yCord + 1; y++) {
for(int x = xCord - 1; x <= xCord + 1; x++) {
if(x > -1 && y > -1 && x < dotMap[0].length && y < dotMap.length) {
if((x != xCord || y != yCord) && dotMap[x][y] == true && visited[x][y] != true) {
visited[x][y] = true;
//findObjects(x,y);
//System.out.println("test");
}
}
}
}
}

How to refactor this java code [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
I have the below java method called solution, there are two large for loops, as you can see, the two for loops are very samilar, so I think it's possible to refactor the code by having a method like public int getElementSize(ArrayList<Integer> factor1, ArrayList<Integer> factor2) which does the work of the for loop, so I can just call the method twice with different parameters instead repeating the two for loop. But since these two for loops have different loop orders, one from head to tail, another one from tail to head, beside this, all other parts of the loop are the same, any ideas how to refactor this code?
class Solution {
public int solution(int[] A) {
ArrayList<Integer> factor1 = new ArrayList<Integer>();
ArrayList<Integer> factor2 = new ArrayList<Integer>();
int factor = 1;
int N = A.length;
while(factor * factor <= N){
if(N % factor == 0){
factor1.add(factor);
factor2.add(N / factor);
}
factor++;
}
for(int i = 1; i < factor2.size(); i++){
int blockSize = factor2.get(i);
int elementSize = factor1.get(i);
int peaks = 0;
for(int j = 0; j < blockSize; j++){
boolean hasPeak = false;
for(int k = elementSize * j; k < elementSize * (j + 1); k++){
if(k > 0 && k < N - 1){
if(A[k] > A[k - 1] && A[k] > A[k + 1])
hasPeak = true;
}
}
if(!hasPeak)
break;
else
peaks++;
}
if(peaks == blockSize)
return blockSize;
}
for(int i = factor1.size() - 1; i >= 0; i--){
int blockSize = factor1.get(i);
int elementSize = factor2.get(i);
int peaks = 0;
for(int j = 0; j < blockSize; j++){
boolean hasPeak = false;
for(int k = elementSize * j; k < elementSize * (j + 1); k++){
if(k > 0 && k < N - 1){
if(A[k] > A[k - 1] && A[k] > A[k + 1])
hasPeak = true;
}
}
if(!hasPeak)
break;
else
peaks++;
}
if(peaks == blockSize)
return blockSize;
}
return 0;
}
}
How about this?
Conditional operator, ? and : similar to, (these are called ternary operators and resolve at compile time to if else blocks)
if(condition) {
this();
} else {
that();
}
In the above, you can single line that as, (condition ? this() : that())
class Solution {
public int solution(int[] A) {
ArrayList<Integer> factor1 = new ArrayList<Integer>();
ArrayList<Integer> factor2 = new ArrayList<Integer>();
int factor = 1;
int N = A.length;
while(factor * factor <= N){
if(N % factor == 0){
factor1.add(factor);
factor2.add(N / factor);
}
factor++;
}
// let i = 0 to be factor2, i = 1 is factor 1
for(int i = 0; i < 2; i++) {
for(int x = (i == 0 ? 1 : factor1.size() - 1); (i == 0 ? x < factor2.size() : x >= 0); (i == 0 ? x++ : x--)){
int blockSize = (i == 0 ? factor2.get(x) : factor1.get(x));
int elementSize = (i == 0 ? factor1.get(x) : factor2.get(x));
int peaks = 0;
for(int j = 0; j < blockSize; j++){
boolean hasPeak = false;
for(int k = elementSize * j; k < elementSize * (j + 1); k++){
if(k > 0 && k < N - 1){
if(A[k] > A[k - 1] && A[k] > A[k + 1])
hasPeak = true;
}
}
if(!hasPeak)
break;
else
peaks++;
}
if(peaks == blockSize)
return blockSize;
}
}
return 0;
}
}
You can refactor the code inside the the for loops to the new method inside move the two big for loops to the new method, in this way, the order of the two loops are still independent, basically it looks like below, the correctness needs to be verified, this is just one idea to not repeat:
class Solution {
public int solution(int[] A) {
ArrayList<Integer> factor1 = new ArrayList<Integer>();
ArrayList<Integer> factor2 = new ArrayList<Integer>();
int factor = 1;
int N = A.length;
while(factor * factor <= N){
if(N % factor == 0){
factor1.add(factor);
factor2.add(N / factor);
}
factor++;
}
for(int i = 1; i < factor2.size(); i++){
int blockSize = factor2.get(i);
int elementSize = factor1.get(i);
int peaks = getElementSize(A, blockSize, elementSize); //call the method
if(peaks == blockSize)
return blockSize;
}
for(int i = factor1.size() - 1; i >= 0; i--){
int blockSize = factor1.get(i);
int elementSize = factor2.get(i);
int peaks = getElementSize(A, blockSize, elementSize); //call the method
if(peaks == blockSize)
return blockSize;
}
return 0;
}
//this method include the code which was repeated inside the loops
public int getElementSize(int[] A, int blockSize, int elementSize){
int peaks = 0;
int N = A.length;
for(int j = 0; j < blockSize; j++){
boolean hasPeak = false;
for(int k = elementSize * j; k < elementSize * (j + 1); k++){
if(k > 0 && k < N - 1){
if(A[k] > A[k - 1] && A[k] > A[k + 1])
hasPeak = true;
}
}
if(!hasPeak)
break;
else
peaks++;
}
return peaks;
}
}

Traversing a 2D array matrix diagonally from bottom left to upper right

I have a 3x4 matrix represented by a 2D array:
. 0 1 2 3
0 a c f i
1 b e h k
2 d g j l
and my approach to traverse the diagonal slice was to treat each slice as a sum, like this:
a = (0+0) = 0
b,c = (0+1),(1+0) = 1
d,e,f = (0+2),(1+1),(2+0) = 2
g,h,i = (1+2),(2+1),(3+0) = 3
j, k = (2+2),(3+1) = 4
l = (3+2) = 5
However, my code right now prints it in the opposite way that I want it to, which is from upper right to bottom left.
Current Output is:
acbfedihgkjl
Desired Output is:
abcdefghijkl
for (int sum = 0; sum <= numRows + numColumns - 2; sum++) {
for (int i = 0; i < numRows; i++) {
int j = sum - i;
if ((i >= 0 && i < numRows) && (j >= 0 && j < numColumns)) {
System.out.print(array[i][j]);
}
}
}
Can somebody point me in the right direction on how to fix my code to get the output that I want?
While it isn't very pretty, I think this will do it:
int i = 0;
int j = 0;
while (true) {
System.out.println("" + array[i][j]);
--i;
++j;
if (i < 0) {
if (j == numCols)
break;
i = Math.min(j, numRows - 1);
j = Math.max(j - numCols + 2, 0);
} else if (j >= numCols) {
if (i == numRows - 2)
break;
i = numRows - 1;
j = Math.max(j + 2 - numCols + i, 0);
}
}
int i = 0;
int j = 0;
int n = 0;
int x = 3;
int y = 4;
int newSize = Math.max(x,y) * Math.max(x,y);
while(n < newSize){
if(i <= x && j <= y)
System.out.println(array[i][j]);
n++;
if(i == 0) {
i = n:
j = 0;
} else {
--i;
++j;
}
}

Categories

Resources