Putting Nested Loops Composite Numbers in Columns - java

I have to write a program that will print out all of the composite numbers that are less than 100. I have to use nested loops to complete this program. Also, the values must be displayed in a table with 10 numbers in each column.
I have been trying this program for over a week now, and I just am completely lost, could I have some help with this?
I did the composite number part, but how exactly do you put the numbers into columns with 10 numbers in each column? Here is the code:
import java.util.Scanner;
class SwitchStatements {
public static void main(String[]Args) {
for (int i = 0; i <= 100; i++) {
for (int j = 2; j <= i/2; j++) {
if (i % j == 0) {
System.out.println(i);
break;
}
}
}
}
}

Do you mean 10 numbers per row (ie 10 columns total), or 10 numbers per column?
Assuming you mean a "table" in the output as something that looks roughly like this (with 5 columns in this example):
1 2 3 4 5
11 12 13 14 15
then I think what you want to do is keep track of how many numbers you've printed on this line, and only use System.out.println when you've printed 10 numbers, and System.out.print otherwise:
int numbersPrinted = 0;
for (int i = 0; i <= 100; i++) {
for (int j = 2; j <= i/2; j++) {
if (i % j == 0) {
if (numbersPrinted < 9) {
System.out.print(i + " ");
numbersPrinted++;
} else {
System.out.println(i);
numbersPrinted = 0;
}
break;
}
}
}
If you want the numbers to line up neatly, you can add two spaces instead of one if i is less than 10 (and therefore is only one digit).
If you actually mean you want ten numbers per column like this (again, 5 in my example instead):
1 2
3 4
5 6
7 8
9 10
then you'll need to print (number of numbers / 10 numbers per column) columns per line, so you can't print them in your nested loop like in your example. Instead, you'll need to add them to an ArrayList or similar and print them in a separate loop later:
ArrayList<int> numbersToPrint = new ArrayList<int>();
...
if (i % j == 0) {
numbersToPrint.add(i);
break;
}
...
int numbersPerRow = (numbersToPrint.size()/10);
int numbersPrinted = 0;
for (int i : numbersToPrint) {
if (numbersPrinted < (numbersPerRow - 1)) {
...
and the rest of that is the same as my first example above.

If you really want 10 numbers in each column, check this code. It can be done with less amount of cycles, but it will be even harder to understand.
What we do here is collecting all composite numbers to list. Fill a 2-dimensional array from that list in a strange order (not row by row as usual, but column by column). And then print it in the 3rd cycle in the usual order.
public static void main(String[] args) {
List<Integer> compositeNumbers = new ArrayList<>();
for (int i = 0; i <= 100; i++) {
for (int j = 2; j <= i / 2; j++) {
if (i % j == 0) {
compositeNumbers.add(i);
break;
}
}
}
int n = compositeNumbers.size();
int numberOfRows = 10;
int maxNumberOfColumns = (n / numberOfRows) + 1;
int[][] numbers = new int[numberOfRows][maxNumberOfColumns];
for (int j = 0; j < maxNumberOfColumns; j++) {
for (int i = 0; i < numberOfRows; i++) {
int index = i + j * numberOfRows;
if (index < n) {
numbers[i][j] = compositeNumbers.get(index);
}
}
}
for (int i = 0; i < numberOfRows; i++) {
for (int j = 0; j < maxNumberOfColumns; j++) {
if (i + j * numberOfRows < n)
System.out.print(String.format("% 3d", numbers[i][j]));
}
System.out.println();
}
}
You will get the nice output:
4 20 33 46 58 72 85 96
6 21 34 48 60 74 86 98
8 22 35 49 62 75 87 99
9 24 36 50 63 76 88 100
10 25 38 51 64 77 90
12 26 39 52 65 78 91
14 27 40 54 66 80 92
15 28 42 55 68 81 93
16 30 44 56 69 82 94
18 32 45 57 70 84 95

Edited to fix composite calculation method.
Assuming you're looking for something like this:
4 20 33 46 58 72 85 96
6 21 34 48 60 74 86 98
8 22 35 49 62 75 87 99
9 24 36 50 63 76 88 100
10 25 38 51 64 77 90
12 26 39 52 65 78 91
14 27 40 54 66 80 92
15 28 42 55 68 81 93
16 30 44 56 69 82 94
18 32 45 57 70 84 95
The first step is to divide the problem into two parts.
Generate all the composite numbers from 4 to 100.
Display all the composite numbers in columns.
You mostly did the first part. You had some errors in your for loop configuration.
You can hold all of the composite numbers in a List<Integer>.
You calculate the number of columns with this line:
int columns = (compositeNumbers.size() + columnLength - 1)
/ columnLength;
Since you have to create a full line to print it, you take the composite integer at position 0, then the composite integer at position 10 (assuming 10 numbers per column). then the composite integer at position 20, and so forth, until you have created a full line.
The last few rows may not have a number in the last column. You have to take that into account when creating a display line.
Here's the code that puts all this together. The calculateCompositeNumbers method calculates the composite numbers. The displayCompositeNumbers method displays the composite numbers in columns.
See how the method names tell you what they do.
package com.ggl.testing;
import java.util.ArrayList;
import java.util.List;
public class CompositeOutput {
public static void main(String[] Args) {
CompositeOutput compositeOutput = new CompositeOutput();
List<Integer> compositeNumbers = compositeOutput
.calculateCompositeNumbers();
System.out.println(compositeOutput.displayCompositeNumbers(
compositeNumbers, 10));
}
private List<Integer> calculateCompositeNumbers() {
List<Integer> compositeNumbers = new ArrayList<>();
for (int i = 4; i <= 100; i++) {
boolean found = false;
int maximum = Math.min(i / 2, 10);
for (int j = 2; j <= maximum && !found; j++) {
if (i % j == 0) {
compositeNumbers.add(Integer.valueOf(i));
found = true;
}
}
}
return compositeNumbers;
}
private String displayCompositeNumbers(List<Integer> compositeNumbers,
int columnLength) {
String lineSeparator = System.getProperty("line.separator");
StringBuilder builder = new StringBuilder();
int columns = (compositeNumbers.size() + columnLength - 1)
/ columnLength;
for (int row = 0; row < columnLength; row++) {
int tempIndex = row;
for (int column = 0; column < columns; column++) {
if (tempIndex < compositeNumbers.size()) {
int number = compositeNumbers.get(tempIndex);
builder.append(String.format("%6d", number));
}
tempIndex += columnLength;
}
builder.append(lineSeparator);
}
return builder.toString();
}
}

Related

How to print 15 numbers on each line?

I have this code, and it works fine, but I want to format it so that it prints 15 numbers on each line.
I have seen it done with % or for loops, but I don't know how to use them in my code. Thank you to everyone for helping! Thank you!
import java.util.*;
import java.io.*;
class Main
{
public static void main(String args[])
{
Scanner sc = new Scanner(System.in);
System.out.print("Enter the number that you want to find all the prime numbers up to it: ");
int num = sc.nextInt();
boolean[] bool = new boolean[num];
for (int i = 0; i < bool.length; i++) {
bool[i] = true;
}
for (int i = 2; i < Math.sqrt(num); i++) {
if(bool[i] == true) {
for(int j = (i * i); j < num; j = j + i) {
bool[j] = false;
}
}
}
System.out.println("List of prime numbers upto given number are : ");
for (int i = 2; i < bool.length; i++) {
if(bool[i]==true)
{
System.out.print(i + " ");
}
}
}
}
You can make increment a count each time bool[i] is true, then move to the next line when the count is 15 and reset the count back to 0.
Here is what your print loop would now look like:
System.out.println("List of prime numbers upto given number are : ");
int count = 0;
for (int i = 2; i< bool.length; i++) {
if(bool[i])
{
if (count == 15) {
count = 0;
System.out.println();
}
System.out.print(i + " ");
count++;
}
}
Output:
Enter the number that you want to find all the prime numbers up to it: 120
List of prime numbers upto given number are :
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
53 59 61 67 71 73 79 83 89 97 101 103 107 109 113
In the context of what you're doing the best option would be something like this:
int count = 0;
System.out.println("List of prime numbers upto given number are : ");
for (int i = 2; i< bool.length; i++) {
if(bool[i]==true) {
System.out.print(i + " ");
count++;
}
if(count == 15) {
System.out.println();
count = 0;
}
}
Do it as follows:
System.out.println("List of prime numbers upto given number are : ");
for (int i = 2, j = 1; i < bool.length; i++) {
if (bool[i] == true) {
System.out.print(i + " ");
if (j % 15 == 0) {
System.out.println();
}
j++;
}
}
A sample run:
Enter the number that you want to find all the prime numbers up to it: 200
List of prime numbers upto given number are :
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
53 59 61 67 71 73 79 83 89 97 101 103 107 109 113
127 131 137 139 149 151 157 163 167 173 179 181 191 193 197
199
Feel free to comment in case of doubt.

Putting values from file separated by space into multi dimension array

I'm newbie and I don't know how to merge my parts of knowledge.
I have to make Algorithm looking for the longest rising sequence of numbers.
My file has 50 columns, every column has some random numbers separated with space.
I'm still trying to put them in Matrix or other multi dimension arrays but I don't know how.
This is my code:
import java.io.File;
import java.util.Scanner;
import java.util.StringTokenizer;
public class reading {
public static void main(String[] args) {
double[][] numbers = new double[101][101];
int column = 0, row = 0;
try {
System.out.print("Enter the file name with extension : ");
Scanner input = new Scanner(System.in);
File file = new File(input.nextLine());
input = new Scanner(file);
for (int columns = 0; columns < 101; columns++) {
String input2 = input.nextLine();
StringTokenizer strToken = new StringTokenizer(input2);
int count = strToken.countTokens();
for (int rows = 0; rows < count; rows++) {
numbers[columns][rows] = Integer.parseInt((String) strToken.nextElement());// writing values to arrays
System.out.println(numbers[columns][rows]);// test
}
}
input.close();
} catch (Exception ex) {
ex.printStackTrace();
}
// here someday will be algorithm
}
}
**Sorry guys for my poor english i'm trying to tell what i want but it's a little bit hard for me. :( I got file whit a lot of numbers and i have to found longest series of numbers from smaller to most bigger without replacing numbers **
little example from file "
45 -31 -21 -34 30 -2 12 21 -39 -46 -48 8 15 30 8 -48 29 12 11 -28 40 27 28 -45 2 50 8 28 14 47 -22 -20 27 16 43 -7 35 13 7 15 40 -42 23 -7 7 18
22 13 28 -33 -15 -46 12 -22 31 -33 39 34 -11 45 -25 -25 -50 48 31 -20 -25 -5 5
18 -36 -24 -17 10 24 21 -35 6 19 38 6 44 20 30 -49 -33 -44 9
37 -36 -18 2 -2 35 -2 45 -36 40 26 -42 -17 45 40 -31 -21 33 -4 -50 40 13 -50 11 12 37 -26 38 -31 7 30 4 32 -50 -7 -40 -12 27
17 -5 -11 41 -1 46 16 16 48 38 -49 10 1 25 39 26 -14 -50"
If you're trying to read whitespace-separated values, the easiest solution is probably just to use Scanner.next or one of the other next... functions (other than nextLine, like Scanner.nextInt, or Scanner.nextDouble in your case).
These functions use whitespace as a delimiter, so each subsequent call will return the next piece of text that's between some whitespace, and also convert it to the appropriate type, if applicable.
input = new Scanner(file);
for (int rows = 0; rows < numbers.length; rows++){
for (int columns = 0; columns < numbers[rows].length; columns++){
numbers[rows][columns] = input.nextDouble();
}
}
If you want each line in the file to be a row, the rows loop should be on the outside (consider that you want to start with row 0 and go through each column in the same way you'd start from line 0 and go through each value in that line).
This is not particularly robust (if there's something wrong with your data, it might still work or it might be hard to find where the problem is).
If you're looking for something more robust, I might recommend something more like:
for (int rows = 0; rows < numbers.length; rows++){
String[] split = input.nextLine().split("\\s+"); // \\s+ is 1 or more whitespace characters
if (split.length != numbers.length) {
throw new IllegalArgumentException("Line " + rows + " has " + split.length + " columns, but needs " + numbers.length);
}
for (int columns = 0; columns < numbers[rows].length; columns++){
numbers[rows][columns] = Double.parseDouble(split[columns]);
}
}
In Java 8 we can achieve the same result like this:
final int DESIRED_ROW_LENGTH = 101;
for (int rows = 0; rows < numbers.length; rows++){
numbers[rows] = Arrays.stream(input.nextLine().split("\\s+"))
.mapToDouble(Double::parseDouble).toArray();
if (numbers[rows].length != DESIRED_ROW_LENGTH) {
throw new IllegalArgumentException("Line " + rows + " has " + numbers[rows].length + " columns, but needs " + DESIRED_ROW_LENGTH);
}
}
I'll provide an alternative* to #Dukeling answer on the premise that you are actually looking for some sort of algorithm for the longest rising sequence of numbers:
Basically, do it directly while reading the file, and just check each position of ((column + 1) - (column) == 1) and update a field if so.
File file = new File("\\\\share\\file\\path\\file.txt");
Scanner sc = new Scanner(file);
int totalCount = 0;
int tempCount = 0;
int tempLineNumber = 1;
int totalLineNumber = 0;
while (sc.hasNextLine()) {
String[] array = sc.nextLine().split("\\s+");
for (int i = 0; i < array.length - 1; i++) {
if (Integer.parseInt(array[i + 1]) - Integer.parseInt(array[i]) == 1) {
tempCount++;
}
}
if (totalCount < tempCount) {
totalCount = tempCount;
totalLineNumber = tempLineNumber;
}
tempCount = 0;
tempLineNumber++;
}
System.out.println("The max longest rising sequence of numbers is: "
+ totalCount + " at line " + totalLineNumber);
* I just threw this example together quickly, and most likely has an issue or two, such as missing edge cases etc
The actual algorithm happens on a one-dimensional array of integers.
So this could be done per line read from the file.
Path path = Paths.get(input.nextLine());
for (String line : Files.readAllLines(path, Charset.defaultCharset())) {
// Convert line into numbers:
String[] words = line.split(" ");
int[] numbers = new int[words.length];
for (int i = 0; i < numbers.length; ++i) {
numbers[i] = Integer.parseInt(words[i]);
}
// Find longest sequence in numbers array:
...
}
As other code here uses File and Scanner, I have given Path (newer alternative for File), and Files a utility class that has such nice methods like readAllLines.
Though you need no matrix, in general one does not use the typical math ordering, but line-by-line (by rows):
for (int row = 0; row < count; rows++) {
... read a line
for (int column = 0; column < 101; column++) {
numbers[row][column] = ...
System.out.print(numbers[row][column] + " ");
}
System.println();
}

Leaving space blank in a two dimenional array

so I'm just starting a pretty simple project for school in which I want to create a booking system for a stadium. I've got a twoD array that will create a simple 7X10 array. However, I want to leave some space in the middle of the array that would represent the pitch/field in the stadium. I'm wondering how to do this?
I'm thinking an array inside an array if that is possible?
This is my code so far(got most of it from another question on here):
package FootballMatch;
public class Seats {
public static void main(String[] args) {
System.out.print("\t\t Stadium Seating \n");
int seatArray[][]= new int[10][7];
int i, x, y = 1;
for(i = 0; i < 10; i++) {
for(x = 0; x < 7; x++) {
seatArray[i][x] = y;
y++;
} // end inner for
} // end outer for
for(int[] row : seatArray) {
printRow(row);
}
} // end of main
public static void printRow(int[] row) {
for (int i : row) {
System.out.print(i);
System.out.print(" \t");
}
System.out.println();
}
}
output:
`Stadium Seating
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 32 33 34 35
36 37 38 39 40 41 42
43 44 45 46 47 48 49
50 51 52 53 54 55 56
57 58 59 60 61 62 63
64 65 66 67 68 69 70`
So i want to have every 3rd to 5th number in the third to eight row of the array invisible, like this:
`Stadium Seating
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 _ _ _ 20 21
22 23 _ _ _ 27 28
29 30 _ _ _ 34 35
36 37 _ _ _ 41 42
43 44 _ _ _ 48 49
50 51 _ _ _ 55 56
57 58 59 60 61 62 63
64 65 66 67 68 69 70`
Note all of these numbers will probably be changed to 'x' in the finished program. 'x' meaning the seat is available and an empty space meaning its the field!
Going off of ControlAltDel's suggestion, a well designed answer to this problem (that also allows for later expansion) is to create a Seat Class to represent a single seat.
public class Seat{
private int index; //-1 if not available, > 0 otherwise
private boolean available;
/** Creates an available seat with index i. i > 0. */
public Seat(int i){
index = i;
available = true;
}
/** Creates a non-available seat. */
public Seat(){
index = -1;
available = false;
}
/** Return a string representation of this Seat. Its index if available, - otherwise */
public String toString(){
if(available) return index + "";
else return "-";
}
}
Then you can create a matrix of Seats that represents your stadium:
public static void main(String[] args) {
System.out.print("\t\t Stadium Seating \n");
Seat seatArray[][]= new Seat[10][7];
int i, x, y = 1;
for(i = 0; i < 10; i++) {
for(x = 0; x < 7; x++) {
if(i >= 2 && i <= 7 && x >= 2 && x <= 4){
seatArray[i][x] = new Seat(); //Not available seat
} else {
seatArray[i][x] = new Seat(y);
}
y++;
}
}
for(Seat[] row : seatArray){ printRow(row); }
}
public static void printRow(Seat[] row) {
for (Seat s : row) {
System.out.print(s); //toString method called implicitly here.
System.out.print(" \t");
}
System.out.println();
}
Use an boolean array to indicate that those positions can be occupied by a person.
In order to do this, you have to change your printing method. You have to use a code like:
// You must set canSeat at your will (true and false).
public static void print(int[][] seatArray, Boolean canSeat[][]) {
for(i = 0; i < 10; i++) {
for(x = 0; x < 7; x++) {
if(canSeat[i][x])
System.out.print(seatArray[i][x]);
else
System.out.print(" ");
System.out.print(" \t");
}
}
}

Displaying all the Odd number between 1 - 99 in java using Nested For Loop

Currently I'm only able to display odd numbers of 1 3 5 7 9. However, I would like to display all the odd numbers from 1 - 99 with 9 rows and 5 col. May I know how am I able to display from 11 onwards rather than just 9 rows of 1 3 5 7 9.
Below is the code I'm stuck with.
public static void main(String args[])
{
for (int i=1; i<=9; i++)
{
for (int j=1; j<=10; j++)
{
if (j%2 !=0)
System.out.print(j + " " );
}
System.out.println();
}
}
first you need to calculate your number, try
for (int i=0; i<=9; i++)
{
for (int j=1; j<=10; j++)
{
int number = j+i*10
if (number%2 !=0)
System.out.print(number + " " );
}
System.out.println();
}
but this problem you can solve with single loop
for (int i=1; i<=99; i++)
{
if (number%2 !=0)
System.out.print(number + " " );
if (number%10 ==0)
System.out.println();
}
for ( i = 1; i < 100; i+=2 ) {
System.out.print(i);
}
System.out.println();
public static void main(String args[])
{
for (int i=1; i<=99; i++)
{
if (i%2 !=0)
System.out.print(i + " " );
if(i%10 == 0)
System.out.println();
}
}
This code will allow you to do what you want with 1 loop which is more efficient than using nested loops.
This will loop through each number from 1-99 and print if it is odd. If the number is a multiple of 10 then it will print a new line.
Maybe this helps:
public static void main(String args[])
{
for (int j = 0; j < 10; j++)
{
for (int i = 1; i <= 9; i++)
{
int c = j * 10 + i;
if (c % 2 !=0)
System.out.print(c + " " );
}
System.out.println();
}
}
Other alternative with just one loop:
public static void main(String args[]) {
for (int j = 1; j <= 99; j += 2) {
System.out.print(j + " ");
if ((j + 1) % 10 == 0) {
System.out.println();
}
}
}
If you want to use a nested forloop you have to use both iterating variables to build your numbers. You dont use i at all in the inner for-loop. Therefore only 1 3 5 7 9 gets printed 9 times. For a hotfix try to use something like
System.out.print(i + j + " " );
instead of
System.out.print(j + " " );
note how i+j does not compute an addition here.
Anyway like pointed out in the comments you dont really need 2 loops here.
we cheat:
for (int i = 1; i <= 99; i += 2)
System.out.printf("%d%s", i, i % 10 == 9 ? "\n" : " ");
we check:
int c =0;
for (int i = 1; i <= 99; i++)
if ((i & 1) == 1) {
c++;
System.out.printf("%d%s", i, c % 5==0 ? "\n" : " ");
}
both output same, 5 odd numbers in a row, without trailing spaces.
With this one you can easily set the number of columns as you like it.
We use a single loop.
Code:
int columns = 5;
int start = 1;
int end = 99;
// iterate through every seconds i.
for (int i = start; i <= end; i += 2) {
System.out.printf("%-4d", i);
// if we have displayed enough words, start a new line
if (i % (2 * columns) == 0) {
System.out.println();
}
}
Output:
1 3 5 7 9
11 13 15 17 19
21 23 25 27 29
31 33 35 37 39
41 43 45 47 49
51 53 55 57 59
61 63 65 67 69
71 73 75 77 79
81 83 85 87 89
91 93 95 97 99
However, if I understood your question correctly, you wanted to show numbers with 5 columns and 9 rows? Well this is impossible if we print only the numbers from 1 to 99. With 5 columns and numbers 1 to 99, you will get 10 rows.
Your code now prints 9 rows of:
1 3 5 7 9
This is happening because your inner loop loops on values between 1 and 9, always.
You should try something like:
int counter = 0;
for(int i=1; i<=99; i++) {
if(i%2 != 0) {
System.out.print(i + " ");
counter++;
}
if(counter == 5) {
System.out.println();
counter = 0;
}
}
This will print:
1 3 5 7 9
11 13 15 17 19
21 23 25 27 29
31 33 35 37 39
41 43 45 47 49
51 53 55 57 59
61 63 65 67 69
71 73 75 77 79
81 83 85 87 89
91 93 95 97 99

2d array diagonally filling

1 2 3
4 5 6
7 8 9
this is my normal array, but i need to make it diagonally like this
1 2 4
3 5 7
6 8 9
this is very stupid way to make it work, but even it is not working because i am not able to find 2nd column elements.
for (i = 0; i < arr.length; ++i) {
for (n = 0; n < arr[0].length; ++n) {
if (i == 0 && n == 0){
arr[i][n] = 0;
} else if (i == 0 && n == 1) {
arr[i][n] = 2;
} else if (i == 1 && n == 0) {
arr[i][n] = 3;
} else if (n == 0) {
arr[i][n] = arr[i - 1][n] - arr[i - 2][n] + 1 + arr[i - 1][n];
} else {
arr[i][n] = arr[i][n - 1] - arr[i][n - 2] + 1 + arr[i][n - 1];
}
}
}
Well, if you were to enumerate the indices in order for that fill pattern, you would get
0,0
1,0
0,1
2,0
1,1
0,2
2,1
1,2
2,2
So, you need to iterate through the total of the two indices. That is, the additive total. As you can see, 0,0 totals 0, 1,0 and 0,1 total 1, and so on. Giving us something like this:
0 1 2
1 2 3
2 3 4
To iterate in this diagonal pattern, we can do the following:
// set up your matrix, any size and shape (MxN) is fine, but jagged arrays will break
int[][] matrix = {{0,0,0},{0,0,0},{0,0,0}};
// number is the value we will put in each position of the matrix
int number = 1;
// iterate while number is less than or equal to the total number of positions
// in the matrix. So, for a 3x3 matrix, 9. (this is why the code won't work for
// jagged arrays)
for (int i = 0; number <= matrix.length * matrix[0].length; i++) {
// start each diagonal at the top row and from the right
int row = 0;
int col = i;
do {
// make sure row and length are within the bounds of the matrix
if (row < matrix.length && col < matrix[row].length) {
matrix[row][col] = number;
number++;
}
// we decrement col while incrementing row in order to traverse down and left
row++;
col--;
} while (row >= 0);
}
Note that while this implementation will work for all matrix sizes (and shapes), it won't be as efficient as possible. Where n is matrix.length (assuming a square matrix), this implementation is an optimal O(n^2) class algorithm in big O notation; however, it effectively performs 2*n^2 iterations, whereas an optimal solution would only perform n^2.
You want to achive something like this:
1 2 4 7
3 5 8 B
6 9 C E
A D F G
In the grid of size NxN, for every point (x,y) in the grid, you can determine the value like this (still needs some corrections for offset at 0, see final formula):
if you are on the upper left half, calculate the area of the triangle that is above and left of you and add your distance from the top
if you are in the lower right half (or on the middle), calculate the area of the triangle below and right of you, add your distance from the bottom and subtract that from the whole area
Let's try it as a formula:
int N = 4; int[][] v = new[N][N];
for(int y = 0; y < N; y++) for(int x = 0; x < N; x++)
v[x][y] = ( x + y < N ) ?
( ( x + y + 1 ) * ( x + y ) / 2 + y + 1 ) :
( N * N + 1 - ( N - y ) - ( 2 * N - x - y - 1 ) * ( 2 * N - x - y - 2 ) / 2 );
I have no idea what complexity this is, but the experts can surely confirm that it is O(N^2) ? Also if it has some cool name like dynamic code, please let me know!
The advantage I see here is that you don't need to jump around memory and can fill all fields with one linear run through the memory. Also having it as a history independent formula can be optimized by the compiler or allow better parallelisation. If you had a machine with N^2 units, they could calculate the whole matrix in one operation.
Diagonal of an M by N Matrix, with Robust Array Formatting
Given that a lot of these answers have already covered the basic N by N arrays, and some are pretty efficient, I went ahead and made a more robust version that handles M by N arrays, along with a nice formatted printer, for your own enjoyment/masochistic viewing.
The efficiency of this method is O(N^2). The format of the printer is O(N^2).
Code
Main
You can set whatever rows and columns you want, assuming positive integer values.
public static void main(String[] args) {
//create an M x N array
int rows = 20;
int columns = 11;
int[][] testData = new int[rows][columns];
//iteratively add numbers
int counter = 0;
for(int i = 0; i < rows; i++) {
for(int j = 0; j < columns; j++) {
testData[i][j] = ++counter;
}
}
//print our test array
printArray(testData);
System.out.println("");
//print our diagonal array
printArray(diagonal(testData));
}
Printing a 2-Dimensional Array
This method works specifically for this example by determining the number of entries using M x N, and then counting the digits. If you want to, say, display any sized array based on the longest item in the array, you could easily adapt this code to do that. A decent challenge best assigned to the reader. O(N^2) for this, but due to having to search the array for the largest value, one that takes the largest digit will by nature require another O(N^2) for search.
static void printArray(int[][] array) {
//get number of digits
int count = array.length * array[0].length;
//get power of function
int power;
//probably the only time I'd ever end a for loop in a semicolon
//this gives us the number of digits we need
//You could also use logs I guess but I'm not a math guy
for(power = 0; count / Math.pow(10, power) > 1; power++);
for(int i = 0; i < array.length; i++){
System.out.print("{");
for(int j = 0; j < array[0].length; j++){
//Let's say Power is 0. That means we have a single-digit number, so we need
// +1 for the single digit. I throw in 2 to make it extra wide
System.out.print(String.format("%" + Integer.toString(power + 2)
+ "s", Integer.toString(array[i][j])));
}
System.out.println("}");
}
}
The Diagonal Converter
There's a lot of edge cases to be tested for when we account for M x N, so I went ahead and seem to have covered all of them. Not the neatest, but looks to be working.
static int[][] diagonal(int[][] input) {
//our array info
final int numRows = input.length;
final int numColumns = input[0].length;
int[][] result = new int[numRows][numColumns];
//this is our mobile index which we will update as we go through
//as a result of certain situations
int rowIndex = 0;
int columnIndex = 0;
//the cell we're currently filling in
int currentRow = 0;
int currentColumn = 0;
for(int i = 0; i < numRows; i++) {
for(int j = 0; j < numColumns; j++) {
result[currentRow][currentColumn] = input[i][j];
//if our current row is at the bottom of the grid, we should
//check whether we should roll to top or come along
//the right border
if(currentRow == numRows - 1) {
//if we have a wider graph, we want to reset row and
//advance the column to cascade
if(numRows < numColumns && columnIndex < numColumns - 1 ) {
//move current row down a line
currentRow = 0;
//reset columns to far right
currentColumn = ++columnIndex;
}
//if it's a square graph, we can use rowIndex;
else {
//move current row down a line
currentRow = ++rowIndex;
//reset columns to far right
currentColumn = numColumns - 1;
}
}
//check if we've reached left side, happens before the
//top right corner is reached
else if(currentColumn == 0) {
//we can advance our column index to the right
if(columnIndex < numColumns - 1) {
currentRow = rowIndex;
currentColumn = ++columnIndex;
}
//we're already far right so move down a row
else {
currentColumn = columnIndex;
currentRow = ++rowIndex;
}
}
//otherwise we go down and to the left diagonally
else {
currentRow++;
currentColumn--;
}
}
}
return result;
}
Sample Output
Input
{ 1 2 3}
{ 4 5 6}
{ 7 8 9}
{ 10 11 12}
Output
{ 1 2 4}
{ 3 5 7}
{ 6 8 10}
{ 9 11 12}
Input
{ 1 2 3 4 5 6}
{ 7 8 9 10 11 12}
{ 13 14 15 16 17 18}
{ 19 20 21 22 23 24}
{ 25 26 27 28 29 30}
{ 31 32 33 34 35 36}
Output
{ 1 2 4 7 11 16}
{ 3 5 8 12 17 22}
{ 6 9 13 18 23 27}
{ 10 14 19 24 28 31}
{ 15 20 25 29 32 34}
{ 21 26 30 33 35 36}
Input
{ 1 2 3 4 5 6}
{ 7 8 9 10 11 12}
{ 13 14 15 16 17 18}
{ 19 20 21 22 23 24}
{ 25 26 27 28 29 30}
{ 31 32 33 34 35 36}
{ 37 38 39 40 41 42}
{ 43 44 45 46 47 48}
{ 49 50 51 52 53 54}
{ 55 56 57 58 59 60}
{ 61 62 63 64 65 66}
{ 67 68 69 70 71 72}
{ 73 74 75 76 77 78}
{ 79 80 81 82 83 84}
{ 85 86 87 88 89 90}
{ 91 92 93 94 95 96}
{ 97 98 99 100 101 102}
{ 103 104 105 106 107 108}
{ 109 110 111 112 113 114}
{ 115 116 117 118 119 120}
{ 121 122 123 124 125 126}
{ 127 128 129 130 131 132}
{ 133 134 135 136 137 138}
{ 139 140 141 142 143 144}
{ 145 146 147 148 149 150}
Output
{ 1 2 4 7 11 16}
{ 3 5 8 12 17 22}
{ 6 9 13 18 23 28}
{ 10 14 19 24 29 34}
{ 15 20 25 30 35 40}
{ 21 26 31 36 41 46}
{ 27 32 37 42 47 52}
{ 33 38 43 48 53 58}
{ 39 44 49 54 59 64}
{ 45 50 55 60 65 70}
{ 51 56 61 66 71 76}
{ 57 62 67 72 77 82}
{ 63 68 73 78 83 88}
{ 69 74 79 84 89 94}
{ 75 80 85 90 95 100}
{ 81 86 91 96 101 106}
{ 87 92 97 102 107 112}
{ 93 98 103 108 113 118}
{ 99 104 109 114 119 124}
{ 105 110 115 120 125 130}
{ 111 116 121 126 131 136}
{ 117 122 127 132 137 141}
{ 123 128 133 138 142 145}
{ 129 134 139 143 146 148}
{ 135 140 144 147 149 150}
Luke's intuition is a good one - you're working through down-and-left diagonals. Another thing to notice is the length of the diagonal: 1, 2, 3, 2, 1. I'm also assuming square matrix. Messing with your for indicies can yield this:
int len = 1;
int i = 1;
while(len <= arr.length){
//Fill this diagonal of length len
for(int r = 0; r < len; r++){
int c = (len - 1) - r;
arr[r][c] = i;
i++;
}
len++;
}
len--; len--;
while(len > 0){
//Fill this diagonal of length len
for(int c = arr.length - 1; c > (arr.length - len - 1); c--){
int r = arr.length - len + 2 - c;
arr[r][c] = i;
i++;
}
len--;
}
System.out.println(Arrays.deepToString(arr));
Here is the code translated from here to Java and adjusted to your problem.
int[][] convertToDiagonal(int[][] input) {
int[][] output = new int[input.length][input.length];
int i = 0, j = 0; // i counts rows, j counts columns
int n = input.length;
for (int slice = 0; slice < 2 * n - 1; slice++) {
int z = slice < n ? 0 : slice - n + 1;
for (int k = z; k <= slice - z; ++k) {
// store slice value in current row
output[i][j++] = input[k][slice - k];
}
// if we reached end of row, reset column counter, update row counter
if(j == n) {
j = 0;
i++;
}
}
return output;
}
Input:
| 1 2 3 |
| 4 5 6 |
| 7 8 9 |
Output:
| 1 2 4 |
| 3 5 7 |
| 6 8 9 |
Click here for running test code
This is a simple dynamic programming (ish) solution. You basically learn from the last move you made.
NOTE: THIS IS A O(N^2) ALGOIRTHM
Initialize:
int m = 4;
int n = 4;
int[][] array = new int[m][n];;
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
array[i][j] = 0;
}
}
The work:
array[0][0] = 1;
for(int i = 0; i < m; i++){
if(i != 0){ array[i][0] = array[i-1][1]+1;}
// This is for the start of each row get 1+ the diagonal
for(int j = 1; j < n; j++){
if(i == 0){
array[i][j] = array[i][j-1]+j;
// only for the first row, take the last element and add + row Count
}else{
if(i == m-1 && j == n -1){
// This is only a check for the last element
array[i][j] = array[i][j-1]+1;
break;
}
// all middle elements: basically look for the diagonal up right.
// if the diagonal up right is out of bounds then take +2 the
// prev element in that row
array[i][j] = ((j+1) != (m)) ? array[i-1][j+1] +1: array[i][j-1]+2;
}
}
}
Printing the solution:
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
System.out.print(array[i][j]);
}
System.out.println("");
}
return 0;
}
You need to do a conversion from index 0..n for x/y (from 0 to x*y) and back to x/y from index...
public void toPos(int index){
return...
}
public int toIndex(int x, int y){
return...
}
I've left the implementation details to you.
Here is Complete working code for your problem. Copy and paste if you like
public class FillArray{
public static void main (String[] args){
int[][] array = {
{1,2,3},
{4,5,6},
{7,8,9}}; //This is your original array
int temp = 0; //declare a temp variable that will hold a swapped value
for (int i = 0; i < array[0].length; i++){
for (int j = 0; j < array[i].length; j++){
if (i < array.length - 1 && j == array[i].length - 1){ //Make sure swapping only
temp = array[i][j]; //occurs within the boundary
array[i][j] = array[i+1][0]; //of the array. In this case
array[i+1][0] = temp; //we will only swap if we are
} //at the last element in each
} //row (j==array[i].length-1)
} //3 elements, but index starts
//at 0, so last index is 2
}
}

Categories

Resources