I've been tackling this one problem and currently having a lack of ideas of how to parse a numerical data divided into small snippets of data squares into two dimensional array. Data is arranged in rectangle like form (Supposedly similar as it would be in a file/text file). Data would look like like in the picture provided below, numerical values can be completely random so they do not matter. I would need to parse all possible squares (red, blue and green highlighted ones are an example) that can be found within that rectangle into an array of square objects .
The problem I am facing is figuring out the way to read all possible square combinations within this rectangle and properly writing them to the console. (I am sure if I could read and print them properly to the console I won't be having too much trouble storing that data either.). I've been thinking of how to do it in several ways, but unfortunately all those attempts and ponderings didn't click in my mind properly. I am not sure if my thoughts would be of any help to you, but here is a snippet of my miserable attempt at figuring this parsing problem. I am trying to print to the console at least 3x3 squares that could be found within the rectangle (matrix/2D array - you name it). It'd be great if anyone could help me figure out how to read and print all possible squares that can be found within that rectangle.
EDIT: Since I can't post images due to website restrictions, I am leaving the link:
Data Image
EDIT2: I also noticed that square highlighted in green colour is incorrect due to not being actually a square, please ignore that and excuse me for inconvenience and possible confusion.
public static void main(String[] args){
int[][] rectangle = {
{4, 9, 6, 2, 6},
{3, 5, 1, 6, 4},
{8, 1, 5, 6, 2},
{1, 1, 6, 2, 2}
};
int m = 5; // row length
int n = 4; // column length
int min = 3; // minimum square row/column length for iteration
int start = 0;
int step = 0;
for (int x = 0; x < n-1; x++){
for(int y = start; y < m-1; y++){
if (y < min){ // no idea how to make this part work
System.out.print(rectangle[x][y] + " ");
step++;
}
if(Math.pow(min, 2) == step && x != n - 1){
// once here save the square, initialize new one;
System.out.println("");
step = 0;
start++;
y = start;
x++;
}
// all squares have been read in x-th column, moving more to the right
if( x == n - 1 && y == min - 1 && x != y){
y = start + 1;
x = 0;
}
}
System.out.println(" ");
}
}
This algorithm works as follows:
determine all points that can be the upper-left-hand-corners of a square in a given rectengle
for each of these determine all possible sizes, so that the complete square is in the rectange
do thins with the new-found squares (in this case print two oppisite corners)
int[][] rectangle = {
{4, 9, 6, 2, 6},
{3, 5, 1, 6, 4},
{8, 1, 5, 6, 2},
{1, 1, 6, 2, 2}
};
int m = 5; // row length
int n = 4; // column length
int min = 3; // minimum square row/column length for iteration
//Take all possible upper-left-hand-corners
for(int row = 0; row <= n - min; row++){
for(int column = 0; column <= m - min; column++){
//Determine all possible square sizes from that corner
for(int size = min; size <= n - row && size <= m - column; size++){
//This will print the upper-left-hand-corner
//and the lower-right-hand-corner as (x|y)
//Place here anything that you want to do with the squares
System.out.println("(" + column + "|" + row + ") to ("
+ (column+size-1) + "|" + (row+size-1) + "), size: " + size);
}
}
}
One note on n and m: You might not want to hardcode the values for the dimensions of the rectangle. Instead you might want to use:
int m = rectangle[0].length;
int n = rectange.length;
Related
I'm working on the following task.
Given an array of n integers and two integer numbers m and k.
You can add any positive integer to any element of the array such that
the total value does not exceed k.
The task is to maximize the
multiples of m in the resultant array.
Consider the following example.
Input:
n = 5, m = 2, k = 2, arr[] = [1, 2, 3, 4, 5]
Let's add 1 to the element arr[0] and 1 to arr[2] then the final array would be:
[2, 2, 4, 4, 5]
Now there are four (4) elements which are multiples of m (2).
I am not getting correct output.
My code:
public class Main {
public static void main(String[] args) {
int n = 5;
int m = 4;
int k = 3;
int count = 0;
int[] arr = {17, 8, 9, 1, 4};
for (int i = 0; i < n; i++) {
for (int j = 0; j <= k; j++) {
// check initial
if (arr[i] % m == 0) {
break;
}
// add
arr[i] = arr[i] + j;
// check again
if (arr[i] % m == 0) {
count++;
break;
}
}
}
System.out.println("Final Array : " + Arrays.toString(arr));
System.out.println("Count : " + count);
}
}
This task boils down to a well-known Dynamic programming algorithm called Knapsack problem after a couple of simple manipulations with the given array.
This approach doesn't require sorting and would be advantages when k is much smaller n.
We can address the problem in the following steps:
Iterate over the given array and count all the numbers that are already divisible by m (this number is stored in the variable count in the code below).
While iterating, for every element of the array calculate the difference between m and remainder from the division of this element by m. Which would be equal to m - currentElement % m. If the difference is smaller or equal to k (it can cave this difference) it should be added to the list (differences in the code below) and also accumulated in a variable which is meant to store the total difference (totalDiff). All the elements which produce difference that exceeds k would be omitted.
If the total difference is less than or equal to k - we are done, the return value would be equal to the number of elements divisible by m plus the size of the list of differences.
Otherwise, we need to apply the logic of the Knapsack problem to the list of differences.
The idea behind the method getBestCount() (which is an implementation Knapsack problem) boils down to generating the "2D" array (a nested array of length equal to the size of the list of differences +1, in which every inner array having the length of k+1) and populating it with maximum values that could be achieved for various states of the Knapsack.
Each element of this array would represent the maximum total number of elements which can be adjusted to make them divisible by m for the various sizes of the Knapsack, i.e. number of items available from the list of differences, and different number of k (in the range from 0 to k inclusive).
The best way to understand how the algorithm works is to draw a table on a piece of paper and fill it with numbers manually (follow the comments in the code, some intermediate variables were introduced only for the purpose of making it easier to grasp, and also see the Wiki article linked above).
For instance, if the given array is [1, 8, 3, 9, 5], k=3 and m=3. We can see 2 elements divisible by m - 3 and 9. Numbers 1, 8, 5 would give the following list of differences [2, 1, 1]. Applying the logic of the Knapsack algorithm, we should get the following table:
[0, 0, 0, 0]
[0, 0, 1, 1]
[0, 1, 1, 2]
[0, 1, 2, 2]
We are interested in the value right most column of the last row, which is 2 plus 2 (number of elements divisible by 3) would give us 4.
Note: that code provided below can dial only with positive numbers. I don't want to shift the focus from the algorithm to such minor details. If OP or reader of the post are interested in making the code capable to work with negative number as well, I'm living the task of adjusting the code for them as an exercise. Hint: only a small change in the countMultiplesOfM() required for that purpose.
That how it might be implemented:
public static int countMultiplesOfM(int[] arr, int k, int m) {
List<Integer> differences = new ArrayList<>();
int count = 0;
long totalDiff = 0; // counter for the early kill - case when `k >= totalDiff`
for (int next : arr) {
if (next % m == 0)
count++; // number is already divisible by `m` we can increment the count and from that moment we are no longer interested in it
else if (m - next % m <= k) {
differences.add(m - next % m);
totalDiff += m - next % m;
}
}
if (totalDiff <= k) { // early kill - `k` is large enough to adjust all numbers in the `differences` list
return count + differences.size();
}
return count + getBestCount(differences, k); // fire the rest logic
}
// Knapsack Algorithm implementation
public static int getBestCount(List<Integer> differences, int knapsackSize) {
int[][] tab = new int[differences.size() + 1][knapsackSize + 1];
for (int numItemAvailable = 1; numItemAvailable < tab.length; numItemAvailable++) {
int next = differences.get(numItemAvailable - 1); // next available item which we're trying to place to knapsack to Maximize the current total
for (int size = 1; size < tab[numItemAvailable].length; size++) {
int prevColMax = tab[numItemAvailable][size - 1]; // maximum result for the current size - 1 in the current row of the table
int prevRowMax = tab[numItemAvailable - 1][size]; // previous maximum result for the current knapsack's size
if (next <= size) { // if it's possible to fit the next item in the knapsack
int prevRowMaxWithRoomForNewItem = tab[numItemAvailable - 1][size - next] + 1; // maximum result from the previous row for the size = `current size - next` (i.e. the closest knapsack size which guarantees that there would be a space for the new item)
tab[numItemAvailable][size] = Math.max(prevColMax, prevRowMaxWithRoomForNewItem);
} else {
tab[numItemAvailable][size] = Math.max(prevRowMax, prevColMax); // either a value in the previous row or a value in the previous column of the current row
}
}
}
return tab[differences.size()][knapsackSize];
}
main()
public static void main(String[] args) {
System.out.println(countMultiplesOfM(new int[]{17, 8, 9, 1, 4}, 3, 4));
System.out.println(countMultiplesOfM(new int[]{1, 2, 3, 4, 5}, 2, 2));
System.out.println(countMultiplesOfM(new int[]{1, 8, 3, 9, 5}, 3, 3));
}
Output:
3 // input array [17, 8, 9, 1, 4], m = 4, k = 3
4 // input array [1, 2, 3, 4, 5], m = 2, k = 2
4 // input array [1, 8, 3, 9, 5], m = 3, k = 3
A link to Online Demo
You must change 2 line in your code :
if(arr[i]%m==0)
{
count++; // add this line
break;
}
// add
arr[i]=arr[i]+1; // change j to 1
// check again
if(arr[i]%m==0)
{
count++;
break;
}
The first is because the number itself is divisible.
and The second is because you add a number to it each time.That is wrong.
for example chenge your arr to :
int[] arr ={17,8,10,2,4};
your output is :
Final Array : [20, 8, 16, 8, 4]
and That is wrong because 16-10=6 and is bigger than k=3.
I believe the problem is that you aren't processing the values in ascending order of the amount by which to adjust.
To solve this I started by using a stream to preprocess the array. This could be done using other methods.
map the values to the amount to make each one, when added, divisible by m.
filter out those that equal to m' (already divisible by m`)
sort in ascending order.
Once that is done. Intialize max to the difference between the original array length and the processed length. This is the number already divisible by m.
As the list is iterated
check to see if k > amount needed. If so, subtract from k and increment max
otherwise break out of the loop (because of the sort, no value remaining can be less than k)
public static int maxDivisors(int m, int k, int[] arr) {
int[] need = Arrays.stream(arr).map(v -> m - v % m)
.filter(v -> v != m).sorted().toArray();
int max = arr.length - need.length;
for (int val : need) {
if (k >= val) {
k -= val;
max++;
} else {
break;
}
}
return max;
}
int m = 4;
int k = 3;
int[] arr ={17,8,9,1,4};
int count = maxDivisors(m, k, arr);
System.out.println(count);
prints
3
Input : arr[] : {1, 2, 3, 4, 5}
ranges[] = { {0, 2}, {0, 3} }
index : 1
Output : 3
Explanation : After first given rotation {0, 2}
arr[] = {3, 1, 2, 4, 5}
After second rotation {0, 3}
arr[] = {4, 3, 1, 2, 5}
After all rotations we have element 3 at given index 1.
Not Able to Understand Why starting from last rotation gives right result but if we start from rotation 0 to last in loop it gives wrong result???
https://www.geeksforgeeks.org/find-element-given-index-number-rotations/
// Java code to rotate an array
// and answer the index query
import java.util.*;
class GFG
{
// Function to compute the element at
// given index
static int findElement(int[] arr, int[][] ranges,
int rotations, int index)
{
for (int i = rotations - 1; i >= 0; i--) {
// Range[left...right]
int left = ranges[i][0];
int right = ranges[i][1];
// Rotation will not have any effect
if (left <= index && right >= index) {
if (index == left)
index = right;
else
index--;
}
}
// Returning new element
return arr[index];
}
// Driver
public static void main (String[] args) {
int[] arr = { 1, 2, 3, 4, 5 };
// No. of rotations
int rotations = 2;
// Ranges according to 0-based indexing
int[][] ranges = { { 0, 2 }, { 0, 3 } };
int index = 1;
System.out.println(findElement(arr, ranges,
rotations, index));
}
}
This will give right result but following will produce wrong result.
for (int i = 0; i < rotations; i++) {
// Range[left...right]
int left = ranges[i][0];
int right = ranges[i][1];
// Rotation will not have any effect
if (left <= index && right >= index) {
if (index == left)
index = right;
else
index--;
}
}
Lets us consider given 5 length array A1.
You have applied {0,2} rotation on A1. It is changed to A2.
You have applied {0,3} rotation on A2.. It is changed to A3
Now you are looking for output index 1 in A3 (which is {0,3} rotated on A2).
So Index 1 in A3 = Index 0 in A2 (as per the logic)
Now you are looking for Index 0 in A2 (which is {0,2} rotated on A1)
So Index 0 in A2 = Index 2 in A1 (as per the logic)
Hope this explanation clears why the rotations array is iterated in reverse way.
Not Able to Understand Why starting from last rotation gives right
result but if we start from rotation 0 to last in loop it gives wrong
result???
Because its not supposed to give the same output. The final results depends on the order in which you apply the rotations.
Suppose first you apply {0,3}, the array would be :
4 , 1 , 2 , 3 , 5
Now you apply {0,2}
2 , 4 , 1 , 3 , 5
Clearly the element at index 1 is NOT 3
For example I have array with length n=3:
for(int i = 0; i < n; i++) {
array[i] = i;
}
So the cases should be:
1. 0
2. 1
3. 2
4. 0 1
5. 0 2
6. 1 2
7. 0 1 2
So the number of cases should be 7 for n = 3.
In my code:
int n = 3;
int[] array = new int[n];
for (int i = 0; i < n; i++) {
array[i] = i;
}
int sum = 0;
for (int i = 0; i < n; i++) {
System.out.println(array[i] + " ");
sum++;
for (int j = i; j < n; j++) {
System.out.print(array[j] + " ");
}
System.out.println();
sum++;
}
System.out.println("sum = " + sum);
Output is:
0
0 1 2
1
1 2
2
2
sum = 6
The number 2 is two times so it is wrong and sum is actually = 5. And I don't get cases
4. 0 1
and
5. 0 2
How to count all possible cases?
Sets, not arrays
The first important observance is that you are not using fixed length arrays here but sets of different lengths.
Take a look at your example. You allow
0
1
2
0, 1
0, 2
1, 2
which are not all of size 3.
Also you don't differentiate between
0, 1
1, 0
so order doesn't matter, like in sets.
Power set
That's why you're actually describing power sets here. For the example set {0, 1, 2} its power set is defined as
P({0, 1, 2}) = {
{}, // empty set
{0},
{1},
{2},
{0, 1},
{0, 2},
{1, 2},
{0, 1, 2}
}
Fortunately there exists an easy closed formula for their size. If n is the size of the input set the size of the power set is
2^n
But they also count the empty set, so you will need to -1 if you don't want that:
2^n - 1
Solution
Thus in Java you could write
int Set<Integer> input = ...
int size = (int) Math.pow(2, input.size()) - 1;
and that's all, you don't need to build the contents manually.
But if you're curious and want to build them, take a look at questions like Obtaining a powerset of a set in Java. It's an implementation of the recursive formula shown at Wikipedia.
So, totally inefficient but also working:
int Set<Integer> input = ...
// Build the power-set using the method from linked question
Set<Set<Integer>> power = powerSet(input);
int size = power.size() - 1;
I need the sum of the variables around 2,2 and then to print it out.
I have no idea on how to do this. Please do help!
This is my code so far:
import java.util.*;
import java.io.*;
public class MatrixSumming
{
private int[][] m = {{5,6},{7,8},{3,4}}; //load in the matrix values
public int sum( int r, int c )
{
return 0;
}
public String toString()
{
return "";
}
}
Here is my runner
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
import static java.lang.System.*;
public class MatrixSummingRunner
{
public static void main( String args[] ) throws IOException
{
//Scanner file = new Scanner (new File("matsum.dat"));
int[][] mat = {{0, 0, 0, 0, 0, 0, 0},
{0, 1, 2, 3, 4, 5, 0},
{0, 6, 7, 8, 9, 0, 0},
{0, 6, 7, 1, 2, 5, 0},
{0, 6, 7, 8, 9, 0, 0},
{0, 5, 4, 3, 2, 1, 0},
{0, 0, 0, 0, 0, 0, 0}};
}
}
I tried finding but couldn't find anything similar to this in matrix.
Do a regular search for the required number and let the index vvalues be "curi" and "curj"
Use the following logic
Let maxi and maxj be the m and n for (mxn) matrix
sum = 0;
for(int i=curi-1;i<curi+3;i++){
for(int j=curj-1;j<curj+3;j++){
if(i>-1 && j>-1 && i<maxi && j<maxj){ // boundary conditions
if(i!=curi && j!=curj){
continue; // skip the current search key to add
}
sum += array[i][j];
}
}
}
You have this method public int sum( int r, int c ) where you pass in two ints.
These are the row and column index, and correspond to a position in the matrix. (Or you have to substract 1, if you take row 1 as the first row, because of the zero-indexed arrays in Java)
So if you have a matrix and the values r and c, you will be at position matrix[r][c] (or the other way round).
Imagine standing on a chess board. Now you have 8 fields around you, which you can reach by taking one step. (Or two, if you cannot move diagonally in one step). You might not have fields on one or more sides. You have to check this before computing a sum.
Now, taking a step means adding or substracting 1 to either r or c. Thus you get other indexes around the field you're standing at by addressing matrix[r-1][c] or matrix[r][c+1] etc. To move diagonally, you have to change both r and c (take two steps. e.g. first move one to the left, then one up. you moved to the field diagonally at the upper left of the original field)
You can then, using this knowledge, access the fields around the current field and sum them up.
This method will get all the surrounding cells values and sum them.
private static int neighboursSum(int[][] grid, int r, int c) {
int sum = 0;
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
// Make sure that we don't sum the Original Value, we only want it's neighbours
if (i == 0 && j == 0) {
continue;
} else {
int newX = r + i;
int newY = c + j;
// Make sure that the new Coordinates do not point outside the range of the Array
if (newX >= 0 && newX <= grid.length && newY >= 0 && newY <= grid.length) {
sum += grid[newX][newY];
}
}
}
}
return sum;
}
For my summer Java class, I'm working on a program that detects whether the elements in an array are a magic square. I'm not entirely sure how to properly iterate through the array to be able to calculate the total of the separate columns and rows to determine if the array is a magic square. We were given the code for the sum of the down diagonal, but I'm unsure how to approach the up diagonal, rows and columns. Here is a snippet of my code so far.
public class MagicSqaure
{
public static void main(String[] args)
{
int[][] array =
{
{2, 7, 6},
{9, 5, 1},
{4, 3, 8}
};
public static int getSumOfDownDiagonal(int[][] array)
{
int total = 0;
for (int i = 0; i < array.length; i++)
{
total += array[i][i];
}
return total;
}
Since it is a class, I can only provide help on how to accomplish traversing through the rows, columns and up diagonal, but providing **no code at all*. It's up to you to do the right implementation, otherwise you're not learning but copying/pasting/becoming a zombie coder.
To traverse each row, go through the elements of your array of arrays like this:
total += array[i][j];
Where i won't change but j changes.
To traverse each column, go through the elements of your array of arrays like this:
total += array[i][j];
Where i changes but j won't change.
To traverse the up diagonal, go through the elements of your array of arrays like this:
total += array[i][j];
Where i starts at the last possible index of the array of arrays and j starts at the first index of the array of arrays.
Whenever I need to derive equations for certain behaviors, I just write a few of the answers out manually then look for patterns. First let's assume this is how we access items in the array:
column
0 1 2
--------
0 | 2 7 6
row 1 | 9 5 1
2 | 4 3 8
(Using array[column][row])
Now let's get the indices for the columns:
column 0 = {2, 9, 4} = array[0][0], array[0][1], array[0][2]
column 1 = {7, 5, 3} = array[1][0], array[1][1], array[1][2]
And here are the rows:
row 0 = {2, 7, 6} = array[0][0], array[1][0], array[2][0]
row 1 = {9, 5, 1} = array[0][1], array[1][1], array[2][1]
And here's the other diagonal:
3x3 array = {4, 5, 6} = array[0][2], array[1][1], array[2][0]
4x4 array = array[0][3], array[1][2], array[2][1], array[3][0]
Notice any patterns? For the diagonal, we start at array[0][array.length - 1] and end at array[array.length - 1][0]. This means our loop would be as follows:
int total = 0;
for (int i = 0; i < array.length; i++)
{
total += array[i][array.length - 1 - i];
}
return total;
And to sum a column, it'd be:
int total = 0;
for (int i = 0; i < array.length; i++)
{
total += array[column_index][i];
}
return total;
And for rows:
int total = 0;
for (int i = 0; i < array.length; i++)
{
total += array[i][row_index];
}
return total;
EDIT: In response to downvotes and comments, I have modified the magic square code to work with row-major conventions. Oh wait, no I didn't since the code would be identical. Anyway, this is how you do it.