There's something wrong in my Magic Square Algorithm - java

Hi I created a Magic Square program in java
It works fine if you input a number 3 but if i input 5 and so on
there's a problem occurring..
The pattern becomes wrong.
Please help me to find out what's wrong in my code:
Here's my code:
Scanner input = new Scanner(System.in);
System.out.print("Enter a number: ");
int num = input.nextInt();
// Number must be ODD and not less than or equals to one to continue
while ((num % 2 == 0) || (num <= 1)) {
System.out.println("Enter a valid number: ");
num = input.nextInt();
}
int[][] magic = new int[num][num];
int row = 0;
int col = num / 2;
magic[row][col] = 1;
for (int i = 2; i <= num * num; i++) {
if (magic[(row + 5) % num][(col + 2) % num] == 0) {
row = (row + 5) % num;
col = (col + 2) % num;
} else {
row = (row + 1 + num) % num;
}
magic[row][col] = i;
}
for (int x = 0; x < num; x++) {
for (int j = 0; j < num; j++) {
System.out.print(magic[x][j] + "\t");
}
System.out.println();
}
}
It's correct when i Input 3,
here's the output:
But when i type a number like 5:
It becomes:
UPDATED!

You seem to be trying to implement the Method for constructing a magic square of odd order.
The method prescribes starting in the central column of the first row with the number 1.
You seem to have that right.
After that, the fundamental movement for filling the squares is diagonally up and right, one step at a time.
I would code this as:
int newRow = row - 1;
int newCol = col + 1;
When an "up and to the right" move would leave the square, it is wrapped around to the last row or first column, respectively.
This is clearly:
if ( newRow < 0 ) {
newRow = num - 1;
}
if ( newCol > num - 1 ) {
newCol = 0;
}
If a filled square is encountered, one moves vertically down one square instead, then continues as before.
if (magic[newRow][newCol] != 0) {
newRow = row + 1;
newCol = col;
}
I know this doesn't actually solve your problem but I hope it gets you somewhere towards your goal. See how I take the words of the algorithm and match them as accurately as possible with code.

Related

How should I reconfigure the arrow "->" to not print when done with with my pathing?

I'm trying to create an optimal path to collect as many 1's as I can but after I execute my code, I still have an arrow pointing to nothing as there are no more places to go. How would I remove the arrow at the end of the code?
import java.util.Arrays;
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner s1 = new Scanner(System.in);
int n = s1.nextInt();
int m = s1.nextInt();
int mat[][] = new int[n][m];
for (int i = 0; i < mat.length; i++){
for (int j = 0; j < mat[0].length; j++){
mat[i][j] = s1.nextInt();
}
}
int path[][] = new int[n][m];
for (int i = 0; i < path.length; i++){
Arrays.fill(path[i], -1);
}
int maxCoins = util(0, 0, mat, path);
System.out.println("Max coins:" + maxCoins);
int row = 0, column = 0;
System.out.print("Path:");
while(row < mat.length && column < mat[0].length){
System.out.print("(" + (row + 1) + "," + (column + 1) + ")");
System.out.print("->");
if(row < n - 1 && column < m - 1){
int down = path[row + 1][column];
int right = path[row][column + 1];
if(down > right){
row += 1;
continue;
}
else if (right > down){
column += 1;
continue;
}
else{
row += 1;
continue;
}
}
if(row + 1 < n){
row += 1;
}
else{
column += 1;
}
}
}
private static int util(int row,int column,int mat[][], int path[][]){
if(row >= mat.length || column >= mat[0].length){
return 0;
}
if(path[row][column]!= -1){
return path[row][column];
}
int right = util(row, column + 1, mat,path);
int down = util(row + 1, column, mat,path);
path[row][column]=Math.max(right, down);
if(mat[row][column] == 1){
path[row][column] += 1;
}
return path[row][column];
}
}
My current input looks like:
5 6
0 0 0 0 1 0
0 1 0 1 0 0
0 0 0 1 0 1
0 0 1 0 0 1
1 0 0 0 1 0
And output is:
Max coins:5
Path:(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(3,4)->(3,5)->(3,6)->(4,6)->(5,6)->
I am just trying to remove the one at the end but unsure where to insert my code:
System.out.print("->");
Cleanest way would be using a StringJoiner.
You can use it as follows
StringJoiner joiner = new StringJoiner("->");
joiner.add("a");
joiner.add("b");
System.out.println(joiner); //prints a->b - you can use toString if you want to return a joined String
You can also define a prefix and suffix for your joined String.
Or if you are familiar with Streams, there is Collectors.joining("->") available.
Three solutions that come to mind:
Add another check inside the loop, and put your sysout -> thingy after that check.
Usually code would generate some kind of list or similar data about the results and return it. It's a lot simpler to print lists, because you know the length etc.
Another common solution is to use StringBuilder and correct it before generating the output with toString()
You could just do something like this:
if (!(row == mat.length - 1 && column == mat[0].length - 1)) {
System.out.print("->");
}
Or a little cleaner:
if (arrowIsNotAtTheEnd(mat, row, column)) {
System.out.print("->");
}
// ...
private static boolean arrowIsNotAtTheEnd(int[][] mat, int row, int column) {
return !(row == mat.length - 1 && column == mat[0].length - 1);
}
For java 8 and above, the String class already has a convenient join method.
CharSequence[] path=new CharSequence[]{
"(1,1)","(2,1)","(2,2)","(2,3)","(2,4)","(3,4)","(3,5)","(3,6)","(4,6)","(5,6)"};
String output=String.join("->",path);
System.out.println(output);
//output: (1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(3,4)->(3,5)->(3,6)->(4,6)->(5,6)

java random number generator without arrays

I am completely new to Java and working on an assignment. I need to generate 6 random numbers within the range of 1 - 49, which is simple.
However, the complication is that the numbers cannot duplicate.
The only options I have for conditionals are the while loop, or the if else statements.
Arrays and all other loops are off limits for this assignment.
Could really use some advice regarding logistics of how to apply the options I have. I realize without arrays, and the other loops that I'm going to have a lot of duplicate code but can handle that. I just need some help wrapping my head around this.
If you can't use arrays, or other collections, you can create 6 variables to save your generate numbers.
public class Generate6Number {
public static void main(String[] args) {
int num1 = 0;
int num2 = 0;
int num3 = 0;
int num4 = 0;
int num5 = 0;
int num6 = 0;
int count = 0;
while (count < 6) {
int numGen = (int) (Math.random() * 49);
if (numGen != num1 &&
numGen != num2 &&
numGen != num3 &&
numGen != num4 &&
numGen != num5) {
if (num1 == 0)
num1 = numGen;
else if (num2 == 0)
num2 = numGen;
else if (num3 == 0)
num3 = numGen;
else if (num4 == 0)
num4 = numGen;
else if (num5 == 0)
num5 = numGen;
else
num6 = numGen;
count++;
}
}
System.out.println("Number 1: " + num1);
System.out.println("Number 2: " + num2);
System.out.println("Number 3: " + num3);
System.out.println("Number 4: " + num4);
System.out.println("Number 5: " + num5);
System.out.println("Number 6: " + num6);
}
}
Set<Integer> values = new HashSet<>();
Random rand = new Random();
while (values.size() <= 6) {
int n = rand.nextInt(50) + 1;
values.add(n);
}
System.out.println(values);
like shuffling a card for first 6
public void shuffle() {
int[] array = new int[49];
for (int i = 0; i < array.length; i++) {
array[i] = i + 1;
}
// we need first 6 random cards
for (int i = 0; i < 6; i++) {
int index = (int) (Math.random() * (( array.length - i) + 1));
int temp = array[i];
array[i] = array[index];
array[index] = temp;
}
for (int i = 0; i < 6; i++) {
System.out.print("[" + array[i] + "]");
}
System.out.println();
}
This seems like a rather strange exercise to attempt without arrays. It is possible, but I don't think it is especially instructive for learning Java, as it is more a maths exercise than a programming one.
In order to generate 6 distinct random numbers in the range 1-49, you basically have to decide for each of those 49 numbers whether or not to "pick" it, with the constraint that you will only pick 6 numbers. So, you are looking to identify one of the choose(49, 6) possible combinations.
So, you can do it like this:
int numToPick = 6;
for (int i = 1; i <= 49; ++i) {
if (shouldPick(i, numToPick)) {
System.out.println(i);
--numToPick;
}
}
(I used a for loop; but you can always rewrite a for loop as a while loop if that's all you can use).
The question is just how to implement that shouldPick function: it returns a boolean true to mean that you should pick it, and will print it; or false to mean that you won't.
This is going to be a probabilistic function (i.e
it's going to use a random number generator), or it won't give you different sets of numbers each time.
The maths to work out the form of that function is quite fun, and the ultimate implementation is pleasingly trivial; but it wouldn't be fun if I gave the answer here.
(But I can assure you that I have implemented it, only changing one line in the above snippet; 2 if you count declaring a random number generator).
You effectively need to take out the already chosen possibility:
Random rand = new Random();
int first = rand.nextInt(49) + 1;
int second = rand.nextInt(48) + 1;
int third = rand.nextInt(47) + 1;
int fourth = rand.nextInt(46) + 1;
int fifth = rand.nextInt(45) + 1;
int sixth = rand.nextInt(44) + 1;
if (first <= second) second++;
if (first <= third) third++;
if (first <= fourth) fourth++;
if (first <= fifth) fifth++;
if (first < sixth) sixth++;
if (second <= third) third++;
if (second <= fourth) fourth++;
if (second <= fifth) fifth++;
if (second <= sixth) sixth++;
if (third <= fourth) fourth++;
if (third <= fifth) fifth++;
if (third <= sixth) sixth++;
if (fourth <= fifth) fifth++;
if (fourth <= sixth) sixth++;
if (fifth <= sixth) sixth++;

Java: How to move a knight on a chessboard until no possible moves are left

I have an assignment to have a knight move around the chessboard until it either completes a full tour or has no where else to go.
im having a problem figuring out how to have it actually stop after there are no more moves. I have the algorithm for the movement down, as well as bounds checking on the chessboard.
setting the loop count to 64 just times out, because the program will try to continually find a spot that doesn't exist if a perfect tour isn't created.
two ideas I have had to fix this is to either increment a variable every time a certain position is checked around a certain spot, and if all possible moves are taken by a previous move, terminate the program. Problem is I have no idea how to actually do this.
A second idea I had is to have the program quit the for loop after 2 seconds(during which the for loop will check each position way more than once) but I feel like my professor would crucify me upside down if I did that
here is my code:
import apcslib.*; //this is only for Format()
public class ktour
{
int[][] kboard = new int[9][9];
int[] vert = new int[9];
int[] horiz = new int[9];
ktour()
{
vert[1] = -2;vert[2] = -1;vert[3] = 1;vert[4] = 2;vert[5] = 2;vert[6] = 1;vert[7] = -1;vert[8] = -2;
horiz[1] = 1;horiz[2] = 2;horiz[3] = 2;horiz[4] = 1;horiz[5] = -1;horiz[6] = -2;horiz[7] = -2;horiz[8] = -1;
path();
}
public void path()
{
int row = 1;
int col = 1;
int loops = 10; //i have this set to 10 for now
int col2 = 1;
int row2 = 1;
int r = (int)(Math.random() * (8) +1); //returns a random from 1 to 9
//System.out.println(r);
kboard[col][row] = 1;
for(int x = 2; x < loops; x++) //this runs the bounds check and places each number for the amount that loops is
{
r = (int)(Math.random() * (8) +1);
col = col2;
row = row2;
col = col + vert[r];
row = row + horiz[r];
while(col <= 0 || col > 8 || row <= 0 || row > 8) //bounds check, will keep running until both row and columb is in the board
{
r = (int)(Math.random() * (8) + 1);
col = col2;
row = row2;
col = col + vert[r];
row = row + horiz[r];
}
if(kboard[col][row] == 0)
{
kboard[col][row] = x;
row2 = row;
col2 = col;
}
else
{
x--; //if the above if is false and a number already occupies the generated spot, x is decremented and the program tries again
}
}
printboard();
}
public void printboard()
{
for(int y = 1; y < 9; y++)
{
System.out.println();
for(int x = 1; x < 9; x++)
{
System.out.print(Format.right(kboard[y][x],3));
}
}
}
}
I was able to fix my lab with the following code. I created a variable called count which I used to check if at any move there were no more moves left. As there are only 8 moves, when the variable reached 9 the code terminated, and printed up to the point it got to.
I had to put multiple if statements excluding r = math.random if count was not 0, meaning I was checking r 1-9, aka every possible move. Therefore, I couldn't use a randomizer, I had to traverse all 8 possible moves.
I also ran into problems when I reached the line where it checks if kboard[col][row] == 0. if you were running through a loop with count greater than 1, it was possible that col or row could be out of bounds, due to lack of a randomizer in the bounds checker. If left without a break, the bounds checker would run forever without a random number generated every time. I fixed this by adding an if statement that allowed the program to proceed if col and row were inside the board. if they were not, x was decremented and count was increased again, signifying a failed attempt.
This way I was able to check all possible moves, disregarding whether or not they were inside the board.
public void path()
{
int row = 1;
int col = 1;
int loops = 64; //i have this set to 10 for now
int col2 = 1;
int row2 = 1;
int count = 0;
boolean end = false;
int r = (int)(Math.random() * (8) +1); //returns a random from 1 to 9
//System.out.println(r);
kboard[col][row] = 1;
for(int x = 2; x < loops; x++) //this runs the bounds check and places each number for the amount that loops is
{
if(count == 0)
r = (int)(Math.random() * (8) +1);
if(count >= 1 && r != 8)
r++;
col = col2;
row = row2;
col = col + vert[r];
row = row + horiz[r];
while(col <= 0 || col > 8 || row <= 0 || row > 8) //bounds check, will keep running until both row and columb is in the board
{
if(count == 0)
r = (int)(Math.random() * (8) + 1);
col = col2;
row = row2;
col = col + vert[r];
row = row + horiz[r];
if(count >= 1)
break;
}
end = false;
if(r == 8 || r == 9)
r = 1;
if(count >= 9)
{
System.out.println("Halting... no where else to go");
loops = 0;
}
if(!(col <= 0 || row <= 0 || row > 8 || col > 8))
{
if(kboard[col][row] == 0)
{
kboard[col][row] = x;
row2 = row;
col2 = col;
count = 0;
}
else
{
count++;
x--; //if the above if is false and a number already occupies the generated spot, x is decremented and the program tries again
}
}
else
{
count++;
x--;
}
}
printboard();
}

Magic Square preferred output

I have an assignment about MAGIC SQUARE:
But i need to rewrite it.
This is my code at the moment:
Scanner input = new Scanner(System.in);
System.out.print("Enter a number: ");
int num= input.nextInt();
//Number must be ODD and not less than or equals to one to continue
while((num%2==0)||(num<=1)){
System.out.println("Enter a valid number: ");
num= input.nextInt();
}
int[][] magic = new int[num][num];
int row = num-1;
int col = num/2;
magic[row][col] = 1;
for (int i = 2; i <= num*num; i++) {
if (magic[(row + 1) % num][(col + 1) % num] == 0) {
row = (row + 1) % num;
col = (col + 1) % num;
}
else {
row = (row - 1 + num) % num;
// don't change col
}
magic[row][col] = i;
}
// print results
for (int i = 0; i < num; i++) {
for (int j = 0; j < num; j++) {
if (magic[i][j] < 10) System.out.print(" "); // for alignment
if (magic[i][j] < 100) System.out.print(" "); // for alignment
System.out.print(magic[i][j] + " ");
}
System.out.println();
}
Currently, my program output is:
My expected/desired output:
What I need is for the starting number (1) to be in the upper middle of the row x col then the pattern is up then left.
If the starting number should be the upper element is the only condition you are missing then iterating the print result row loop in reverse order will solve the problem. So instead of printing rows in order 0, 1, 2, ..., n, try to print rows in order n, n-1, n-2, ..., 1, 0.
Apply same logic to columns to get the output same as the goal output.

How to print out an X using nested loops

I have searched through to find a simple solution to this problem.
I have a method called
printCross(int size,char display)
It accepts a size and prints an X with the char variable it receives of height and width of size.
The calling method printShape(int maxSize, char display) accepts the maximum size of the shape and goes in a loop, sending multiples of 2 to the printCross method until it gets to the maximum.
Here is my code but it is not giving me the desired outcome.
public static void drawShape(char display, int maxSize)
{
int currentSize = 2; //start at 2 and increase in multiples of 2 till maxSize
while(currentSize<=maxSize)
{
printCross(currentSize,display);
currentSize = currentSize + 2;//increment by multiples of 2
}
}
public static void printCross(int size, char display)
{
for (int row = 0; row<size; row++)
{
for (int col=0; col<size; col++)
{
if (row == col)
System.out.print(display);
if (row == 1 && col == 5)
System.out.print(display);
if (row == 2 && col == 4)
System.out.print(display);
if ( row == 4 && col == 2)
System.out.print(display);
if (row == 5 && col == 1)
System.out.print(display);
else
System.out.print(" ");
}
System.out.println();
}
}
Is it because I hardcoded the figures into the loop? I did a lot of math but unfortunately it's only this way that I have been slightly close to achieving my desired output.
If the printCross() method received a size of 5 for instance, the output should be like this:
x x
x x
x
x x
x x
Please I have spent weeks on this and seem to be going nowhere. Thanks
The first thing you have to do is to find relationships between indices. Let's say you have the square matrix of length size (size = 5 in the example):
0 1 2 3 4
0 x x
1 x x
2 x
3 x x
4 x x
What you can notice is that in the diagonal from (0,0) to (4,4), indices are the same (in the code this means row == col).
Also, you can notice that in the diagonal from (0,4) to (4,0) indices always sum up to 4, which is size - 1 (in the code this is row + col == size - 1).
So in the code, you will loop through rows and then through columns (nested loop). On each iteration you have to check if the conditions mentioned above are met. The logical OR (||) operator is used to avoid using two if statements.
Code:
public static void printCross(int size, char display)
{
for (int row = 0; row < size; row++) {
for (int col = 0; col < size; col++) {
if (row == col || row + col == size - 1) {
System.out.print(display);
} else {
System.out.print(" ");
}
}
System.out.println();
}
}
Output: (size = 5, display = 'x')
x x
x x
x
x x
x x
Instead of giving a direct answer, I will give you some hints.
First, you are right to use nested for loops.
However as you noticed, you determine when to print 'x' for the case of 5.
Check that 'x' is printed if and only if row = col or row + col = size - 1
for your printCross method, try this:
public static void printCross(int size, char display) {
if( size <= 0 ) {
return;
}
for( int row = 0; row < size; row++ ) {
for( int col = 0; col < size; col++ ) {
if( col == row || col == size - row - 1) {
System.out.print(display);
}
else {
System.out.print(" ");
}
}
System.out.println();
}
}
ah, I got beaten to it xD
Here's a short, ugly solution which doesn't use any whitespace strings or nested looping.
public static void printCross(int size, char display) {
for (int i = 1, j = size; i <= size && j > 0; i++, j--) {
System.out.printf(
i < j ? "%" + i + "s" + "%" + (j - i) + "s%n"
: i > j ? "%" + j + "s" + "%" + (i - j) + "s%n"
: "%" + i + "s%n", //intersection
display, display
);
}
}
Lte's try this simple code to print cross pattern.
class CrossPattern {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.println("enter the number of rows=column");
int n = s.nextInt();
int i, j;
s.close();
for (i = 1; i <= n; i++) {
for (j = 1; j <= n; j++) {
if (j == i) {
System.out.print("*");
} else if (j == n - (i - 1)) {
System.out.print("*");
} else {
System.out.print(" ");
}
}
System.out.println();
}
}
}

Categories