Is there something wrong with my Magic Square Code? - java

A brief explanation: With the code below it will make a randomly generated Square and some code below would make sure that it was a Magic Square, in which the sum of the elements in each row, column, and the two diagonals are the same value.
My teacher said at maximum it should take three minutes to generate a magic square. So all I ask is there anything that can be done to improve or fix this code, please?
import java.util.ArrayList;
import java.util.Random;
class Main {
public static void main(String[] args) {
int size = 9;
int N = 3;
boolean result = true;
ArrayList<Integer> list = new ArrayList<Integer>(size);
int[][] mat = new int[N][N];
while (result) {
for (int i = 1; i <= size; i++) {
list.add(i);
}
Random rand = new Random();
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
int index = rand.nextInt(list.size());
System.out.print(list.remove(index)+" ");
}
System.out.println();
}
System.out.println();
// Checking process
// sumd1 and sumd2 are the sum of the two diagonals
int sumd1 = 0, sumd2 = 0;
for (int i = 0; i < N; i++) {
// (i, i) is the diagonal from top-left -> bottom-right
// (i, N - i - 1) is the diagonal from top-right -> bottom-left
sumd1 += mat[i][i];
sumd2 += mat[i][N - 1 - i];
}
// if the two diagonal sums are unequal then it is not a magic square
if (sumd1 != sumd2)
result = false;
// calculating sums of Rows and columns and checking if they are equal to each other,as well as equal to diagonal sum or not
for (int i = 0; i < N; i++) {
int rowSum = 0, colSum = 0;
for (int j = 0; j < N; j++) {
rowSum += mat[i][j];
colSum += mat[j][i];
}
if (rowSum != colSum || colSum != sumd1)
result=false;
}
result = true;
}
}
}

Trying with random numbers to coincidentally find a solution is deadly slow.
If you have the numbers 1 to 9, its entire sum 1+2+3+...+8+9 is 9*(1+9)/2 = 45.
As you have 3 rows and 3 colums, a row and column must sum upto 45/3 = 15.
Now that should restrict the number of possibilities.
So you must build in some intelligence in the code. Avoid random numbers as they do not even guarantee you'll find a solution in hundred years.
If you already treated recursion, that would be the easiest way to try all possibly valid combinations.
If you already treated Set, a BitSet maybe might be useful for a row, column or diagonal.
If you find it hard to code walking through all possibilities, you might hold the 2 dimensional matrix in a 1 dimensional array int[N*N], and have N (rows) + N (columns) + 2 (diagonals) arrays of N indices.
And of course I will not spoil your fun and satisfaction finding a smart solution.
Work it out on paper first.

Related

Adding rows, columns, diagonals in a 2D array (java)

import java.util.Scanner;
class Main
{
public static void main(String args[])
{
int i, j;
Scanner reader = new Scanner (System.in);
int array[][] = new int[4][4];
System.out.println("Enter Numbers: ");
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
array[i][j] = reader.nextInt();
System.out.println("Square: ");
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
System.out.print(array[i][j] + " ");
System.out.println();
}
}
}
I have this code written in java that asks a user for 16 numbers and then prints the numbers in a 4x4 array. I have to find the sum of each individual column and each individual row and of each individual diagonal. I am not sure how to do that.
I do not know what you are even trying to do in your code, you just input and print 4x4 array. In java arrays are fixed you can use ArrayList and other built in classes to do this in easier way. This algorithm would be a good way for variable size of inputs since 4 can be replaced by any value:
int matrixWidthHeight = 4;
int rowSum[matrixWidthHeight];
int columnSum[matrixWidthHeight];
for (int i = 0; i < matrixWidthHeight; ++i) {
for (int j = 0; j < matrixWidthHeight; ++j)
rowSum[i] += arr[i][j];
for (int j = 0; j < matrixWidthHeight; ++j)
rowSum[i] += arr[j][i];
sumDiagonal1 += arr[i][matrixWidthHeight - i]; // / diagonal sum
sumDiagonal2 += arr[matrixWidthHeight - i][i]; // \ diagonal sum
}
I do not know how Java works behind the seen, but for array size of 4 you can do:
int rowSum[4];
int columnSum[4];
for (int i = 0; i < 4; ++i) {
rowSum[i] += arr[i][0];
rowSum[i] += arr[i][1];
rowSum[i] += arr[i][2];
rowSum[i] += arr[i][3];
columnSum[i] += arr[0][i];
columnSum[i] += arr[1][i];
columnSum[i] += arr[2][i];
columnSum[i] += arr[3][i];
sumDiagonal1 += arr[i][4 - i]; // / diagonal sum
sumDiagonal2 += arr[4 - i][i]; // \ diagonal sum
}
The first one is easy to adjust for all kind of sizes, but is N^2, the second one is N, but today this does not matter for matrix of 4x4, since it is 4 * 2 * 4 (32) loop ops, vs 4 loop ops isn't a big deal for today CPUs.
You can't change the length of an array after it's initialization in java. What you can do and should do here is to copy the content of the old array into a new array with more rows/columns. The same holds true for the diagonals.
In, Java, arrays are immutable in length, which means that you can't add or remove a column or row in your case. You might want to take a look at a Collection, such as ArrayLists. Those have an implementation which allows for scaling.
You can always read a bit more about Collections here.

I don't know how assign new value to the empty array

I am a beginner in coding. I have to write a code that will divide array with random numbers into two different arrays. One array will contain odd numbers, the other one even numbers. But something is wrong, and i don't really know what to do.
According to the console the problem is in the place where there is a lot of exclamation marks. when i change those lines to System.out.println("x") it works perfectly fine.
public void P_N () {
int I_E = 0; // amount of even numbers
int I_O = 0; // amount of odd numbers
for (int i = 0; i < tab2.length; i++) { // tab2 is a array with random numbers
if (tab2[i] % 2 == 0)
I_E = I_E + 1;
else
I_O = I_O+1;
}
int [] tab_E = new int[I_E]; // array with even numbers
int [] tab_O = new int [I_O]; // array with odd numbers
for (int i = 0; i < tab2.length; i++){
if (tab2[i] % 2 == 0){
tab_E[i] = tab2[i]; //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
}
for (int i = 0; i < tab2.length; i++){
if (tab2[i] % 2 != 0){
tab_O[i] = tab2[i]; //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
}
for (int i = 0; i< tab_E.length; i++) {
System.out.println("Even array: " + tab_E[i]);
System.out.println("------------------------------------------------");
}
for (int i = 0; i< tab_O.length; i++) {
System.out.println("Odd array: " + tab_O[i]);
}
}
Problem is in going out of bounds for arrays tab_E and tab_O, when variable i is more tab_E.length. Just create another variable, for example "j". And iterate throug your array using it. Like I'v written below
int j = 0;
for (int i = 0; i < tab2.length; i++) {
if (tab2[i] % 2 == 0) {
tab_E[j++] = tab2[i];
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
}
j = 0;
for (int i = 0; i < tab2.length; i++) {
if (tab2[i] % 2 != 0) {
tab_O[j++] = tab2[i];
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
}
I would rather use 2 ArrayLists one for even numbers and another one is for odd numbers and later convert it into array using toArray() method.
public void P_N(){
ArrayList<Integer> evenNumberList = new ArrayList<Integer>();
ArrayList<Integer> oddNumberList = new ArrayList<Integer>();
for (int i = 0; i < tab2.length; i++) { // tab2 is a array with random numbers
if (tab2[i] % 2 == 0) {
evenNumberList.add(tab2[i]);
} else {
oddNumberList.add(tab2[i]);
}
}
int[] evenNumberArray = evenNumberList.toArray();
int[] oddNumberArray = oddNumberList.toArray();
}
This will take some extra space but makes your application more efficient, I hope this helps.
You have initialized the even/odd number arrays with a quantity of the even/odd numbers accordingly:
int [] tab_E = new int[I_E]; // array with even numbers
int [] tab_O = new int [I_O]; // array with odd numbers
Ii is reasonable to assume that the sizes of even or odd number arrays are might be much smaller than the size of the original source array.
But in this even number filtering loop (as well as in the odd filtering loop) you use source array index values to address target array positions, end eventually face the ArrayIndexOutOfBoundsException.
for (int i = 0; i < tab2.length; i++)
{
if (tab2[i] % 2 == 0)
{
tab_E[i] = tab2[i]; //here the same i value is used to address non existing index in tab_E array
}
}
A quick fix might be the following:
int tab_E_index = 0;
for (int i = 0; i < tab2.length; i++){
if (tab2[i] % 2 == 0){
tab_E[tab_E_index] = tab2[i]; //i value gets incremented every loop iteration
tab_E_index++; //tab_E_index value get incremented only when even number is added to the tab_E array
}
}
Please don't just copy/paste it, but try to understand what caused the issue on the first place. Good luck and happy coding.

How to randomly fill in 10% 2 dimensional array with int = 1?

I have little problem , im starting learn java .
I need to create 2dimensional array , and i need fill this array in 10% only int 1 of course my code need fill this array randomly .
Need some hints how to fill in 10% .
public static void main(String[] args) {
int maxX = 10;
int maxY = 10;
int[][] Arr = new int[maxX][maxY];
Random r = new Random();
// random ints
for (int x = 0; x < maxX; x++) {
for (int y = 0; y < maxY; y++) {
Arr[x][y] = r.nextInt(2);
}
}
// printing Arr
for (int i = 0; i < Arr.length; i++) {
for (int j = 0; j < Arr[i].length; j++) {
System.out.print(Arr[i][j] + " ");
}
System.out.println();
}
}
Make the array, take a random row and column, while the percentage is not exceeded, check if the position has 0, if yes fill it with 1.
int[][] array = new int[N][N];
int percentage = N*N/10;
int filled = 0;
while(filled <= percentage)
{
Random rand = new Random();
int i = rand.nextInt(N+1);
int j = rand.nextInt(N+1);
if(array[i][j] == 0)
{
filled++;
array[i][j] = 1;
}
}
for(int i = 0; i < N; i++)
{
for(int j = 0; j < N; j++)
{
System.out.print(array[i][j] + " ");
}
System.out.println();
}
You can take the following steps:
Suppose you need to fill an N * N array.
Create a List and add to it (N * N) / 10 1s and (N * N * 9) / 10 0s. list.addAll(Collections.nCopies(count,1 or 0)) can help you here.
Run Collections.shuffle on that List to obtain random order.
Iterate over the elements of the List. The first N elements will become the first row the the 2D array, the next N elements will become the second row of the array, and so on...
An alternative to shuffling is to pick 10% x N random positions and put a 1 (if a 0 was in the position, otherwise pick another position). In pseudo code:
int[][] array = new int[N][N]
apply N * N / 10 times {
index = random(0 .. N * N)
if array(index) = 0 then array(index) = 1
else retry with another index
}
You will need to convert the index from 0 to N*N into a pair of i,j in the 2D array.
I would use "double random = Math.random();"
And then an if to check if the variable random is less or equal to 0.1

2D bucket sort issue

Please dont let the length of this post scare you! Okay so here is the prompt I am currently working on:
"Write a class named BucketSort containing a method called sort that:
a) Place each value of the one-dimensional array into a row of the bucket array, based on the value’s “ones” (rightmost) digit. For example, 97 is placed in row 7, 3 is placed in row 3 an 100 is placed in row 0. This procedure is called a distribution pass.
b) Loop through the bucket array row by row, and copy the values back to the original array. This procedure is called a gathering pass. The new order of the preceding values in the one-dimensional array is 100, 3 and 97.
c) Repeat this process for each subsequent digit position (tens, hundreds, thousands, etc.) On the second (tens digit) pass, 100 is placed in row 0, 3 is placed in row 0 (because 3 has no tens digit) and 97 is placed in row 9. After the gathering pass, the order of the values in the one-dimensional array is 100, 3 and 97. On the third (hundreds digit) pass, 100 is placed in row 1, 3 is placed in row 0 and 97 is placed in row 0 (after the 3) After this last gathering pass, the original array is in sorted order. being sorted.
This sorting technique provides better performance than a bubble sort,but requires much more memory—the bubble sort requires space for only one additional element of data. This comparison is an example of the space/time trade-off: The bucket sort uses more memory than the bubble sort, but performs better. This version of the bucket sort requires copying all the data back to the original array on each pass. Another possibility is to create a second two-dimensional bucket array and repeatedly swap the data between the two bucket arrays. The two-dimensional array of buckets is 10 times the length of the integer array"
A bit of a mouth full I know. Below is my code thus far, but I can't figure out why it will not print in the correct order and I think it is time for fresh eyes. Any ideas are appreciated, thanks!
import java.util.Arrays;
public class BucketSort_main {
public static void main(String[] args)
{
int[] numbers = new int [5];
int[] tnumbers = new int [500];
int [][] bucket = new int [10][numbers.length];
int [] a = new int [10];
int count = 0;
int divisor = 1;
int cnt = 1;
boolean moreDigits = true;
for (int s = 0; s < 10; s++)
{
a[s] = 0;
}
for (int b = 0; b < numbers.length; b++)
{
numbers [b] = (int)(Math.random()*2000);
tnumbers [b] = numbers [b];
}
int[] tmpSort = new int[10];
while (moreDigits)
{
moreDigits = false;
for (int i = 0; i < tmpSort.length; i++)
{
tmpSort[i]= -1; // hint hint
}
for (int i = 0; i < numbers.length; i++)
{
int tmp = tnumbers[i] / divisor;
if (tmp/10 != 0)
{
moreDigits = true;
}
int digit = tmp % 10;
tmpSort[digit] = tnumbers[i]; // hint hint
System.out.println("Number["+i+"], Digit "+cnt+" is "+digit + ". Full number = " + tnumbers[i]);
bucket [digit][a[digit]] = tnumbers[i];
System.out.println ("Digit " + digit + " going to slot " + a[digit] + ". " + bucket[digit][a[digit]]);
System.out.println (" ");
a[digit]++;
}
cnt++;
divisor *= 10;
for (int x = 0; x < 10; x++)
{
a [x] = 0;
for (int y = 0; y < numbers.length; y++)
{
if (bucket[x][y] != 0)
{
tnumbers [y] = 0;
tnumbers [y] = bucket[x][y];
bucket[x][y] = 0;
}
}
}
}
for (int o = 0; o < numbers.length; o++)
{
System.out.println (tnumbers[o]);
}
}
}
The Problem is here:
for (int x = 0; x < 10; x++)
{
a [x] = 0;
for (int y = 0; y < numbers.length; y++)
{
if (bucket[x][y] != 0)
{
tnumbers [y] = 0;
tnumbers [y] = bucket[x][y];
bucket[x][y] = 0;
}
}
}
You are using the same y to get values from the bucket and assign values to tnumbers. So, when you loop through y the second time you are starting over again at tnumbers[0], tnumbers[1], etc...
Fix this issue and your code works fine.

2D Array in Java with number manipulation

My goal is to
Create a 5x5 array and fill it with random integers in the range of 1 to 25.
Print this original array
Process the array, counting the number of odds, evens, and summing all of the elements in the array.
Print the total odds, evens, and the sum.
Im not sure how to do it and my teacher is very confused and cannot help me. I was wondering if i could get some guidance.
Here is my code:
public class Processing {
public static void main(String[] args) {
Random Random = new Random();
int[][] Processing = new int[5][5];
for (int x = 0; x < 5; x++) {
int number = Random.nextInt(25);
Processing[x] = number;
}
for (int i = 0; i < 5; i++) {
Processing[i] = new int[10];
}
}
}
Please follow naming conventions for your variables. See here: http://en.wikipedia.org/wiki/Naming_convention_(programming)#Java
Anyways, you have to nest your loops as follows:
for(int i = 0; i < 5; i ++) {
for(int j = 0; j < 5; j++) {
yourArray[i][j] = random.nextInt(25);
}
}
i is the row number and j is the column number, so this would assign values to each element in a row, then move on to the next row.
I'm guessing this is homework so I won't just give away the answer to your other questions, but to set you on the right track, here's how you would print the elements. Again, use two nested loops:
for(int i = 0; i < 5; i ++) {
for(int j = 0; j < 5; j++) {
// print elements in one row in a single line
System.out.print(yourArray[i][j] + " ");
}
System.out.println(); //return to the next line to print next row.
}

Categories