Matrix manipulation (rotation/rolling) - java

I have this 3x3 matrix:
{
[1,2,3],
[4,5,6],
[7,8,9]
}
Suppose that if I send two parameters m and n, this matrix must move m and n positions (m positive / move right or negative move left) and (n positive / move down or n negative move up). For the sample if I send m = 1 , n = 0:
{
[3, 1, 2],
[6, 4, 5],
[9, 7, 8]
}
Is there some kind of method to do this? Or is it just 'hard handwork'?

If you are prepared to use List<List<Integer>> instead of int[][] you can use Collections.rotate(List list,int distance).
private void rotate(List<List<Integer>> matrix, int m, int n) {
for (List<Integer> row : matrix) {
Collections.rotate(row, m);
}
Collections.rotate(matrix, n);
}
public void test() {
int[][] m = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
List<List<Integer>> matrix = new ArrayList<>();
for (int[] r : m) {
List<Integer> row = new ArrayList<>();
for (int v : r) {
row.add(v);
}
matrix.add(row);
}
System.out.println("Before: " + matrix);
rotate(matrix, 1, 2);
System.out.println("After: " + matrix);
}
Prints:
Before: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
After: [[3, 1, 2], [6, 4, 5], [9, 7, 8]]
which is slightly different from what you were expecting but it looks like it makes sense.

Related

Generate all possible combinations of an array of size n having exactly k subarrays

It's a combinatorics problem. We can partition the array at max n-1 times and out of it, we have to choose k-1 partitions.
Ex: arr[] = {1, 2, 3, 4, 5, 6}
k = 3, n = 6.
Total possibilities = (n-1)C(k-1) 5C2 = 10.
Expected Output : (3-dimensional array)
[
[[1], [2], [3, 4, 5, 6]],
[[1], [2, 3], [4, 5, 6]],
[[1], [2, 3, 4], [5, 6]],
[[1], [2, 3, 4, 5], [6]],
[[1, 2], [3], [4, 5, 6]],
[[1, 2], [3, 4], [5, 6]],
[[1, 2], [3, 4, 5], [6]],
[[1, 2, 3], [4, 5], [6]],
[[1, 2, 3, 4], [5], [6]],
]
Constraints:
Subarrays should have at least 1 element.
SubArrays should only consist of consecutive elements.
For ex: [[1, 3], [2, 4], [5, 6]] This is not valid.
So far, I have tried a recursive method but it yields wrong results. I can't wrap my head around how to correct it. I need an answer explaining how to approach this problem properly and the intuition behind it first and then correct my code and point out where I went wrong.
My code:
public static void main(String[] args) {
int n = 6;
int k = 3;
int[] arr = new int[]{1,2,3,4,5,6};
ArrayList<ArrayList<ArrayList<Integer>>> result = new ArrayList<ArrayList<ArrayList<Integer>>>();
ArrayList<ArrayList<Integer>> eachComb = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> eachSubArray = new ArrayList<Integer>();
int index = 0;
generateCombinations(arr, k, index, eachSubArray, eachComb, result);
for (ArrayList<ArrayList<Integer>> each : result) {
for(ArrayList<Integer> eachh: each) {
System.out.println(eachh);
}
System.out.println("-------------------------------");
}
}
private static void generateCombinations(int[] arr, int k, int index, ArrayList<Integer> eachSubArray,
ArrayList<ArrayList<Integer>> eachComb, ArrayList<ArrayList<ArrayList<Integer>>> result) {
if(k==0 || index==arr.length) {
return;
}
if(!eachSubArray.isEmpty()) {
eachComb.add(new ArrayList<>(eachSubArray));
}
if(k==1) {
ArrayList<Integer> last = new ArrayList<Integer>();
for(int i=index; i<arr.length; i++) {
last.add(arr[i]);
}
if(!last.isEmpty()) {
eachComb.add((last));
result.add(new ArrayList<ArrayList<Integer>>(eachComb));
eachComb.remove(eachComb.size()-1);
}
return;
}
eachSubArray.clear();
for(int i=index; i<arr.length; i++) {
eachSubArray.add((arr[i]));
generateCombinations(arr, k-1, i+1, eachSubArray, eachComb, result);
if(!eachComb.isEmpty()) {
eachComb.remove(eachComb.size()-1);
}
}
}

Index of center of mxn matrix. if center does not exist, return the index of the square closest to the center with the highest integer

Trying to write a method which returns the center of the MxN matrix and if the center does not exist the method should return the index of the square closest to the center with the highest integer value
Eg 1. -
[[5, 7, 8, 6, 3],
[0, 0, 7, 0, 4],
[4, 6, 3, 4, 9],
[3, 1, 0, 5, 8]]
return [1,2] (Center does not exist so closest to the center is [[0,
7, 0],[6, 3, 4]] and 7 is the max value)
Eg 2. -
[[5, 7, 8, 6],
[0, 0, 7, 0],
[4, 6, 3, 4],
[3, 1, 0, 5]]
return [1,2] (Center does not exist so closest to center is [[0,7],[6,3]] and 7 is the max value)
Eg 3. -
[[5, 7, 8],
[0, 0, 7],
[4, 6, 3]]
return [1,1] (Center exists)
private static int[] centerCoordinates(int[][] matrix) {
int row = matrix.length;
int col = matrix[0].length;
if (row % 2 != 0 && col % 2 != 0 && row == col)
return new int[]{row / 2, col / 2};
if (row % 2 == 0 && col % 2 == 0 && row == col) {
//calculate the max of internal square Eg 2.
return new int[]{x, y};
}
//where row!=col
}
I'm assuming you made a mistake in example 1, you gave the right answer, but I think the cells considered should only be [[7],[3]] and not 3 columns wide.
Basically if the dimension is even check length/2-1 and length/2.
If the dimension is odd check only length/2.
Loop through and take max.
private static int[] centerCoordinates(int[][] matrix) {
int row = matrix.length;
int col = matrix[0].length;
int[] ans = new int[]{row/2-(1-(row%2)), col/2-(1-(col%2))};
int best = Integer.MIN_VALUE;
for(int i=row/2-(1-(row%2));i<row/2+1;i++){
for(int j=col/2-(1-(col%2));j<col/2+1;j++){
if(matrix[i][j]>best){
best = matrix[i][j];
ans = new int[]{i,j};
}
}
}
return ans;
}
For this case the center point exists only for those matrices where m == n and both are odd numbers. If this condition is not met, then take central region (m, n):
even - from x / 2 to length - x / 2
odd - from x / 2 - 1 to length - x / 2 + 1
public static void main(String[] args) {
int[][] m1 = {
{5, 7, 8, 6, 3},
{0, 0, 7, 0, 4},
{4, 6, 3, 4, 9},
{3, 1, 0, 5, 8}};
int[][] m2 = {
{5, 7, 8, 6},
{0, 0, 7, 0},
{4, 6, 3, 4},
{3, 1, 0, 5}};
int[][] m3 = {
{5, 7, 8},
{0, 0, 7},
{4, 6, 3}};
int[][] cr1 = centralRegion(m1);
int[][] cr2 = centralRegion(m2);
int[][] cr3 = centralRegion(m3);
Arrays.stream(cr1).map(Arrays::toString).forEach(System.out::println);
// [0, 7, 0]
// [6, 3, 4]
System.out.println(maxValue(cr1)); // 7
Arrays.stream(cr2).map(Arrays::toString).forEach(System.out::println);
// [0, 7]
// [6, 3]
System.out.println(maxValue(cr1)); // 7
Arrays.stream(cr3).map(Arrays::toString).forEach(System.out::println);
// [0]
}
public static int[][] centralRegion(int[][] arr) {
if (arr.length == arr[0].length && arr.length % 2 != 0) {
return new int[][]{{arr[arr.length / 2][arr[0].length / 2]}};
} else {
return Arrays.stream(arr, cp(arr.length), arr.length - cp(arr.length))
.map(row -> Arrays
.stream(row, cp(row.length), row.length - cp(row.length))
.toArray())
.toArray(int[][]::new);
}
}
public static int cp(int length) {
return length / 2 - length % 2 == 0 ? 0 : 1;
}
public static int maxValue(int[][] arr) {
return Arrays.stream(arr).flatMapToInt(Arrays::stream).max().getAsInt();
}

Combination of subarrays

Not sure if this has been asked already but I'm having trouble printing combinations of subarrays.
Given say
int[][] x= {{1,2},{3,4,5},{6,7}};
print all valid combinations by choosing one int from each subarray.
some valid outputs are:
1,3,6
1,3,7
1,4,6
1,4,7
..
... etc
SO far my code looks like
public static void main(String args[]) {
int[][] x= {{1,2},{3,4,5},{6,7}};
for(int i = 0; i < x.length; i++){
for (int j = 0; j < 3; j++){
for (int k = 0; k < 2; k++){
System.out.println(x[0][i]+" " + x[1][j] +" "+ x[2][k]);
}
}
My code is throwing an exeption indexoutofbounds. I'm not sure where I'm going out of bounds. I know its the naive solution and brute force and theres prob a better way to solve it but this solution is the first that came across my mind.
Instead of doing i < x.length, try i < x[0].length The length of x is 3 and that of the first element is 2. Hence, the out of bounds exception. Also, it might be a good idea to get x[1].length and x[2].length instead of hard coding 3 and 2.
Try:
public class MyClass {
public static void main(String args[]) {
int[][] x= {{1,2},{3,4,5},{6,7}};
for (int i = 0; i < x[0].length; i++){
for (int j = 0; j < x[1].length; j++){
for(int k = 0; k < x[2].length; k++){
System.out.println(x[0][i] + " " + x[1][j] + " " + x[2][k]);
}
}
}
}
}
Looking for something complex written in Java 8? Here it is:
package com.test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class ArrayPrint {
#SuppressWarnings("resource")
public static void main(String args[]) {
int[][] x = { { 1, 2 }, { 3, 4, 5 }, { 6, 7 } };
Stream<List<Integer>> inputs = null;
for (int[] set : x) {
List<Integer> list = new ArrayList<Integer>();
Collections.addAll(list, Arrays.stream(set).boxed().toArray(Integer[]::new));
if (inputs == null) {
inputs = Stream.of(list);
} else {
inputs = Stream.concat(inputs, Stream.of(list));
}
}
Stream<List<List<Integer>>> listified = inputs.filter(Objects::nonNull).filter(input -> !input.isEmpty())
.map(l -> l.stream().map(o -> new ArrayList<>(Arrays.asList(o))).collect(Collectors.toList()));
List<List<Integer>> combinations = listified.reduce((input1, input2) -> {
List<List<Integer>> merged = new ArrayList<>();
input1.forEach(permutation1 -> input2.forEach(permutation2 -> {
List<Integer> combination = new ArrayList<>();
combination.addAll(permutation1);
combination.addAll(permutation2);
merged.add(combination);
}));
return merged;
}).orElse(null);
combinations.forEach(System.out::println);
}
}
Output:
[1, 3, 6]
[1, 3, 7]
[1, 4, 6]
[1, 4, 7]
[1, 5, 6]
[1, 5, 7]
[2, 3, 6]
[2, 3, 7]
[2, 4, 6]
[2, 4, 7]
[2, 5, 6]
[2, 5, 7]
With int[][] x = { { 1, 2 }, { 3, 4, 5 }, { 6, 7 }, { 8, 9, 10 } };, Output:
[1, 3, 6, 8]
[1, 3, 6, 9]
[1, 3, 6, 10]
[1, 3, 7, 8]
[1, 3, 7, 9]
[1, 3, 7, 10]
[1, 4, 6, 8]
[1, 4, 6, 9]
[1, 4, 6, 10]
[1, 4, 7, 8]
[1, 4, 7, 9]
[1, 4, 7, 10]
[1, 5, 6, 8]
[1, 5, 6, 9]
[1, 5, 6, 10]
[1, 5, 7, 8]
[1, 5, 7, 9]
[1, 5, 7, 10]
[2, 3, 6, 8]
[2, 3, 6, 9]
[2, 3, 6, 10]
[2, 3, 7, 8]
[2, 3, 7, 9]
[2, 3, 7, 10]
[2, 4, 6, 8]
[2, 4, 6, 9]
[2, 4, 6, 10]
[2, 4, 7, 8]
[2, 4, 7, 9]
[2, 4, 7, 10]
[2, 5, 6, 8]
[2, 5, 6, 9]
[2, 5, 6, 10]
[2, 5, 7, 8]
[2, 5, 7, 9]
[2, 5, 7, 10]
Thus, this code can handle any two dimensional integer array.
Regarding my suggestion from the comments try this code and look at the changes to each for loop. Instead of iterating over predetermined size like for(int k = 0; k < 2; k++) We instead iterate based on the size of the array as follows for(int k = 0; k < x[1].length; k++)
public static void main(String args[]) {
int[][] x = { { 1, 2, 3}, { 3, 4, 5 }, { 6, 7 } };
for (int j = 0; j < x[0].length; j++) {
for (int k = 0; k < x[1].length; k++) {
for (int l = 0; l < x[2].length; l++) {
System.out.println(x[0][j] + " " + x[1][k] + " " + x[2][l]);
}
}
}
}
As long as your outer array only contains three arrays you can do as shown. Otherwise you will need to be a bit more sophisticated with you loops and not hardcode the specific index like for(int k = 0; k < x[0].length; k++) Here we are directly coding index 0.
Hope this helps.
You could always declare an array of objects and cast to the data-type of your choice like this.
public class PrintArray{
public static void main(String[] args){
Object[][] myArray = {{1, 2, 3},
{4, 5, null},
{7, 8, null}};
for(int x = 0; x < myArray.length; x++){
for(int y = 0; y < 3; y++){
if(myArray[x][y] != null){
System.out.print((int)myArray[x][y]);
}
}
System.out.println();
}
}
}
I hope this helps

Permutation between two vectors

I´m studying some techniques of algorithms and got stucked in one problem, I need to do a permutation between two groups. For example:
[1,2,3] e [5,6,7]
Need to generate:
[5,2,3] e [1,6,7]
[5,6,3] e [1,2,7]
........
And so on.
From this what I've done so far is do a permutation in one vector between yourself.
Passing one vector [1,2,3]. Generate the answer:
123
132
213
231
321
312
Based on the code below:
public void permutar(int[] num, int idx) {
for (int i = idx; i < num.length; i++) {
swap(num, i, idx);
permutar(num, idx + 1);
swap(num, i, idx);
}
if (idx == num.length - 1) {
for (int i = 0; i < num.length; i++) {
System.out.print(num[i]);
}
System.out.println("");
}
}
public void swap(int[] num, int a, int b) {
int aux = num[a];
num[a] = num[b];
num[b] = aux;
}
How to do a permutation between this two vectors?
Although you did not precisely describe what you are looking for, and attempt to answer: It seems like you are just looking for all 3-element subsets of the input (1,2,3,5,6,7). Each subset is the first vector of one solution, and the respective remaining elements the other vector.
Here is an example how this may be computed, based on a ChoiceIterable utility class that I wrote a while ago:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
public class CombinationsOfVectors
{
public static void main(String[] args)
{
List<Integer> input = Arrays.asList(1,2,3,5,6,7);
ChoiceIterable<Integer> c = new ChoiceIterable<Integer>(3, input);
for (List<Integer> v0 : c)
{
Set<Integer> s = new LinkedHashSet<Integer>(input);
s.removeAll(v0);
List<Integer> v1 = new ArrayList<Integer>(s);
System.out.println(v0+" and "+v1);
}
}
}
// From https://github.com/javagl/Combinatorics/blob/master/src/
// main/java/de/javagl/utils/math/combinatorics/ChoiceIterable.java
// See the GitHub repo for a commented version
class ChoiceIterable<T> implements Iterable<List<T>>
{
private final List<T> input;
private final int sampleSize;
private final long numElements;
public ChoiceIterable(int sampleSize, List<T> input)
{
this.sampleSize = sampleSize;
this.input = input;
long nf = factorial(input.size());
long kf = factorial(sampleSize);
long nmkf = factorial(input.size() - sampleSize);
long divisor = kf * nmkf;
long result = nf / divisor;
numElements = result;
}
private static long factorial(int n)
{
long f = 1;
for (long i = 2; i <= n; i++)
{
f = f * i;
}
return f;
}
#Override
public Iterator<List<T>> iterator()
{
return new Iterator<List<T>>()
{
private int current = 0;
private final int chosen[] = new int[sampleSize];
{
for (int i = 0; i < sampleSize; i++)
{
chosen[i] = i;
}
}
#Override
public boolean hasNext()
{
return current < numElements;
}
#Override
public List<T> next()
{
if (!hasNext())
{
throw new NoSuchElementException("No more elements");
}
List<T> result = new ArrayList<T>(sampleSize);
for (int i = 0; i < sampleSize; i++)
{
result.add(input.get(chosen[i]));
}
current++;
if (current < numElements)
{
increase(sampleSize - 1, input.size() - 1);
}
return result;
}
private void increase(int n, int max)
{
if (chosen[n] < max)
{
chosen[n]++;
for (int i = n + 1; i < sampleSize; i++)
{
chosen[i] = chosen[i - 1] + 1;
}
}
else
{
increase(n - 1, max - 1);
}
}
#Override
public void remove()
{
throw new UnsupportedOperationException(
"May not remove elements from a choice");
}
};
}
}
The output in this example will be
[1, 2, 3] and [5, 6, 7]
[1, 2, 5] and [3, 6, 7]
[1, 2, 6] and [3, 5, 7]
[1, 2, 7] and [3, 5, 6]
[1, 3, 5] and [2, 6, 7]
[1, 3, 6] and [2, 5, 7]
[1, 3, 7] and [2, 5, 6]
[1, 5, 6] and [2, 3, 7]
[1, 5, 7] and [2, 3, 6]
[1, 6, 7] and [2, 3, 5]
[2, 3, 5] and [1, 6, 7]
[2, 3, 6] and [1, 5, 7]
[2, 3, 7] and [1, 5, 6]
[2, 5, 6] and [1, 3, 7]
[2, 5, 7] and [1, 3, 6]
[2, 6, 7] and [1, 3, 5]
[3, 5, 6] and [1, 2, 7]
[3, 5, 7] and [1, 2, 6]
[3, 6, 7] and [1, 2, 5]
[5, 6, 7] and [1, 2, 3]
If this is not what you have been looking for, you should describe more clearly and precisely what the intended result is.
(E.g. whether or not
[1, 2, 3] and [5, 6, 7]
and
[5, 6, 7] and [1, 2, 3]
count as different results is up to you, but you may filter the results accordingly)
Your task is equal to list all 3-element subsets of your 6-element set. Since the order inside the 3-Element-set does not matter, you should define an order, like 'the smaller number comes first'.
Then the algorithm gets obvious: list = [1 2 3 5 6 7]
EDIT: Set1 should always be the set with number 1 in it, to avoid symmetrical identical solutions.
For all the numbers i from 2 to 5
for all the numbers j from i+1 to 5
Set1 = {list[1], list[i], list[j]}
Set2 = "the other numbers"
This should give right your ordered list from your 9-element comment.
These are nested loops, obviously.
As mentioned in comments to OP question, you have to generate Combination. The usual usecase is to take some subset of elements from a set. In this problem you take subset which represents elements taken from the first set and the rest will be taken from the second.
To implement combination I recommend a for loop counting from 0 to 2^n (where n is number of elements in one array). Then take this number and represent it in binary. Now each 0 or 1 in binary representation says from which set should be given number (and second set will be exact opposite).
I guess you have this as a homework or mental excercise so code is not included :]

Convert String into a two dimensional array

I try to convert this string
s=[[4, 2, 2, 4], [3, 4, 5, 6], [6, 7, 8, 9], [3, 2, 1, 4]]
into a two dimensional array like this
{4, 2, 2, 4},
{3, 4, 5, 6},
{6, 7, 8,9},
{3, 2, 1, 4}
by use this code
int e=s.replaceAll("\\[", "").replaceAll(" ","").replaceAll("],","]").length();
String[] rows1 = s.replaceAll("\\[", "").replaceAll(" ","").replaceAll("],","]").substring(0, e-2).split("]");
String[][] matrix1 = new String[4][4];
int r1 = 0;
for (String row1 : rows1) {
matrix[r1++] = row1.split(",");
}
System.out.println(Arrays.deepToString(matrix1));
But is have problem like this
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at test.main(test.java:94)
Can you help me find a solution?
I think this code will help you. Read the all comments carefully.
String s="[[4, 2, 2, 4], [3, 4, 5, 6], [6, 7, 8, 9], [3, 2, 1, 4]]";
s=s.replace("[","");//replacing all [ to ""
s=s.substring(0,s.length()-2);//ignoring last two ]]
String s1[]=s.split("],");//separating all by "],"
String my_matrics[][] = new String[s1.length][s1.length];//declaring two dimensional matrix for input
for(int i=0;i<s1.length;i++){
s1[i]=s1[i].trim();//ignoring all extra space if the string s1[i] has
String single_int[]=s1[i].split(", ");//separating integers by ", "
for(int j=0;j<single_int.length;j++){
my_matrics[i][j]=single_int[j];//adding single values
}
}
//printing result
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
System.out.print(my_matrics[i][j]+" ");
}
System.out.println("");
}
[[4, 2, 2, 4], [3, 4, 5, 6], [6, 7, 8, 9], [3, 2, 1, 4]]
Logic:
1) replacing all [ to "" now I have-> 4, 2, 2, 4], 3, 4, 5, 6], 6, 7, 8, 9], 3, 2, 1, 4]]
2) Separating all by "]," now I have->
A) 4, 2, 2, 4
B) 3, 4, 5, 6
c) 6, 7, 8, 9
d) 3, 2, 1, 4
3) Separating A B C D by ", " now I have->
A) a) 4 b) 2 c) 2 d) 4
B) a) 3 b) 4 c) 5 d) 6
c) a) 6 b) 7 c) 8 d) 9
d) a) 3 b) 2 c) 1 d) 4
Solution using Java streams:
String[][] arr = Arrays.stream(str.substring(2, str.length() - 2).split("\\],\\["))
.map(e -> Arrays.stream(e.split("\\s*,\\s*"))
.toArray(String[]::new)).toArray(String[][]::new);
Try this...
String s="[[4, 2, 2, 4], [3, 4, 5, 6], [6, 7, 8, 9], [3, 2, 1, 4]]";
// Split on this delimiter
String[] rows = s.split("], \\[");
for (int i = 0; i < rows.length; i++) {
// Remove any beginning and ending braces and any white spaces
rows[i] = rows[i].replace("[[", "").replace("]]", "").replaceAll(" ", "");
}
// Get the number of columns in a row
int numberOfColumns = rows[0].split(",").length;
// Setup your matrix
String[][] matrix = new String[rows.length][numberOfColumns];
// Populate your matrix
for (int i = 0; i < rows.length; i++) {
matrix[i] = rows[i].split(",");
}
// Display your matrix
System.out.println(Arrays.deepToString(matrix));
Results:
This just doesn't add the comma's at the end of the line:
String s = "[[4, 2, 2, 4], [3, 4, 5, 6], [6, 7, 8, 9], [3, 2, 1, 4]]";
for (String l: s.split("\\]\\s*,\\s*\\[")) {
l = l.replaceAll("\\[", "").replaceAll("\\]", "");
System.out.println("{" + l + "}");
}
Assuming that the input string will always be in that format, with 4 integers between each bracket, I think the best way to do it would simply be to use a Scanner object and it's nextInt() method which will ignore the brackets and comma's and just find the numbers. Then put them into a 2d array like how you would with a loop.
It kinda gets rid of all the fun you were having with removing the brackets though, so it's not really better in terms of making an exercise out of this.

Categories