I've seen several questions here that don't quite answer my question. I'm trying to do a rendition of the classic matrix rotation question used so often in interview questions. Instead of focusing on the square matrix, I'm interested in M x N matrices.
For input matrix
1 2 3
4 5 6
7 8 9
1 2 3
I'd like to transform the matrix into
3 2 1
9 8 7
6 5 4
3 2 1
Here is the code I've written:
#include <iostream>
#include <vector>
#include <algorithm>
void do_swaps(int& a, int& b, int& c, int& d) {
std::swap(a, b);
std::swap(c, d);
}
void rotate(std::vector<std::vector<int>>& v) {
size_t m = v.size();
size_t n = v[0].size();
for(size_t i = 0; i < m/2; ++i) {
for(size_t j = 0; j <= n/2; ++j) {
do_swaps(v[i][j], v[m-i-1][n-j-1], v[m-j-1][i], v[j][n-i-1]);
}
}
}
void print(const std::vector<std::vector<int>>& v) {
size_t m = v.size();
size_t n = v[0].size();
for(size_t i = 0; i < m; ++i) {
for(size_t j = 0; j < n; ++j) {
std::cout << v[i][j] << ' ';
}
std::cout << '\n';
}
}
int main() {
std::vector<std::vector<int>> m{{1,2,3}, {4,5,6}, {7,8,9}, {1, 2, 3}};
std::cout << "Before: \n";
print(m);
rotate(m);
std::cout << "\nAfter: \n";
print(m);
}
And here's my output:
Before:
1 2 3
4 5 6
7 8 9
1 2 3
After:
3 2 1
9 5 7
6 8 4
3 2 1
My code works for 3 x 3 matrices (haven't tested higher dimensional matrices), but I seem to have an off by one error in my code causing the inner-most elements to remain unswapped.
In the line for(size_t j = 0; j <= n/2; ++j) {, I've tried adjusting the stop condition to several things including j < (n+1)/2; and j < (n-1)/2;, but it remains the same.
Can someone explain where I've gone wrong in my algorithm?
You don't take care of middle line in case when lines number is odd.
Further, you swap elements that lie on the middle column (when columns number is odd) twice. You can check if m is odd with a bitwise-and with 1.
The following is an easier way to project swapped values is presented above and you don't even have to care about the middle column in this case.
void rotate(std::vector<std::vector<int>>& v) {
size_t m = v.size();
size_t n = v[0].size();
for (size_t i = 0; i < m / 2; ++i)
{
for (size_t j = 0; j < n; ++j)
std::swap(v[i][j], v[m - i - 1][n - j - 1]);
}
if (m&1)
for (size_t i = 0; i< n/2; ++i)
std::swap(v[m/2][i], v[m/2][n-i-1]);
}
I would use mirror x and then mirror y or vice versa. It is in-place and safe for any resolution (even/odd). So first swap all rows and then all columns (or vice versa). Here some code for this.
void rotate(std::vector<std::vector<int>>& v) {
size_t m= v.size();
size_t n=v[0].size();
for(size_t i=0;i<m;i++) {
for(size_t j=0,k=n-1;j<k;j++,k--) {
std::swap(v[i][j],v[i][k]);
}
}
for(size_t j=0;j<n;j++) {
for(size_t i=0, k=m-1; i<k; i++, k--) {
std::swap(v[i][j],v[k][j]);
}
}
}
A pythonish way (not in place):
d = (1, 2, 3), (4, 5, 6), (7, 8, 9), (1, 2, 3)
[r[::-1] for r in d[::-1]]
Related
We have given an array of n size and we to have to rotate it by k times where k can be greater than n in some cases .
My try -
#include<iostream>
using namespace std;
void inputarray(int arr[],int size){
for(int i=0;i<size;i++){
cin>>arr[i];
}
}
int main(){
int n;
cin>>n;
int arr[100];
inputarray(arr,n);
int ansarr[n];
int k;
cin>>k;
k = k%n;
int j=0;
for(int i =n-k;i<n;i++){
ansarr[j++] = arr[i];
}
for(int i=0;i<=k;i++){
ansarr[j++]=arr[i];
}
for(int i=0;i<n;i++){
cout<<ansarr[i];
}
}
My output is coming correct for k>2 like my output for k=3 is -
6
1 2 3 4 5 6
3
456123
Which is correct but for k <2 like k = 2 , 1 and 0 my output is not coming correct . Like for K=2 my output is -
6
1 2 3 4 5 6
2
561234199699
So where am I doing wrong can anyone please tell .
You can perform the rotation with a single loop, and this is completely bulletproof, using
for (int i= 0; i < n; i++)
{
ans[i]= arr[(i + k) % n];
}
Now you can eliminate the modulo inside the loop by noting that i + k remains in [0, n) for i in [- k, n - k), thus in [0, n - k), and i + k - n remains in [0, n) for i in [n - k, 2n - k), thus in [n - k, n). So you can rewrite with two successive loops
k= k % n;
int i;
for (i= 0; i < n - k; i++)
{
ans[i]= arr[i + k];
}
for ( ; i < n ; i++)
{
ans[i]= arr[i + k - n];
}
Caution: due to the behavior of the operator %, the above code will fail for k < 0.
For starters pay attention to that variable length arrays like this
int ansarr[n];
are not a standard C++ feature. You should declare the array similarly to the array arr
int ansarr[100];
Or instead of arrays you could use standard container std::vector.
In any case your code is wrong at least because this for loop
for(int i =n-k;i<n;i++){
ansarr[j++] = arr[i];
}
should start from i equal to k instead of i = n - k
for(int i = k;i<n;i++){
ansarr[j++] = arr[i];
}
and correspondingly the second for loop should look like
for(int i=0;i < k;i++){
ansarr[j++]=arr[i];
}
That is the condition of the loop should look like i < k.
Your program works for k equal to 3 because the expression n - k when n is equal to 6 yields the same value 3.
Bear in mind that there is standard algorithm std::reverse_copy declared in the header <algorithm> that you could use.
Here is a demonstration program
#include <iostream>
#include <algorithm>
int main()
{
const size_t N = 6;
for (size_t k = 0; k < N; k++)
{
int a[N] = { 1, 2, 3, 4, 5, 6 };
int b[N];
std::rotate_copy( a, a + k, a + N, b );
std::cout << k << ":";
for (size_t i = 0; i < N; i++)
{
std::cout << ' ' << b[i];
}
std::cout << '\n';
}
}
The program output is
0: 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
As for your approach with for loop then it is enough to use only one for loop. For example
#include <iostream>
int main()
{
const size_t N = 6;
for (size_t k = 0; k < N; k++)
{
int a[N] = { 1, 2, 3, 4, 5, 6 };
int b[N];
for (size_t j = 0, i = k; j < N; i = ( i + 1 ) % N)
{
b[j++] = a[i];
}
std::cout << k << ":";
for (size_t i = 0; i < N; i++)
{
std::cout << ' ' << b[i];
}
std::cout << '\n';
}
}
The program output is the same as shown above
0: 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
I'm not sure how either the question description or the current answers are "rotate it by k times," where "it" is the give array. They all seem to create a new array.
To rotate an array by k, first take k modulo the array length, then perform three steps (for example, {1, 2, 3, 4, 5}, k = 3):
Reverse the part up to index k:
{3, 2, 1, 4, 5}
Reverse the part from index k to the end:
{3, 2, 1, 5, 4}
Reverse the whole array:
{4, 5, 1, 2, 3}
I am trying to swap minimum row value with reverse diagonal. I managed to print out every row minimum value, but my swap fails. Maybe you could give me some hints.
for (int i = 0; i < n; i++)
{
int min = mas[i][0];
for (int j = 1; j < m; j++)
{
if (mas[i][j] < min)
{
min = mas[i][j];
}
for(int k=n-1;k>0;k--){
for(int h = m-1; h>0;h--){
min = mas[i][j];
mas[i][j]=mas[k][h];
mas[k][h]=min;
}
cout << "New Matrix\n";
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
cout << mas[i][j] << " ";
}
}
}
}
system("pause");
return EXIT_SUCCESS;
}
This is my for for a minimum value and later I am adding another for to swap values.
My result:
I go printed out 3 matrices and none of them are correctly swapping value. I guess it's because of for in for cycle?
My file with with 2d array:
1 2 5 // row min 1, reverse diagonal 5
2 8 9 // row min 2, reverse diagonal 8
5 9 10 // row min 5, revese diagonal 5
What output I expect:
5 2 1 // 5 diagonal swap with min = 1
8 2 9 // 8 diagonal swap with min = 2
5 9 10 // 5 diagonal no swap because 5 is row minimum
If I understand correctly then the "reverse diagonal" can be present only in a square matrix. So there is no sense to enter two values n and m to deal with a square matrix.
If to consider the example of a 3 x 3 matrix shown in your question and to use loops instead of for example standard functions std::max_element and std::swap then the code that converts the matrix can look the following way as it is shown in the demonstrative program
#include <iostream>
#include <iomanip>
int main()
{
const size_t N = 3;
int a[N][N] =
{
{ 1, 2, 5 },
{ 2, 8, 9 },
{ 5, 9, 10 }
};
for (size_t i = 0; i < N; i++)
{
for (size_t j = 0; j < N; j++)
{
std::cout << std::setw(2) << a[i][j] << ' ';
}
std::cout << '\n';
}
std::cout << std::endl;
for (size_t i = 0; i < N; i++)
{
size_t min = 0;
for (size_t j = 1; j < N; j++)
{
if (a[i][j] < a[i][min]) min = j;
}
if ( min != N - i - 1 )
{
int tmp = a[i][min];
a[i][min] = a[i][N - i - 1];
a[i][N - i - 1] = tmp;
}
}
for (size_t i = 0; i < N; i++)
{
for (size_t j = 0; j < N; j++)
{
std::cout << std::setw(2) << a[i][j] << ' ';
}
std::cout << '\n';
}
std::cout << std::endl;
}
The program output is
1 2 5
2 8 9
5 9 10
5 2 1
8 2 9
5 9 10
This has been annoying me for most of the day..
Suppose that I have the following vector:
v = [1, 2, 4, 9]
I transpose this, so the vector is in columns:
v = [1, 2
4, 9]
I do this, using the following method:
for(unsigned i=0; (i < cols); i++)
{
for(unsigned j=0; (j < 2); j++)
{
std::cout << vect[i*2+j] << " ";
}
std::cout << std::endl;
}
But how would I calculate the columns, first? My aim is to achieve the following:
(1 + 4)/2 = 2.5
(2 + 9)/2 = 5.5
Therefore, a resulting vector would return the mean matrix: x = [2.5, 5.5]
I have tried the following:
double summation = 0;
for(unsigned i=0; (i < cols); i++)
{
for(unsigned j=0; (j < size); j++)
{
summation += values[i*(i*j)+j];
}
std::cout << summation << std::endl;
}
Which produces:
3
8
I am probably missing something really stupid here, but, I can't seem to figure out what.
I have also tried to have a variable subRow which begins at 0 and increments each time by 3 but this did not work either.
Your last sentence has the right idea, but not quite the right number. Where you mention 3, it appears you need 2. That's normally called the "stride". Using it, averaging by columns would come out something like this:
for (int i=0; i<stride; i++) {
double total = 0;
for (int j=0; j<input.size(); j+=stride)
total += input[j];
result[i] = total / (j.size()/stride);
}
At least for the moment, this takes for granted that the size of the input matrix really is "correct" --i.e., an even multiple of the stride you specify.
You may find it easier to debug if keep your index calculations simple:
std::vector<int> v{1, 2, 4, 9};
const unsigned int WIDTH = 2;
for (unsigned int i = 0; i < WIDTH; ++i)
{
double sum = 0.0;
for (unsigned int j = i; j < v.size(); j += WIDTH)
{
sum += v[j];
}
// do something with sum
}
Your problem appears to be here: for(unsigned j=0; (j < size); j++)
You are starting j at 0 and increment by 1 to size() each time. Most of the values you hit will not be valid for what you are trying to do.
int v[] = {1,2,4,9};
int cols = 2;
int rows = 2;
for(int c=0 ; c < cols ; c++) {
double sum=0;
for(int r=0 ; r < rows ; r++)
sum += v[cols*r+c];
std::cout << sum /rows << std::endl;
}
And I'm doing pretty good in fact I found the intersection and think I have the right code. Only problem is that it doesn't seem to print out the last value.
So if I have two sets:
9 12 7 8 1 19 11 2 14
15 10 8 2 5 16 14 7 19 0 11 3 13 18 9 17 1 12
My code will produce the following output:
1
2
7
8
9
11
12
14
But the right intersection of the sets should be:
1
2
7
8
9
11
12
14
19
So, my code doesn't print out the last value and I can't find out why.
void findIntersection(vector<int> A, vector<int> B)
{
vector<int> intersection;
int n1 = A.size();
int n2 = B.size();
int i = 0, j =0;
while(i <= n1 && j <= n2)
{
if(A[i] > B[j])
{
j++;
}
else if( B[j] > A[i])
{
i++;
}
else
{
intersection.push_back(A[i]);
i++;
j++;
}
}
for(unsigned int i = 0; i <= intersection.size(); i++)
{
cout << intersection[i] << endl;
}
}
void slowintersect(vector<vector<int> > v)
{
vector<int> vec;
vector<int> c;
int store_0;
int row = 0;
for(size_t j =0; j < v.at(row).size(); j++)
{
store_0 = v[row][j];
c.push_back(store_0);
}
for(size_t i = 0; i < v.size(); i++)
{
for(size_t k = 0; k < v.at(i).size(); k++)
{
vec.push_back(k);
}
}
findIntersection(c, vec);
}
#include <algorithm>
#include <set>
set<int> intersect;
set_intersection(s1.begin(),s1.end(),s2.begin(),s2.end(), // sorted!
std::inserter(intersect,intersect.begin()));
example
if you don't want std::algorithm, there are several errors in your code. i.e:
for(unsigned int i = 0; i <= intersection.size(); i++)
^
should be <
here is an important error:
int i = 0, j =0;
while(i <= n1 && j <= n2)
{ ^ ^
< <
if(A[i] > B[j])
{
j++;
you will skip all n-1 A elements if A[0] is greater than each B element, and end the loop
I'm assuming you do not want to use the C++ standard algorithm.
Couple of things.
1. Your algorithm shall work only if both vectors are initially sorted. Are they?
2. You shouldn't access vector[vector.size()] element as it is out of bounds.
My second point means:
while(i <= n1 && j <= n2)
Change this to
while(i < n1 && j < n2)
And change the following
for(unsigned int i = 0; i <= intersection.size(); i++)
to
for(unsigned int i = 0; i < intersection.size(); i++)
Also, MOST IMPORTANT ERROR!!!!
for(size_t k = 0; k < v.at(i).size(); k++)
{
vec.push_back(k);
}
Change it to:
for(size_t k = 0; k < v[i].size(); k++)
{
vec.push_back(v[i][k]);
}
Your while co dition is broken. You must continue until both indexes are at the end. Currently you stop when one of the indexes has reached the end.
When you fix that, you also must ensure that you don't increase i beyond n1; same for j and n2.
While you are developing you should rather use vector.at(i) instead of vector[i] to enable safety checks.
i'm trying to figure out how to fill a multidimentional array in this way:
Input: rows = 3 , cols = 3 :
1 4 7
2 5 8
3 6 9
can somebody give me an idea?
P.S My task is to find how many nubers stay in the same position in both arrangements. Ex:
1 4 7 1 2 3
2 5 8 4 5 6
3 6 9 7 8 9
so the numbers that are in the same position are : 1 5 9.
i've tryied :
//n = 3 , m = 3
for(int i = 0; i <n; i++) {
for(int j = 0; j <m; j++){
if(array[i][j] == array2[i][j]) {
lol++;
}
}
}
cout<<lol;
/*
1 2 3
4 5 6
7 8 9
1 4 7
2 5 8
3 8 9
*/
it must show me 3 , but it shows 0, where is the problem?
Populate at initialization:
int a[3][3] = { { 1, 4, 7},
{ 2, 5, 8},
{ 3, 6, 9}
};
EDIT (unsure if resolved):
After update to question here is an example application that (with modification to accept input from user) will diff two arrays and construct an array indicating the elements that were the same and a count of the number of identical elements:
#include <iostream>
int** make_array(const size_t a_rows, const size_t a_columns)
{
int** result = new int*[a_rows];
for (size_t i = 0; i < a_rows; i++)
{
*(result + i) = new int[a_columns];
}
return result;
}
void print_array(int** a_array, const size_t a_rows, const size_t a_columns)
{
for (size_t r = 0; r < a_rows; r++)
{
for (size_t c = 0; c < a_columns; c++)
{
std::cout << *(*(a_array + r) + c) << " ";
}
std::cout << "\n";
}
std::cout << "\n";
}
int main()
{
// Example data.
int a[3][3] = { { 1, 4, 7},
{ 2, 5, 8},
{ 3, 6, 9}
};
int b[3][3] = { { 1, 2, 3},
{ 4, 5, 6},
{ 7, 8, 9}
};
size_t rows = 3;
size_t columns = 3;
// Create three arrays:
// - two input arrays
// - array that represents which elements are the same
int** in_1 = make_array(rows, columns);
int** in_2 = make_array(rows, columns);
int** diff = make_array(rows, columns);
// Populate with example data.
for (size_t r = 0; r < rows; r++)
{
for (size_t c = 0; c < columns; c++)
{
*(*(in_1 + r) + c) = a[r][c];
*(*(in_2 + r) + c) = b[r][c];
}
}
// Diff.
// The 'diff' array will hold '1' for elements that
// were the same and '0' for elements that were not.
size_t same_count = 0;
for (size_t r = 0; r < rows; r++)
{
for (size_t c = 0; c < columns; c++)
{
*(*(diff + r) + c) = *(*(in_1 + r) + c) == *(*(in_2 + r) + c);
same_count += *(*(diff + r) + c);
}
}
std::cout << "\n";
// Results.
print_array(in_1, rows, columns);
print_array(in_2, rows, columns);
print_array(diff, rows, columns);
std::cout << "Same element count: " << same_count << "\n";
// Free...
return 0;
}
Output:
$ ./cpp/main.exe
1 4 7
2 5 8
3 6 9
1 2 3
4 5 6
7 8 9
1 0 0
0 1 0
0 0 1
Same element count: 3
Create a dynamically allocated array if you only know the dimensions at runtime:
int** x = new int*[rows];
for ( int i = 0 ; i < rows ; i++ )
x[i] = new int[cols];
And then populate it:
for ( int i = 0 ; i < rows ; i++ )
for ( int j = 0 ; i < cols ; j++ )
x[i][j] = y;
Or better yet, use a vector of vectors, this will give you more flexibility:
std::vector<std::vector<int> > x;
A simple solution would be this:-
int k = 1;
for(int i = 0; i < row; i++){
for(int j = 0; j < col; j++){
a[j][i] = k; // filling it in the column first order
++k;
}
}