This should be a fairly straight-forward question but I cannot seem to figure out how to get all diagonals of a non-square matrix.
I already have what I consider the anti-diagonals (examples at: https://stackoverflow.com/a/33769730), but I need the opposite diagonal lines too.
Example Array:
1 2 3 4
5 6 7 8
9 10 11 12
Current output:
[1], [2,5], [3,6,9], [4,7,10], [8,11], [12]
Expected additional output:
[4], [3,8], [2,7,12], [1,6,11], [5,10], [9]
I'm looking more for pseudocode so I can understand this better.
EDIT: Code I have to get anti-diagonals (since no one seems to want to follow link)
int ndiags = width + height - 1;
System.out.println("---");
for (int diag = 0; diag < ndiags; diag++) {
int row_stop = Math.max(0, diag - width + 1);
int row_start = Math.min(diag, height - 1);
for (int row = row_start; row >= row_stop; row--) {
// on a given diagonal row + col = constant "diag"
// diag labels the diagonal number
int col = diag - row;
System.out.println(col + "," + row);
relax(col, row);
}
System.out.println("---");
}
I tried the following, but I'm still just getting anti-diagonals:
int ndiags = width + height - 1;
System.out.println("---");
for (int diag = 0; diag < ndiags; diag++) {
int row_stop = Math.max(0, diag - height + 1);
int row_start = Math.min(diag, width - 1);
for (int row = row_start; row >= row_stop; row--) {
// on a given diagonal row + col = constant "diag"
// diag labels the diagonal number
int col = diag - row;
System.out.println(col + "," + row);
relax(col, row);
}
System.out.println("---");
}
You can generalize this code for any matrix...for now it prints correct output for above specified matrix
output: [4 ] [3 8 ] [2 7 12 ] [5 10 ] [9 ]
class Diagonal
{
public static void main(String[] args)
{
int r=3,c=4;
int Mat[][]={{1,2,3,4},{5, 6 ,7 ,8},{9,10,11,12}};
int x,y;
for(int i=c-1;i>0;i--)
{
y=i;x=0;
System.out.print("[");
while(y<c)
{
System.out.print(Mat[x][y]+" ");
x++;y++;
}
System.out.print("] ");
}
for(int i=1;i<r;i++)
{
x=i;y=0;
System.out.print("[");
while(x<r)
{
System.out.print(Mat[x][y]+" ");
x++;y++;
}
System.out.print("] ");
}
}
}
For anti-diagonal:
output: [1 ] [2 5 ] [3 6 9 ] [4 7 10 ] [8 11 ] [12 ]
class Diagonal
{
public static void main(String[] args)
{
int r=3,c=4;
int Mat[][]={{1,2,3,4},{5, 6 ,7 ,8},{9,10,11,12}};
int x,y;
for(int i=0;i<c;i++)
{
y=i;x=0;
System.out.print("[");
while(y>=0 && x<r)
{
System.out.print(Mat[x][y]+" ");
x++;y--;
}
System.out.print("] ");
}
for(int i=1;i<r;i++)
{
x=i;y=c-1;
System.out.print("[");
while(x<r)
{
System.out.print(Mat[x][y]+" ");
x++;y--;
}
System.out.print("] ");
}
}
}
Each diagonal going in top-left to bottom-right direction is defined by j - i value where i is a row number and j is column number. Note that some of identifiers can be negative.
So pseudocode may be like this:
Create a dictionary with int keys and Linst<int> values.
Iterate over each element of the array.
Append current element to the list identified by j - i value from dictionary.
In the end you can extract your lists from the dictionary in either way as items are sorted by integer key key. The sorting corresponds to the way of taking top-right or bottom-left diagonal first.
An advantage of this method is that you don't need to deal with your rectangular matrix dimensions and apply any checks. Just a single matrix traversal.
could you show an example of what the list might look like?
The dictionary might look like this:
keys: -2 -1 0 1 2 3
-------------------------------
lists: 9 5 1 2 3 4
10 6 7 8
11 12
List elements are visualized from top to bottom.
Related
EDIT 2
I separated out the offset code into a new method at Gavin's suggestion:
private static int getOffset(int offset, int row, int col, ArrayList<ArrayList<Integer>> triangle, ArrayList<ArrayList<Integer>> p_triangle, ArrayList<Integer> sums) {
int row_num = (row+1); //= 1-indexed row #
int p_value = p_triangle.get(row).get(col); // number from pascal's triangle
if (col > 1) {
// element is in the left half of Pascal's Triangle
if (col <= (row_num/2)) offset++;
// penultimate element
else if (col == row_num - 2) offset = sums.size() - p_value;
// elements halfway until penultimate;
// [-2, -3] all work up until row 10 and fail thereafter
else offset = sums.size() - p_value - (row_num - col - 2);
}
return offset;
}
And found that, oddly enough, subtracting 2 or 3 both work when calculating the offset for an element in the latter half of the given row (between halfway and antepenultimate). And I have no idea why that's the case.
Even stranger is that I modified Oleg's answer
public static int findMaxSum(ArrayList<ArrayList<Integer>> data) {
for (int row = data.size() - 2; row >= 0; row--)
for (int col = 0; col < data.get(row).size(); col++)
data.get(row).set(col, data.get(row).get(col) + Math.max(data.get(row + 1).get(col), data.get(row + 1).get(col + 1)));
return data.get(0).get(0);
}
and found that the behavior of algorithm appears to be correct up to a triangle of size 10. However, it starts to breakdown after that with the following discrepancies in rows 11-15:
size = 11 [correct:772 | mine:752]
size = 12 [correct:850 | mine:830]
size = 13 [correct:908 | mine:921]
size = 14 [correct:981 | mine:961]
size = 15 [correct:1074 | mine:1059]
Unfortunately, I still can't discern a pattern from this.
EDIT
I'd like to emphasize that I'm not looking for a better way to solve this particular Project Euler problem; instead, I just want to know if it's possible to use Pascal's Triangle to do it in the way I described (or in some slightly modified way) and if someone can see the logic in my code I may be blind to.
ORIGINAL QUESTION
I am trying to solve Project Euler problem 18.
The goal is to find the max sum of all the 2^14 paths down a triangle of numbers.
I was struck by the similarity with Pascal's Triangle and wondered if it could be used to solve the problem.
My logic is as follows:
1.) Calculate the sums by row.
2.) Use Pascal's triangle to determine how many there must be (as each row adds up to a power of two) and to determine the offset from the start of the of the previous rows sums.
Ex.
Pascal's Triangle
1
1 1
1 2 1
1 3 3 1
Triangle To Process
3
7 4
2 4 6
8 5 9 3
Sums
[3]
[10, 7]
[12, 14, 11, 13]
[20, 17, 19, 16, 23, 20, 22, 16]
For row 3, we see Pascal's Triangle informs us that there will be 1 + 2 + 1 or 4 values. Furthermore, it describes how to build the sums because it's the first and last element added to the sum directly preceding them and the middle value added to both of those sums as it has contact with both the preceding chains.
By extension, the fourth row shows that the second number in the Triangle to Process should be added to the first three sums from row three and the third number should be added to the final three.
The way I get the offset is kind of ugly (and maybe the source of the trouble):
if (i > 1) {
if (i < (p_triangle.get(row).size()/2)) offset++;
else if (i == triangle.get(row).size()-2) offset = sums.size() - p_triangle.get(row).get(i);
else offset = sums.size() - p_triangle.get(row).get(i) - (p_triangle.get(row).size() - i - 2);
}
Where p_triangle.get(row) is the current Pascal's Triangle row being used, sums is the array of cumulative sums (2^(row-1) in length), offset is where to start the summations from, and the Pascal's Triangle number is how many elements from the sum list starting at the offset to sum the number at index i in the Triangle to Process, i.e., triangle.get(row).get(i).
I know this may not be the most efficient algorithm to solve the problem, but it seems like it could be a nice one. The thing is, I can't get it to work.
SPOILER ALERT ON THE ANSWER TO THE PROBLEM
The correct answer is apparently 1074
Can anyone tell me where in the code or in my logic for using Pascal's Triangle, I might have messed up?
THE FULL CODE:
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.lang.Math;
public class MaxPathSum {
private static ArrayList<ArrayList<Integer>> pascalsTriangle(int n_rows) {
ArrayList<ArrayList<Integer>> triangle = new ArrayList<>();
triangle.add(new ArrayList<Integer>(){{add(1);}});
triangle.add(new ArrayList<Integer>(){{add(1); add(1);}});
for (int row = 2; row < n_rows; row++) {
ArrayList<Integer> next_row = new ArrayList<>();
next_row.add(1);
for (int i = 1; i < triangle.get(row-1).size(); i++) {
next_row.add(triangle.get(row-1).get(i-1) + triangle.get(row-1).get(i));
}
next_row.add(1);
triangle.add(next_row);
}
return triangle;
}
private static ArrayList<ArrayList<Integer>> buildTriangle(int n_rows) {
Scanner sc = new Scanner(System.in);
ArrayList<ArrayList<Integer>> triangle = new ArrayList<>();
for (int row = 1; row <= n_rows; row++) {
ArrayList<Integer> row_arr = new ArrayList<>();
for (int elem = 1; elem <= row; elem++) {
row_arr.add(sc.nextInt());
}
triangle.add(row_arr);
}
return triangle;
}
private static int findLargestSum(ArrayList<ArrayList<Integer>> triangle, ArrayList<ArrayList<Integer>> p_triangle) {
ArrayList<Integer> sums = new ArrayList<>();
sums.add(triangle.get(0).get(0));
// traverse the rows
for (int row = 1, offset = 0; row < triangle.size(); row++, offset = 0) {
ArrayList<Integer> new_sums = new ArrayList<>();
// traverse each element in each row
new_sums.add(sums.get(0) + triangle.get(row).get(0));
for (int i = 1; i < triangle.get(row).size()-1; i++) {
int n_times = p_triangle.get(row).get(i);
for (int j = 0; j < n_times; j++) {
new_sums.add(triangle.get(row).get(i) + sums.get(j+offset));
}
if (i > 1) {
if (i < (p_triangle.get(row).size()/2)) offset++;
else if (i == triangle.get(row).size()-2) offset = sums.size() - p_triangle.get(row).get(i);
else offset = sums.size() - p_triangle.get(row).get(i) - (p_triangle.get(row).size() - i - 2);
System.out.println("Row: " + row + " | Offset: " + offset);
}
}
new_sums.add(sums.get(sums.size()-1) + triangle.get(row).get(triangle.get(row).size()-1));
sums = new_sums;
}
Collections.sort(sums);
return sums.get(sums.size() - 1);
}
public static void main(String[] args) {
int n_rows = Integer.parseInt(args[0]);
// build pascalsTriangle
ArrayList<ArrayList<Integer>> p_triangle = pascalsTriangle(n_rows);
// build triangle from input
ArrayList<ArrayList<Integer>> triangle = buildTriangle(n_rows);
// traverse triangle finding largest sum
int largest_sum = findLargestSum(triangle, p_triangle);
// display results
System.out.println(largest_sum);
}
}
Just be simple!
public static int findMaxSum(int[][] data) {
for (int row = data.length - 2; row >= 0; row--)
for (int col = 0; col < data[row].length; col++)
data[row][col] += Math.max(data[row + 1][col], data[row + 1][col + 1]);
return data[0][0];
}
Sorry for bad expression to make people confused, i edit my question again.
There is Integer array , it contains 29 numbers, These 29 numbres are made up of 0 to 10.
For example: Integer [ ] num ={ 0,3,4,5,6,1,3,10,4,3,1,0,2,2,3,4,1,0,8,7,6,6,5,8,9,0,5,10,8} I want to realign these numbers into Jtable(limits 6 rows,10 columns).
if 0 <= number < 5,i will call them "Small" number;
if 5 <= number < 10,i will call them “Big" number;
if number = 10, i will call them "P"number.
In a word, the 29 numbers are made up of 3 type number("Samll","Big","P").
In the array num, we can see first three number is belong to "Small" number,so they show one by one in c1,the fourth is 5,it is "Big"number,so it jump to next column, it goes c2,the remaining cells of c1 will not be used again. if the same type number is over 6,it wil turn right to next nearest cell to contiune showing(See 2nd sample image).others array numbers are the same logic,loop the array num and then show the numbers according to the number type in jtable.
The final result what i want in Jtable ,you can see below sample images i post. Anybody posts sample code will be very helpful to me,Thanks in advance!
Below sencond sample image, the red underline number total 10 "Small" numbers over 6, so turn to the right nearest cell to contiune showing. The green underline total 7 "Big" numbers ,because the sixth cell in c6 has been occupied, so it turns right to contiune showing after fifth cell
I wrote code just to create the 6 x 10 int matrix.
Here's the output from one of my many tests.
0 5 1 10 4 8 0 5 10 8
3 6 3 3 7
4 1 6
0 6
2 5 8 9
2 3 4 1 0
Oracle has a helpful tutorial, Creating a GUI With JFC/Swing, that will help you learn how to create a Swing GUI. Skip the Netbeans section.
You will want to use a JTable to display your matrix.
When tackling a problem like creating your matrix, it helps to break it down into steps. Keep breaking it down into steps until you can code each step.
This task was so complicated, I had to print debug output to make sure I was making progress. Don't be afraid to put many System.out.print and System.out.println statements in your code. You can use a DEBUG boolean like I did to turn the extra print statements off.
Here's the complete runnable code to create the 6 x 10 matrix. I didn't check for more than 10 subsets of values. I left that for you.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class RealignNumbers {
private static final boolean DEBUG = false;
public static void main(String[] args) {
RealignNumbers rn = new RealignNumbers();
int[] numbers = { 0, 3, 4, 5, 6, 1, 3, 10, 4, 3, 1, 0, 2, 2, 3, 4, 1, 0,
8, 7, 6, 6, 5, 8, 9, 0, 5, 10, 8 };
int[][] matrix = rn.realignNumbers(numbers);
printMatrix(matrix);
}
private static void printMatrix(int[][] matrix) {
for (int row = 0; row < matrix.length; row++) {
for (int column = 0; column < matrix[row].length; column++) {
if (matrix[row][column] >= 0) {
String display = String.format("%3d", matrix[row][column]);
System.out.print(display);
} else {
System.out.print(" ");
}
}
System.out.println();
}
}
public int[][] realignNumbers(int[] numbers) {
List<List<Integer>> matrixList = splitInput(numbers);
printList(matrixList);
int[][] matrix = fillMatrix(matrixList);
return matrix;
}
private List<List<Integer>> splitInput(int[] numbers) {
List<List<Integer>> matrixList = new ArrayList<>();
int number = numbers[0];
boolean isSmall = number < 5;
List<Integer> numberList = new ArrayList<>();
numberList.add(Integer.valueOf(number));
for (int index = 1; index < numbers.length; index++) {
if (numbers[index] == 10) {
// Finish prior List if exists
if (numberList.size() > 0) {
matrixList.add(numberList);
numberList = new ArrayList<>();
}
// Create numberList for 10
numberList.add(Integer.valueOf(numbers[index]));
matrixList.add(numberList);
// Start new List
numberList = new ArrayList<>();
} else {
boolean small = numbers[index] < 5;
if (isSmall == small) {
// Add number to List
numberList.add(Integer.valueOf(numbers[index]));
} else {
// Number is different; end list and start new List
matrixList.add(numberList);
numberList = new ArrayList<>();
numberList.add(Integer.valueOf(numbers[index]));
isSmall = small;
}
}
}
if (numberList.size() > 0) {
matrixList.add(numberList);
}
return matrixList;
}
private void printList(List<List<Integer>> matrixList) {
if (DEBUG) {
int count = 1;
for (List<Integer> numberList : matrixList) {
String display = String.format("%2d", count++);
System.out.print("List " + display + " ");
for (int number : numberList) {
display = String.format("%3d", number);
System.out.print(display);
}
System.out.println();
}
}
}
private int[][] fillMatrix(List<List<Integer>> matrixList) {
int masterColumn = -1;
int length = 6;
boolean firstTimeSwitch = true;
int[][] matrix = new int[length][10];
for (int[] row : matrix) {
Arrays.fill(row, -1);
}
for (List<Integer> numberList : matrixList) {
masterColumn++;
int column = masterColumn;
int row = 0;
for (int number : numberList) {
if (DEBUG) {
System.out.println("row " + row + " column " + column);
}
matrix[row][column] = number;
// Check if we hit the last row
// If so, increment columns
if (row < (length - 1)) {
row++;
} else {
if (firstTimeSwitch) {
length--;
firstTimeSwitch = false;
}
column++;
}
}
if (length < 6) {
firstTimeSwitch = true;
}
}
return matrix;
}
}
If you really want to do this, then think of a jTable much like a 2D array, for example, int[][] yourArray = new int[6][10];.
So the first number in your list goes at yourArray[0][0] = 0, and the next two go on the same column yourArray[1][0] = 3 and yourArray[2][0] = 4, and the next number 5 goes into a new column yourArray[0][1] = 5 and so on.
So when it comes to turning you could do something like this inside the loop that places numbers into the jTable:
if(row > rowCount) {
col++;
yourTableModel.setValueAt(number, row, col);
}
But to make sure that nothing overlaps when turning also use:
//Insert value if able
if(yourTableModel.getValueAt(row, col) != null){
row++;
yourTableModel.setValueAt(number, row, col);
}
//Move to next col if not able to fit the number within the row
else{
col++;
yourTableModel.setValueAt(number, row, col);
}
if we have these numbers in
array [][]
{1, 2, 3, 4},
{1, 2, 20, 4},
{1, 20, 2, 4},
{1, 2, 3, 4},};
it should looks like this
1 0 0 4
0 0 0 0
0 0 0 0
1 0 0 4
but i could output code only like this...
1 0 3 4
1 0 20 4
0 0 0 0
1 0 3 4
and i don't understand how to correct it, please help me,
this is my code.Thanks!
package com.company;
public class Main {
public static void main(String[] args) {
int[][] array2 = {{1, 2, 3, 4},
{1, 2, 20, 4},
{1, 20, 2, 4},
{1, 2, 3, 4},};
int countMax = 0;
int countIndexHorizontal = 0;
int countIndexVertical = 0;
int max = Integer.MIN_VALUE;
int m, k,x;
for (int i = 0; i < array2.length; i++) {
for (int j = 0; j < array2[i].length; j++) {
if (array2[i][j] > max) {
max = array2[i][j];
}
}
}
for (k = 0; k < array2.length; k++) {
for (m = 0; m < array2[k].length; m++) {
if (array2[k][m] == max) {
countIndexHorizontal = k;
countIndexVertical = m;
for (x = 0; x < array2.length; x++) {
for (int j = 0; j < array2[x].length; j++) {
if (countIndexVertical == x || j == countIndexHorizontal) {
array2[x][j] = 0;
}
}
}
}
}
}
for (int i = 0; i < array2.length; i++) {
for (int j = 0; j < array2[i].length; j++) {
System.out.print(array2[i][j] + " ");
}
System.out.println();
}
}
}
it looks like there are a lot of code and a little of words and site don't allow me to finally post my question and i'm really angry, maybe this text will help me to solve this problem.
Algorithm
This is the part when you only use pen and paper. Basically, I understood the problem as follow:
Given a matrix with n rows and m columns of Integer1:
Find the highest value
All entries in the rows and columns holding the highest value must have its value set at 0
Print the updated matrix
Assumption
I made the following assumptions:
In n is not necessarily equal to m. For example, you can have the array:
Valid Input
1 2 3 4 5 6
7 8 9 10 11 12
7 8 12 5 6 4
which must give, as 12 is the highest value:
Output
1 2 0 4 5 0
0 0 0 0 0 0
0 0 0 0 0 0
The matrix is consistent: every row has m columns and every column has n rows. For example, such input is incorrect:
Incorrect input
1 2 3
7 8 9 10
7 8
Logic
At this stage, you're still using pen, paper and Google only!
In my problem understanding, I splitted in three parts as I thought this is how you understood the problem. This is the mathematics understanding. Now let's convert it into a more Java understanding. First of all, we need to translate some vocabulary:
Mathematics wording | Java wording
--------------------|---------------------
matrix | 2-dimensional array
Integer | int (primitive type)
which gives in Java way:
Given an 2-dimensional int[][] array:
Find the highest value
Find the rows and columns holding the highest value
Update the array by setting the value to 0 for the rows and columns found in 2.
Print the array
In the specific case of my solution, I combine 1. + 2. and I combined 3. + 4.
What you did
Let's open your favorite IDE and compare my analysis with your input:
Find the highest value: OK here: : you use the variable max and scan the matrix to find the maximum value. You also assumed that the matrix could be rectangle (n rows and m columns with n != m). So it's good
for (int i = 0; i < array2.length; i++) {
for (int j = 0; j < array2[i].length; j++) {
if (array2[i][j] > max) {
max = array2[i][j];
}
}
}
Find the rows and columns: ERROR here, as mentioned by ccp-beginner, when you found a the highest value, you erase (set to zero) the value for the whole column and whole row but maybe the same highest value was stored somewhere else in this row or column
for (k = 0; k < array2.length; k++) {
for (m = 0; m < array2[k].length; m++) {
if (array2[k][m] == max) {
countIndexHorizontal = k;
countIndexVertical = m;
// additional operation defined in 3.
}
// in ccp-beginner example of
// 2, 2
// 1, 1
// if k=0 and m=0, you'll update the value
// of the first row and first column giving:
// 0, 0
// 0, 1
// but when k=0, m=1, you'll find 0 instead
// of 2 so your program will consider that
// this row / column does not contain the
// highest value
}
}
I assume here the
countIndexHorizontal = row
countIndexVertical = column
So you need to keep track of the rows and columns when you're setting the values to 0.
Update the array: ERROR here (cf ccp-beginner's answer)
for (x = 0; x < array2.length; x++) {
for (int j = 0; j < array2[x].length; j++) {
if (countIndexVertical == x || j == countIndexHorizontal) {
array2[x][j] = 0;
// In your example:
// 1 2 3 4
// 1 2 20 4
// 1 20 2 4
// 1 2 3 4
// and if countIndexVertical=2 and countIndexHorizontal=1
// (the 20 of the second row between 2 and 4), you'll have
// 1 0 3 4
// 1 0 20 4
// 0 0 0 0
// 1 0 3 4
// instead of
// 1 2 0 4
// 0 0 0 0
// 1 20 0 4
// 1 2 0 4
}
}
}
you got confused between countIndexVertical and countIndexHorizontal, as you have
x = row
j = column
You should had (please notice the swapping)
if (countIndexHorizontal == x || j == countIndexVertical) {
array2[x][j] = 0;
}
Print the array: OK here, nothing special to mention
for (int i = 0; i < array2.length; i++) {
for (int j = 0; j < array2[i].length; j++) {
System.out.print(array2[i][j] + " ");
}
System.out.println();
}
The problem
Basically, what you need is how to store the rows and the columns containing the highest value. At first, we could be tempted to use array again right, like
int[] rowsContainingHighestValue;
int[] columnsContainingHighestValue;
But you don't know how many highest value you'll encounter so you need something to store multiple value with a dynamic size: I'll use List.
Some Java point
The rowsContainingHighestValue and columnsContainingHighestValue become:
List<Integer> rowsContainingHighestValue = new ArrayList<>();
List<Integer> columnsContainingHighestValue = new ArrayList<>();
You may want to have a look at the following point:
Why List instead of array?
My objects are declared as List but I instantiate2 with ArrayList: What is a Interface and what is a Class
Why I used List<Integer> instead of List<int>
What is the difference between Integer and int
One solution
loop through for the matrix to fetch the maximum value and store all rows and columns holding this value instead of a single row/column combination (countIndexHorizontal and countIndexVertical)
If a new maximum value is found, store it (like you did) AND store the current row and column index
If a value is identical to the current maximum value (e.g. you have 20 twice), then append the row and column index to the existing respective row / column list
loop a second time for updating and printing the value
it's basically combining your two last double-loop: if the scanned element belongs to a row or a column holding the maximum value, then the value must be set at 0 (exactly the way you did but shorter as I already have the list of rows / columns)
once the values are properly updated, just proceed to a simple printing
Which in code gives:
public static void main(String[] args) {
int[][] array2 = {
{1, 2, 3, 4},
{1, 2, 20, 4},
{1, 20, 2, 4},
{1, 2, 3, 4}
};
// find the maximum value and store its position:
// It's List instead of a single value as multiple
// rows and columns can hold the same maximum value
List<Integer> rowsWithMaxValue = new ArrayList<>();
List<Integer> colsWithMaxValue = new ArrayList<>();
int maxValue = Integer.MIN_VALUE;
// First matrix-scan to fetch the maximum value and the
// row(s) and column(s) to set the value at 0
for (int row = 0; row < array2.length; row++) {
for (int col = 0; col < array2[row].length; col++) {
// get the current value
int value = array2[row][col];
// found a new maximum or an existing one?
if (value > maxValue) {
// this is a new maximum value, we can reset
// the list as the previous rows and columns
// are not relevant anymore
maxValue = value;
rowsWithMaxValue = new ArrayList<>();
colsWithMaxValue = new ArrayList<>();
rowsWithMaxValue.add(row);
colsWithMaxValue.add(col);
} else if (value == maxValue) {
// The same value (like 20) is found again
// so multiple rows and columns will have
// their value set at 0
rowsWithMaxValue.add(row);
colsWithMaxValue.add(col);
}
}
}
// Second matrix-scan for updating the values and printing
for (int row = 0; row < array2.length; row++) {
for (int col = 0; col < array2[row].length; col++) {
// is it in a forbidden row? If yes, set the value
// at zero. One of the condition (row or column) is
// enough to have its value set at 0
if (rowsWithMaxValue.contains(row) || colsWithMaxValue.contains(col)) {
array2[row][col] = 0;
}
// Simply print the value
System.out.print(array2[row][col] + " ");
}
System.out.println();
}
}
1Integer in the mathematics meaning: positive or negative number without decimal
2I won't explain instantiation here. Feel free to google it
You can improve the program by changing the condition to
if (countIndexHorizontal == x || j == countIndexVertical)
Your program is deleting the wrong lines for the first 20 it finds (including the other 20).
This change will get you the correct answer for your specific case, but the program is still broken for examples like this
2 2
1 1
The correct output is
0 0
0 0
but it won't work because when it finds the first 2 it will delete the second 2, but the second 2 is still needed to clear the 0 in the bottom right corner. You're going to have to keep a separate data structure for the positions you want to clear. I'll leave that for you to figure out.
The program I need to write is a square 2d array made of numbers, like this
0 1 2
3 4 5
6 7 8
or this
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
The program reads the number "d" (side of the square 2d array- above are examples of d=3 and d=5), number "n" (how many inputs there will be next) and these n inputs (eg. if n=3, the program should let me insert three numbers, like from the first example, let's say I'd choose 1 and 4 and 3. So the input looks like:
3
3
1 4 2
Then, it needs to calculate the distance between the first and second, second and third input and sum them up. That sum is then the output. Here is the program
if(b==2) {
int d=sc.nextInt();
int n=sc.nextInt();
int[][] array=new int[d][d]; //length and heigth of array
int c=0;
int manhattanDistanceSum=0;
for (int i = 0; i < n; i ++){ //for inserting values
for (int j = 0; j < n; j ++){
if (i < n){
i++;
array[i][j] = sc.nextInt();
}
else {
break;
}
for( i=0; i<array.length;i++) {
for( j=0;j<array[0].length;j++) {
array[i][j]=c; //actual locations of numbers
//numbers in array
c++;
if(manhattanDistanceSum != 0) {
int dx= c / d;
int dy= c % d;
c=Math.abs(dx) + Math.abs(dy);
manhattanDistanceSum+=c;
}
}
}
System.out.print(array[i][j]);
System.out.println();
}
}
System.out.println(manhattanDistanceSum);
}
}
}
*the b doesn't matter, it just means this is going to be a square array, so ignore it. It has nothing to do with this.
This is all I got, and need help with anything that is wrong in my code.
Thankyou
I've just cobbled together this example and tested that it works with positive and negative numbers. It might not do exactly what you want (for example, is the data in your array organised row-by-column or column-by-row) and it might not exactly format the output the way you want, but it should show you how to iterate through the array and analyse and then extract the data to produce a String which can be printed out.
Be sure to conduct your own testing (create unit tests for all cases which your application will need) as I have thrown this together in a few minutes in the hope that it would get you started. It should not be considered a finished product by any means.
public static void main(String[] args) {
int[][] data = {{0, -10734, 2}, {3, 437, 5}, {6, 733838, 8}};
System.out.println("Table:\n" + formatAsTable(data));
}
public static String formatAsTable(int[][] squareNumericArray) {
int cellSpacing = 2;
StringBuilder sb = new StringBuilder();
int squareSide = squareNumericArray.length;
int cellSize = findLargestNumericString(squareNumericArray)
+ cellSpacing;
for (int firstIndex = 0; firstIndex < squareSide; ++firstIndex) {
if (squareNumericArray[firstIndex].length != squareSide) {
throw new IllegalArgumentException(
"Array must have same size in both dimensions.");
}
for (int secondIndex = 0; secondIndex < squareSide; ++secondIndex) {
sb.append(String.format("%-" + cellSize + "d",
squareNumericArray[firstIndex][secondIndex]));
}
sb.append("\n");
}
return sb.toString();
}
private static int findLargestNumericString(int[][] squareNumericArray) {
int maxLength = 0;
for (int firstIndex = 0; firstIndex < squareNumericArray.length;
++firstIndex) {
for (int secondIndex = 0; secondIndex
< squareNumericArray[firstIndex].length; ++secondIndex) {
String numberAsString = Integer.toString(
squareNumericArray[firstIndex][secondIndex]);
if (numberAsString.length() > maxLength) {
maxLength = numberAsString.length();
}
}
}
return maxLength;
}
This code will output the following to the console:
Table:
0 -10734 6
3 437 5
6 733838 19
Having an array such as int[] arr = new int[]{9, 6, 5, 2, 1, 2, 6, 3, 2, 7, 3, 8, 1, 5, 4, 7}; I want to print it like this:
* Output:
* 9
* 6 1
* 5 2 2
* 2 6 7 1
* 3 3 5
* 8 4
* 7
Without the * basically that's what I am trying to do. I intended to go over the array and just use System.out.println();until I reached then "end" which would be the 7 and then go to the next line but that didn't work.
I also tried printing 9 then 6 and 1 and so on but I couldn't make it to work either, I'm at a loss here and would appreciate guidance as to how can I think this through please.
EDIT
The intermediate step I have is making the array a "block" like this:
* Intermediate Step:
* 9 6 5 2
* 1 2 6 3
* 2 7 3 8
* 1 5 4 7
It should work for an array of any size.
I think this should work
You iterate 2 times. first you get the first row and all the diagonal rows below it, and then the last row and all the diagonal rows above it. You have to create a second array though to hold this info. I assumed that the array is same size for both X and Y. 7x7, 4x4 etc. tested with 4x4 data (your data)
String[][] array2 = new String[array.length*2][array.length];
for (int mb = 0; mb < array.length; mb++) {
String p1 = array[0][mb];
array2[mb][0] = p1;
int count = 0;
for (int i=1;i<=mb;i++) {
count++;
String p2 = array[i][mb-i];
array2[mb][count] = p2;
}
}
int counter = -1;
for (int mb = array.length -1; mb > 0; mb--) {
counter++;
String p1 = array[array.length -1][mb];
array2[mb+array.length -1][counter] = p1;
for (int i=0;i<counter;i++) {
String p2 = array[array.length -2 - i][array.length -counter + i];
array2[mb+array.length -1][i] = p2;
}
}
Well lets think you have two-dimensional array (you can change your one-dimension to two-dimensional easily)
PseudoCode :
whereToGo = RIGHT;
i = 0;
j = 0;
maxX = WIDTH;
maxY = HEIGHT;
minX = 0;
minY = 0;
while (somethingLeft){
addNumberToPyramid(array[i][j]);
if (whereToGo == RIGHT){
i++;
if (maxX == i) {
whereToGo = DOWN;
minY++;
}
} else if (whereToGo == DOWN){
//Same as if you go RIGHT, but increasing "j", at the end, you decrease maxY and then goLeft
} //... other two directions
}
This is how to parse input. Similar way for adding it to pyramid. I would prefer creating another 2D array, put that directly there as pyramid and then write method for printing this array correctly :
public class Pyramid{
//initialize minX, maxX etc.
int[][] array;
whereToGo = DOWN;
int i = 0, j = 0;
//initialize array size in constructor
public void addNumberToPyramid(int value){
if (whereToGo == DOWN){
array[i][j] == value;
j++;
if (j == maxY){
whereToGo = UPRIGHT;
maxY -= 2;
} else if (whereToGo == UPRIGHT){
} //... other else if directions
}
}
}
OK, first of all: You can't print a triangle like that for every length of an array. Say for example you had that array but missing the last entry; then your triangle would be missing one element at some point. In fact, you can print such a triangle if and only if the number of elements is the square of a natural number; in your example 16 = 4^2. Now, that 4 is also the length of your longest row.
OK, now how to do it. If you look at the intermediate step
9 6 5 2
1 2 6 3
2 7 3 8
1 5 4 7
and call that arr2, you want to print arr2[0][0] in the first row, arr2[1][0] and arr2[0][1] in the second row and so on until row 4 (which is of course the root of the length of the initial array). So you can write a nested loop that counts up like that.
Then you want to print arr2[1][3], arr2[2][2] and arr2[3][1] in the next row, then arr2[2][3] an arr2[3][2] and finally in the last row just arr2[3][3]. That is most easily done in a second nested loop.
I won't give you the exact code of course as this is obviously a learning task. But I will tell you that if you have a counter i for the outer loops and a counter j for the inner ones, the indexes in the intermediate array will depend on both i and j.