Java Loop star pattern - algorithm optimalization - java

Can anyone tell me what is the more elegant solution for outputting this pattern?
I most interested in my makeTemplate method, but any other help will be appreciated.
Here is my code, which i want to be more readable:
public class Main {
public static void makeTemplate(char tab[][], int rows, int col) {
boolean increase = true;
int j = 0;
char star = '*';
for (int i = 0; i < rows; i++) {
if (increase) {
tab[i][j] = star;
if (j >= col - 1) {
increase = false;
j--;
continue;
}
j++;
} else {
tab[i][j] = star;
if (j < 0 + 1) {
increase = true;
j++;
continue;
}
j--;
}
}
}
public static void main(String[] args) {
char[][] tab = new char[30][6];
makeTemplate(tab, 30, 6);
for (int i = 0; i < 30; i++) {
for (int j = 0; j < 6; j++) {
System.out.print(tab[i][j]);
}
System.out.println();
}
}
}

Only made some changes to makeTemplate
public static void makeTemplate(char tab[][], int rows, int col) {
boolean increase = true;
int j = 0;
char star = '*';
for (int i = 0; i < rows; i++) {
tab[i][j] = star;
if (increase) {
if (j >= col - 1) {
increase = false;
j--;
} else {
j++;
}
} else {
if (j < 1) {
increase = true;
j++;
}else {
j--;
}
}
}
}
Replaced the continue statements with else as the continue statement pretty much does the same thing as the else. Using continue in the if statement says to skip the j++ or j-- below. So instead the j++ or j-- will only be executed if the if is true.
I also changed if(j < 0 + 1) to if(j < 1) as 0+1 = 1
Moved tab[i][j] = star; before the first if as it is the first line in the if and else - Thanks Betlista

Elegant java8 solution:
IntStream.range(0, ROWS).forEach(i -> {
int cur = i % (COLS * 2);
if(cur < 6) {
IntStream.range(0, cur).forEach(f -> System.out.print(" "));
} else {
IntStream.range(0, COLS - cur % COLS).forEach(f -> System.out.print(" "));
}
System.out.println("*");
});
Granted, I haven't used the makeTemplate() method but as far as elegance and understand-ability goes, this does the job well.

You can use recursion
public static char[][] makeTemplate(char tab[][], int rows, int col, int curRow, int curPos, boolean increase) {
if (curRow == rows)
return tab;
tab[curRow][curPos] = '*';
if (increase && curPos + 1 == col) {
increase = false;
} else if (curPos == 0) {
increase = true;
}
return makeTemplate(tab, rows, col, curRow + 1, (increase) ? ++curPos : --curPos, increase);
}
public static void main(String[] args) {
char[][] tab = makeTemplate(new char[30][6], 30, 6, 0, 0, true);
for (int i = 0; i < 30; i++) {
for (int j = 0; j < 6; j++) {
System.out.print(tab[i][j]);
}
System.out.println();
}
}

Related

Java - How do I make a thick square of stars with a 4x4 hollow section in the middle?

I'm struggling to know what to put in the if section
System.out.println("\\n");
for (int x = 0; x < 12; x++) {
for(int t = 0; t < 12; t++) {
********** if(x >= 4 || t >= 4 || x <= 4 || t <= 4 ) { *****************
System.out.print(" * ");
}
else {
System.out.print(" ");
}
}//end inner loop
System.out.println();
}//end outer loop
What I'm trying to accomplish:
With this you can set the size and the gap of the inner square. There's no error checking, so that would be on you.
public static void printSquare(int size, int gap, char c) {
StringBuilder builder = new StringBuilder();
int start = (int) (size/2 - gap/2);
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (j > 0) {
builder.append(' ');
}
if (i >= start
&& i < start+gap
&& j >= start
&& j < start+gap) {
builder.append(' ');
} else {
builder.append(c);
}
if (j < size -1) {
builder.append(' ');
}
}
builder.append(System.lineSeparator());
}
System.out.println(builder);
}
public static void main(String[] args) {
printSquare(12, 4, '*');
}

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.

My Merge Sort code is not working (Java)

I have just written up this code an have been trying for ages to try and find out why it is not printing the sorted list. It is running and there are no bugs, except it just does not print out the sorted list. Can you please help me find whats wrong?
public class Merging {
public static void main(String[] args) {
int[] a = new int[10];
populate(a);
printA(a);
a = merge_sort(a);
printA(a);
}
public static int[] merge_sort(int[] B) {
if (B.length <= 1) {
return B;
}
int midpoint = B.length / 2;
int[] left = new int[midpoint];
int[] right= new int[B.length-midpoint];
int[] result;
for (int i = 0; i < midpoint; i++) {
left[i] = B[i];
}
int x = 0;
for (int j = midpoint; j < B.length; j++) {
if (x < right.length) {
right[x] = B[j];
x++;
}
}
left = merge_sort(left);
right = merge_sort(right);
result = merge(left, right);
return result;
}
public static int[] merge(int[] left, int[] right) {
int lengthResult = left.length + right.length;
int[] result = new int[lengthResult];
int indexL = 0;
int indexR = 0;
int indexRes = 0;
while (indexL < left.length || indexR < right.length) {
if (indexL < left.length && indexR < right.length) {
if (left[indexL] <= right[indexR]) {
result[indexRes] = left[indexL];
indexL++;
indexRes++;
} else {
result[indexRes] = right[indexR];
indexR++;
indexRes++;
}
} else if (indexL < left.length) {
result[indexRes] = left[indexL];
indexL++;
indexRes++;
}
}
return result;
}
public static void printA(int[] B) {
for (int i = 0; i < B.length; i++) {
System.out.print(B[i] + " ");
}
}
public static int[] populate(int[] B) {
for (int i = 0; i < B.length; i++) {
B[i] = (int) (Math.random() * 100);
}
return B;
}
}
imagine the case in your loop, where indexL < left.length == false but indexR < right.length == true, you never increase indexR and the loop will never terminate

Sudoku Checker java

public class Sudoku {
public static void main(String[] args) {
// Row and column Latin but with invalid subsquares
String config1 = "1234567892345678913456789124567891235678912346" + "78912345789123456891234567912345678";
String[][] puzzle1 = makeSudoku(config1);
if (isValidSudoku(puzzle1)) {
System.out.println("This puzzle is valid.");
} else {
System.out.println("This puzzle is invalid.");
}
System.out.println(getPrintableSudoku(puzzle1));
System.out.println("--------------------------------------------------");
// Row Latin but column not Latin and with invalid subsquares
String config2 = "12345678912345678912345678912345678912345678" + "9123456789123456789123456789123456789";
String[][] puzzle2 = makeSudoku(config2);
if (isValidSudoku(puzzle2)) {
System.out.println("This puzzle is valid.");
} else {
System.out.println("This puzzle is invalid.");
}
System.out.println(getPrintableSudoku(puzzle2));
System.out.println("--------------------------------------------------");
// A valid sudoku
String config3 = "25813764914698532779324685147286319558149273663" + "9571482315728964824619573967354218";
String[][] puzzle3 = makeSudoku(config3);
if (isValidSudoku(puzzle3)) {
System.out.println("This puzzle is valid.");
} else {
System.out.println("This puzzle is invalid.");
}
System.out.println(getPrintableSudoku(puzzle3));
System.out.println("--------------------------------------------------");
}
public static String[][] makeSudoku(String s) {
int SIZE = 9;
int k = 0;
String[][] x = new String[SIZE][SIZE];
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
x[i][j] = s.substring(k, k + 1);
k++;
}
}
return x;
}
public static String getPrintableSudoku(String[][] x) {
int SIZE = 9;
String temp = "";
for (int i = 0; i < SIZE; i++) {
if ((i == 3) || (i == 6)) {
temp = temp + "=================\n";
}
for (int j = 0; j < SIZE; j++) {
if ((j == 3) || (j == 6)) {
temp = temp + " || ";
}
temp = temp + x[i][j];
}
temp = temp + "\n";
}
return temp;
}
//sudoku validation
public static boolean isValidSudoku(String[][] x) {
return rowsAreLatin(x) && colsAreLatin(x) && goodSubsquares(x);
}
public static boolean rowsAreLatin(String[][] x) {
// fill in your code here
boolean result = true; // Assume rows are latin
for (int i = 0; i < 9; i++) {
result = result && rowIsLatin(x, i); // Make sure each row is latin
}
return result;
}
public static boolean rowIsLatin(String[][] x, int i) {
boolean[] found = new boolean[9];
for (int j = 0; j < 9; j++) {
found[Integer.parseInt(x[i][j])] = true;
}
for (int j = 0; j < 9; j++) {
if (!found[j]) {
return false;
}
}
return true;
}
public static boolean colsAreLatin(String[][] x) {
// fill in your code here
boolean result = true; // Assume cols are latin
for (int j = 0; j < 9; j++) {
result = result && colIsLatin(x, j); // Make sure each row is latin
}
return result;
}
public static boolean colIsLatin(String[][] x, int j) {
// fill in your code here
boolean[] found = new boolean[9];
for (int i = 0; i < 9; i++) {
found[Integer.parseInt(x[i][j])] = true;
}
for (int i = 0; i < 9; i++) {
if (!found[i]) {
return false;
}
}
return true;
}
public static boolean goodSubsquares(String[][] x) {
return true;
}
public static boolean goodSubsquare(String[][] x, int i, int j) {
boolean[] found = new boolean[9];
// We have a 3 x 3 arrangement of subsquares
// Multiplying each subscript by 3 converts to the original array subscripts
for (int p = i * 3, rowEnd = p + 3; p < rowEnd; p++) {
for (int q = j * 3, colEnd = q + 3; q < colEnd; q++) {
found[Integer.parseInt(x[p][q])] = true;
}
}
for (int p = 0; p < 9; p++) {
if (!found[p]) {
return false;
}
}
return true;
}
}
This the error I am getting. Help!
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 9
at Sudoku.rowIsLatin(Sudoku.java:104)
at Sudoku.rowsAreLatin(Sudoku.java:93)
at Sudoku.isValidSudoku(Sudoku.java:85)
at Sudoku.main(Sudoku.java:8)
Java Result: 1
The problem is with the line:
Integer.parseInt(x[i][j])
Sudoku numbers range from [1, 9], but indices for an array (of length 9) range from [0, 8]. So, when the (i, j) element is a 9, the index is 9 and therefore the IndexOutOfBoundsException is being thrown.
You'll have to change it to
found[Integer.parseInt(x[i][j]) - 1] = true;
Note that you also make the same mistake in the column's respective method.

Project Euler #23 in Java

I've spent quite a while working on Problem #23 on Project Euler.
The answer the program below gives me is 4190428, and I can't figure out why.
I think it's probably a one or two character mistake somewhere.
public long problem23() {
ArrayList<Integer> abundantNumbers = new ArrayList<Integer>();
int limit = 28123;
for(int i = 2; i < limit; i++) {
if(isAbundantNum(i)) {
abundantNumbers.add(i);
}
}
boolean [] abundantSum = new boolean [limit+1];
for(int a = 0; a < abundantNumbers.size(); a++) {
for(int b = 1; b < abundantNumbers.size(); b++) {
int temp = abundantNumbers.get(a) + abundantNumbers.get(b);
if(temp <= limit) {
abundantSum[temp] = true;
} else {
break;
}
}
}
long sum = 0;
for(int i = 1; i <= limit; i++) {
if(!abundantSum[i]) {
sum += i;
}
}
return sum;
}
public boolean isAbundantNum(int n) {
int factorSum = 1;
for(int i = 2; i < Math.sqrt(n); i++) {
if(n%i == 0) {
factorSum += i; factorSum += n/i;
}
}
if(factorSum > n) {
System.out.println(n);
return true;
}
return false;
}
Edit: Added isAbundantNum(int n) method.
You have 2 bugs...
for(int b = 1; b < abundantNumbers.size(); b++) {
'b' should start at zero not 1
for(int i = 2; i < Math.sqrt(n); i++) {
if(n%i == 0) {
factorSum += i; factorSum += n/i;
}
}
Factoring like that gives you duplicates (like 2*2 = 4, you're getting both 2s).
Try something like:
for(int i = 2; i < n; i++) {
if(n%i == 0) {
factorSum += i;
}
}
Here is another implementation:
import java.util.ArrayList;
import java.util.List;
public class P23 {
final static int MIN = 12;
final static int MAX = 28123;
static boolean numbers[] = new boolean[MAX+1];
static List<Integer> abundantNumbers = new ArrayList();
public static void main(String args[]) {
generateAbundants(MIN, MAX);
int size = abundantNumbers.size();
for (int i = 0; i < size; i++) {
for (int j = i; j < size; j++) {
int current = abundantNumbers.get(i) + abundantNumbers.get(j);
if (current <= MAX) {
numbers[current] = true;
} else {
break;
}
}
}
long sum = 0;
for (int i = 1 ; i <= MAX ; i++ ) {
if ( numbers[i] == false ) {
sum += i;
}
}
System.out.println(sum);
}
private static int sumOfProperDivisors(int x) {
int sum = 1;
int squareRoot = (int) Math.sqrt(x);
for (int i = 2; i <= squareRoot; i++) {
if (x % i == 0) {
sum += i;
sum += x / i;
}
}
// if x is a perfect square, it's square root was added twice
if (squareRoot * squareRoot == x) {
sum -= squareRoot;
}
return sum;
}
private static boolean isAbundant(int x) {
if (x < sumOfProperDivisors(x)) {
return true;
}
return false;
}
private static void generateAbundants(int min, int max) {
for (int i = min; i < max; i++) {
if (isAbundant(i)) {
abundantNumbers.add(i);
}
}
}
}
Time: 455 ms
Explanation:
The default value for j is i. You can take j = 0 ( as Ted Bigham said -> b in that case ), because it will work, but it will take into consideration every number twice ( 12+20 = 20+12 ). It's more efficient to start from i. Why isn't it good to start from 1? Because you can loose solutions: in my example 24 = 12 + 12.
Regarding the for loop containing the divisors part, you can use the approach containing sqrt because it's more efficient ( O(sqrt(n)) instead of O(n) ), but you have to adjust it. In my example you can see that I have <= squareRoot because if I don't use =, it will skip some values ( E.g.: 6 is divisor for 36, but you don't include it in your solution ). Because I counted 6 twice, I remove one of those roots. Of course that Ted's method is good, but sometimes it's better to have an improved performance, even if the simplicity is affected.

Categories