I need to flip an image over an imaginary diagonal going from the top right to bottom left of an image. This is what I have so far. getBasicPixel(x,y) returns the rgb of the pixel as an int value.
public static void flipD(Picture p){
int h= p.getHeight();
int w= p.getWidth();
int v=0;
for(int i=0; i< h; i++){
for(int j=0; j<w; j++){
v=p.getBasicPixel(i,j);
p.setBasicPixel(w-1-i, w-1-j, v);
}
}
}
This should just be a matter of trading x and y. So, if one were doing this operation on an array it would look like this.
int portrait[][] = { {1,2}, {2,4}, {3,6} };
int landscape[][] = new int[2][3];
for (int row=0; row < portrait.size; row++) {
for (int col=0; col < portrait[0].size; col++) {
landscape[col][row]=portrait[row][col];
}
}
Related
I'm trying a simple intuition to transpose a matrix in place.
I'm trying to swap elements of matrix[i][j] and matrix[j][i] but it is not working, I'm wondering what is happening behind the scene.
class Solution {
public int[][] transpose(int[][] matrix) {
for(int i = 0; i < matrix.length; i++){
for(int j = 0; j < matrix[0].length; j++){
int temp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = temp;
}
}
return matrix;
}
}
Output
For matrix -> [[1,2,3],[4,5,6],[7,8,9]]
It is giving output -> [[1,2,3],[4,5,6],[7,8,9]]
but the expected output should be -> [[1,4,7],[2,5,8],[3,6,9]]
You are transposing each pair of elements twice, which puts them back how they were.
One solution would be to change for(int j = 0; in the inner loop to for(int j = i + 1;. This would make sure that each pair of elements is only transposed once.
Also be aware that this general solution only works for square matrices.
how about this way?
public int[][] transpose(int[][] matrix) {
int[][] result = new int[matrix.length][matrix[0].length];
for(int i = 0; i < matrix[0].length; i++){
for(int j = 0; j < matrix.length; j++){
result[j][i] = matrix[i][j];
System.out.println(Arrays.deepToString(result));
}
}
return result;
}
public static int[][] shift(final int[][] original, final int amount) {
int[][] shifted = new int[original.length][original[0].length];
for (int col = 0; col < original.length; col++) {
for (int row = 0; row < original[col].length; row++) {
shifted[col][row] = FILL_VALUE;
}
for (int cols = 0; cols < original.length + amount; cols++) {
for (int rows = 0; rows < original[cols].length; rows++) {
if (cols - amount < original.length) {
shifted[cols][rows] = original[cols - amount][rows];
}
}
}
}
return shifted;
}
Hi,
I am trying to write a method that will shift the elements in my 2-D array to the left by some arbitrary amount. I don't want to loop the values back around, but instead fill the empty arrays with some fill_value which is already predefined. And if the shift amount is more than the orignial length, I would just return an image with only fill_value. However, this function is throwing an arrayindexoutofbound Error. But I can't think of how I should change my for loop to fix the error. Any help is appreciated! Thank you!
I believe it's because in your second outer for loop, the condition is cols < length + amount, so it will continue past the edge of the array if amount > 0. You could step through your code with a debugger and see exactly where it's going out of bounds.
The error is occurring because of following line:
shifted[cols][rows] = original[cols - amount][rows];
When cols=0, rows=0, amount=2 (say), it is trying to access original[-2][0] which does not exist.
Instead you may use following:
public class overflow1 {
static int a[][] = {{1,2,3,4,5,6},{2,3,4,5,6,7},{3,4,5,6,7,8}, {4,5,6,7,8,9}, {5,6,7,8,9,10}, {6,7,8,9,10,11}};
static int b[][] ;
static int FILL_VALUE =0;
public static int[][] shift(final int[][] original, final int amount) {
int[][] shifted = new int[original.length][original[0].length];
for (int col = 0; col < original.length; col++) {
for (int row = 0; row < original[col].length; row++) {
shifted[col][row] = FILL_VALUE;
}
for (int cols = 0; cols < original.length ; cols++) {
for (int rows = 0; rows < original[cols].length; rows++) {
if (cols - amount >=0) {
shifted[cols][rows] = original[cols - amount][rows];
}
}
}
}
return shifted;
}
public static void main(String[] arggs) {
b=shift(a,2);
System.out.println("Original array:");
for(int i=0; i<a.length; i++){
for (int j=0; j<a[i].length; j++){
System.out.print(a[i][j]+ ":");
}
System.out.println();
}
System.out.println("After shift by 2 array:");
for(int i=0; i<b.length; i++){
for (int j=0; j<b[i].length; j++){
System.out.print(b[i][j]+ ":");
}
System.out.println();
}
}
}
Here is the output for the sample:
Original array:
1:2:3:4:5:6:
2:3:4:5:6:7:
3:4:5:6:7:8:
4:5:6:7:8:9:
5:6:7:8:9:10:
6:7:8:9:10:11:
After shift by 2, array:
0:0:0:0:0:0:
0:0:0:0:0:0:
1:2:3:4:5:6:
2:3:4:5:6:7:
3:4:5:6:7:8:
4:5:6:7:8:9:
I am trying to work through an assignment that is asking me to create a method in Java that, when given a desired height and width, create a row- or column- major matrix.
Here is what I have so far:
public static int[][] increasingMatrix(int width, int height, boolean format){
if (format) { // generate row-major matrix
int[][] array = new int[height][];
int count = 0;
for (int i = 0; i < height; i++) {
array[i] = new int[width];
for (int j = 0; j < width; j++) {
array[i][j] = count;
count++;
}
}
return array;
} else {
int[][] array = new int[width][];
int count = 0;
for (int i = 0; i < width; i++) {
array[i] = new int [height];
for (int j = 0; j < height; j++) {
array[j][i] = count;
count ++;
}
}
return array;
}
}
However, when I go and try to run tests on the generated array, the column-major matrix (from what I can tell) is being generated incorrectly. The row-major matrix seems to generate correctly.
Can you see anything that I am doing wrong? I have stared at this for hours but cant seem to get any breakthroughs.
Thanks!
Your code is wrong. The first index in the matrix is always the width.
Remember: a matrix is an array of arrays. The first index is the width of the matrix, the second is the height.
Try this:
if(format) {
return buildRowMajorMatrix(width, height);
} else {
return buildColumnMajorMatrix(width, height);
}
Where buildRowMajorMatrix looks like:
private int[][] buildRowMajorMatrix(int width, int height) {
int[][] matrix = new int[width][height];
int cellValue = 0;
for(int columnIndex = 0 ; columnIndex < width ; columnIndex++) {
for(int rowIndex = 0 ; rowIndex < height ; rowIndex++, cellValue++) {
matrix[columnIndex][rowIndex] = cellValue;
}
}
return matrix;
}
And buildColumnMajorMatrix looks like:
private int[][] buildColumnMajorMatrix(int width, int height) {
int[][] matrix = new int[width][height];
int cellValue = 0;
for(int rowIndex = 0 ; rowIndex < height ; rowIndex++) {
for(int columnIndex = 0 ; columnIndex < width ; columnIndex++, cellValue++) {
matrix[columnIndex][rowIndex] = cellValue;
}
}
return matrix;
}
In else condition:
else {
int[][] array = new int[width][];
int count = 0;
for (int i = 0; i < width; i++) {
array[i] = new int [height];
for (int j = 0; j < height; j++) {
array[j][i] = count;
count ++;
}
}
return array;
}
You are trying trying to iterate through arrays (rows of matrix, j-index) that are not yet initialized. To implement column-major matrix you need to first initialize all rows (or switch to more complex algorithm).
Also I think width and height of matrix in both formats should be same. Row- and column-majority only says whether we fill matrix iterating by columns or rows, but I guess wording of the task leaves room for interpretation.
My solution:
public static int[][] increasingMatrix(int width, int height, boolean format){
int[][] array = new int[height][width]; // Java's shortcut generating regular array of arrays for you
int count = 0;
if (format) { // generate row-major matrix
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
array[i][j] = count;
count++;
}
}
} else {
for (int j = 0; j < width; j++)) {
for (int i = 0; i < height; i++ {
array[i][j] = count;
count++;
}
}
}
return array;
}
I'm solving the rotate an NxN matrix in place question.
It seems that my code makes a rotation, but leaves an X over the image.
So I'm guessing it's rotating the edges incorrectly.
I'm attaching two images as sample input and output.
What's wrong with my code:
public static void rotateRight(float[][] img){
for (int i=0; i<N/2; i++){
for (int j=i; j<N-i; j++){
int J_COMP = N-j-1; //complement of J
int LEFT = i;
int RIGHT = N-i-1;
int TOP = i;
int BOTTOM = N-i-1;
float temp = img[J_COMP][LEFT];
img[J_COMP][LEFT] = img[BOTTOM][J_COMP];
img[BOTTOM][J_COMP] = img[j][RIGHT];
img[j][RIGHT] = img[TOP][j];
img[TOP][j] = temp;
}
}
}
You are rotating main diagonals twice.
Fix inner loop (see "fix" comment)
package tests.StackOverflow;
public class Question_20773692 {
private static int N;
public static void main(String[] args) {
float[][] img;
int count;
N=3;
count = 0;
img = new float[N][N];
for(int i=0; i<N; ++i) {
for(int j=0; j<N; ++j) {
img[i][j] = count++;
}
}
printImg(img);
rotateRight(img);
printImg(img);
}
public static void printImg(float[][] img) {
for(int j=0; j<N; ++j) {
System.out.print("-");
}
System.out.println();
for(int i=0; i<N; ++i) {
for(int j=0; j<N; ++j) {
System.out.print((int)(img[i][j]));
}
System.out.println();
}
for(int j=0; j<N; ++j) {
System.out.print("-");
}
System.out.println(); }
public static void rotateRight(float[][] img){
for (int i=0; i<N/2; i++){
for (int j=i; j<N-i; j++){
//for (int j=i+1; j<N-i; j++){ //fix
int J_COMP = N-j-1; //complement of J
int LEFT = i;
int RIGHT = N-i-1;
int TOP = i;
int BOTTOM = N-i-1;
float temp = img[J_COMP][LEFT];
img[J_COMP][LEFT] = img[BOTTOM][J_COMP];
img[BOTTOM][J_COMP] = img[j][RIGHT];
img[j][RIGHT] = img[TOP][j];
img[TOP][j] = temp;
}
}
}
}
In-place rotation of matrix.... I guess this should work.
public void rotate(ArrayList<ArrayList<Integer>> a) {
int n=a.size()/2;
for(int i=1;i<=n;i++){
ArrayList<Integer>temp=a.get(i-1);
a.set(i-1,a.get(a.size()-i));
a.set(a.size()-i,temp);
}
for(int i=0;i<a.size();i++){
for(int j=i+1;j<a.get(0).size();j++){
a.get(i).set(j,a.get(i).get(j)^a.get(j).get(i));
a.get(j).set(i,a.get(i).get(j)^a.get(j).get(i));
a.get(i).set(j,a.get(i).get(j)^a.get(j).get(i));
}
}
}
If you are about rotating picture, I would recommend to use java.awt.geom.AffineTransform
If this is logical-only question about matrix rotation, I believe you can correct your result by replacing (one or both?) < to <=. Also, note that your picture has size 309x309 (odd numbers!), and you left the middle not corrected by N/2. Possible solution is add 1 - replace N/2 to
N % 2 == 0 ? N / 2 : N / 2 + 1
I looked at the algorithm here for clockwise rotation, but I can't do it the other way around. So basically, for clockwise rotation, you need to multiply the transpose to a rotation matrix, but how do you do the same thing the other way around?
Here's my code:
public class rotation2 {
public static int [][] multiplyMatrix(int [][] m1) {
int [][] m2 = {{0,0,0,1},
{0,0,1,0},
{0,1,0,0},
{1,0,0,0}};
int[][] result = new int[4][4];
// multiply
for (int i=0; i<4; i++)
for (int j=0; j<4; j++)
for (int k=0; k<4; k++)
result[i][j] += m1[i][k] * m2[k][j];
return result;
}
public static int [][] multiplyMatrix2(int [][] m2) {
int [][] m1 = {{0,0,0,1},
{0,0,1,0},
{0,-1,0,0},
{-1,0,0,0}};
int[][] result = new int[4][4];
// multiply
for (int i=0; i<4; i++)
for (int j=0; j<4; j++)
for (int k=0; k<4; k++)
result[i][j] += m1[i][k] * m2[k][j];
return result;
}
public static void printArray(int [][] array) {
for(int row = 0; row < array.length; row++) {
for(int col = 0; col < array[row].length; col++) {
if (array[row][col] > 0) {
System.out.printf("1");
} else {
System.out.printf("0");
}
}
System.out.printf("\n");
}
}
public static int [][] transpose(int [][] m1) {
int m = 4;
int n = 4;
int c = 0;
int d = 0;
int[][] transpose = new int [n][m];
for ( c = 0 ; c < m ; c++ ) {
for ( d = 0 ; d < n ; d++ ) {
transpose[d][c] = m1[c][d];
}
}
return transpose;
}
public static void main(String[] args) {
int [][] m1 = {{1,0,0,0},
{1,0,0,0},
{1,1,0,0},
{0,0,0,0}};
int [][] transpose = transpose(m1);
printArray(transpose);
transpose = multiplyMatrix(transpose);
printArray(transpose);
int [][] transpose2 = transpose(m1);
printArray(transpose2);
transpose2 = multiplyMatrix(transpose2);
printArray(transpose2);
}
}
You don't transpose for counter clock rotation, right?
What you have to do is to (1) transpose the matrix, and (2) inverse the rows (clockwise) or columns (counter-clockwise), respectively.
You can just use a double-for-loop to set the new values for the individual cells, doing both steps at the same time. In code, this might look like this:
public static int[][] rotate(int[][] m, boolean left) {
int rows = m.length, cols = m[0].length;
int[][] m2 = new int[cols][rows]; // swap rows and cols
for (int r = 0; r < rows; r++)
for (int c = 0; c < cols; c++)
if (left) // rotate left
m2[c][r] = m[r][cols - c - 1];
else // rotate right
m2[c][r] = m[rows - r - 1][c];
return m2;
}
For more information and alternative approaches, take a look at the answers to this related question.