Reputation: 25
How would I change the size of a 2d array without rearranging the numbers in an array mainly using for loops and only built in methods? For example, {{4,5,6,7,10}, {8,4,3,9,13}} to become {{4}, {5,6}, {7,10,8}, {4,3,9,13}}.
I tried making the 2d array into two separate parts then adding it back to a new 2d array. I'm not sure how I would create the second 2d array.
Upvotes: 1
Views: 286
Reputation: 159096
Here's one way to do it, using pure Java code (e.g. loops) and no methods at all.
static int[][] toTriangle(int[][] input) {
// Count number of values
int valueCount = 0;
for (int[] inputRow : input)
valueCount += inputRow.length;
if (valueCount == 0)
return new int[0][0];
// Determine number of result rows, and how many values that can store
int resultRowCount = 0, resultCount = 0;
for (int row = 0; resultCount < valueCount; row++) {
resultRowCount++;
resultCount += row + 1;
}
int oversize = resultCount - valueCount;
// Build result jagged array (last row is likely truncated)
int[][] result = new int[resultRowCount][];
for (int row = 0; row < resultRowCount - 1; row++)
result[row] = new int[row + 1];
result[resultRowCount - 1] = new int[resultRowCount - oversize];
// Copy values
int inputRow = 0, inputCol = 0;
for (int[] resultRow : result) {
for (int i = 0; i < resultRow.length; i++) {
while (inputCol == input[inputRow].length) {
inputRow++;
inputCol = 0;
}
resultRow[i] = input[inputRow][inputCol++];
}
}
return result;
}
Tests
test(new int[][] {{4,5,6,7,10}, {8,4,3,9,13}});
test(new int[][] {{1,2,3,4}, {}, {5,6,7}});
static void test(int[][] input) {
print("Input", input);
print("Result", toTriangle(input));
}
static void print(String label, int[][] arr) {
System.out.println(label + ":");
for (int[] row : arr) {
System.out.print(" [");
String sep = "";
for (int val : row) {
System.out.print(sep + val);
sep = ", ";
}
System.out.println("]");
}
}
Outputs
Input:
[4, 5, 6, 7, 10]
[8, 4, 3, 9, 13]
Result:
[4]
[5, 6]
[7, 10, 8]
[4, 3, 9, 13]
Input:
[1, 2, 3, 4]
[]
[5, 6, 7]
Result:
[1]
[2, 3]
[4, 5, 6]
[7]
Notice how the last row is truncated in length, since there are not enough values to fill a triangle. The second example also shows that it can handle empty sub-arrays in the input.
Upvotes: 0
Reputation: 40034
There are many ways to do this. Here is one that works for any triangular number
of elements that originate in a 2D array.
First, flatten them all into a single array.
int[] oneD = Arrays.stream(src).flatMapToInt(Arrays::stream).toArray();
Then reversing the length which should be k
where k = n(n+1)/2
the
number of rows would be the following. And the 2D result is partially allocated.
int rows = (int)(Math.sqrt(2*oneD.length + .25) -.5);
int[][] dest = new int[rows][];
Now it's just a matter of copying from the oneD
array to the destination.
for (int i = 0, s = 0, e = 1; i < rows; i++) {
dest[i] = Arrays.copyOfRange(oneD, s, e );
s = e;
e += i+2;
}
for (int[] arr : dest) {
System.out.println(Arrays.toString(arr));
}
Prints
[4]
[5, 6]
[7, 10, 8]
[4, 3, 9, 13]
Upvotes: 1
Reputation: 2360
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
public class ArrayResize {
public static void main(String[] args) {
Integer[][] input = new Integer[][] {{10, 11, 12 ,13, 14}, {15, 16, 17, 18, 19}};
AtomicInteger index = new AtomicInteger(0);
AtomicInteger group = new AtomicInteger(1);
Collection<List<Integer>> out = Arrays.stream(input)
.flatMap(i -> Arrays.stream(i)) // flatten
.collect(Collectors.groupingBy(i -> {
final int currentIndex = index.getAndIncrement();
return (group.get() * (group.get() + 1)) / 2 == currentIndex
? group.incrementAndGet() // increment group if index matches the summation of the range
: group.get(); // return the group
}))
.values();
System.out.println(out);
}
}
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
public class ArrayResize {
public static void main(String[] args) {
Integer[][] input = new Integer[][] {{10, 11, 12 ,13, 14}, {15, 16, 17, 18, 19}};
AtomicInteger index = new AtomicInteger(0);
AtomicInteger group = new AtomicInteger(1);
Integer[][] output = Arrays.stream(input)
.flatMap(i -> Arrays.stream(i)) // flatten
.collect(Collectors.groupingBy(i -> {
final int currentIndex = index.getAndIncrement();
return (group.get() * (group.get() + 1)) / 2 == currentIndex
? group.incrementAndGet() // increment group if index matches the summation of the range
: group.get(); // return the group
})).values().stream() // stream collection
.map(subgroup -> subgroup.toArray(new Integer[0])) // map subgroups to arrays
.collect(Collectors.toList()) // collect as list of arrays
.toArray(new Integer[0][0]); // convert to array
System.out.println(Arrays.deepToString(output));
}
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class ArrayResize {
public static void main(String[] args) {
Integer[][] input = new Integer[][] {{10, 11, 12 ,13, 14}, {15, 16, 17, 18, 19}};
List<Integer> flattened = Arrays.stream(input).flatMap(i -> Arrays.stream(i)).collect(Collectors.toList());
List<Integer[]> temporary = new ArrayList<>();
final int count = flattened.size();
int start = 0;
int range = 1;
while (start < count) {
temporary.add(flattened.subList(start, Math.min(start + range, count)).toArray(new Integer[0]));
start += range;
range++;
}
Integer[][] result = temporary.toArray(new Integer[0][0]);
System.out.println(Arrays.deepToString(result));
}
}
Upvotes: 0
Reputation: 15
If I understood your question, I recommend you use List<List<Integer>>
, for example ArrayList, insted of pure arrays, and you can set your aggregations like this:
List<List<Integer>> matrix = new ArrayList<>();
List<Integer> values = new ArrayList<>();
// add {4,5,6,7,10} to array, result = {{4,5,6,7,10}}
values = new ArrayList<>(Arrays.asList(4,5,6,7,10));
matrix.add(values);
// add {8,4,3,9,13} to last array, result = {{4,5,6,7,10}, {8,4,3,9,13}}
values = new ArrayList<>(Arrays.asList(8,4,3,9,13));
matrix.add(values);
System.out.println("start="+ matrix);
// reset array or you can use another array to copy
matrix = new ArrayList<>();
values = new ArrayList<>(Arrays.asList(4));
matrix.add(values);
values = new ArrayList<>(Arrays.asList(5,6));
matrix.add(values);
values = new ArrayList<>(Arrays.asList(7,10,8));
matrix.add(values);
values = new ArrayList<>(Arrays.asList(4,3,9,13));
matrix.add(values);
System.out.println("end="+ matrix);
Output: start=[[4, 5, 6, 7, 10], [8, 4, 3, 9, 13]] end=[[4], [5, 6], [7, 10, 8], [4, 3, 9, 13]]
Upvotes: 0