Does anyone know an efficient way to right circular-shift a matrix? Btw, the matrix is binary but a method to solve a non-binary matrix is also fine.
Right now, I'm thinking of implementing a circular array for the rows of my matrix and updating each row whenever a shift operation is required.
Another method, I was considering was implementing a vector of pointers to columns (of the matrix) represented by vectors and swapping them around when a shift operation occurs.
E.g.
1 2 3
4 5 6
7 8 9
Right-shift
3 1 2
6 4 5
9 7 8
Another problem arises with all these solutions if I need to shift the matrix down as well. To implement both operations efficiently, is completely beyond me.
Down-shift
9 7 8
3 1 2
6 4 5
Something like this perhaps,
class matrix {
std::vector<bool> elements;
int rows, cols, row_ofs, col_ofs;
std::size_t index(int r, int c) {
r = (r + row_ofs) % rows;
c = (c + col_ofs) % cols;
return std::size_t(r)*cols + c; // row major layout
}
public:
matrix() : rows(0), cols(0) {}
matrix(int r, int c)
: elements(std::size_t(r)*c), rows(r), cols(c) {}
int num_rows() const { return rows; }
int num_cols() const { return cols; }
std::vector<bool>::reference operator()(int r, int c) {
return elements.at(index(r,c));
}
bool operator()(int r, int c) const {
return elements.at(index(r,c));
}
void rotate_left() { col_ofs = (col_ofs+1 ) % cols; }
void rotate_right() { col_ofs = (col_ofs+cols-1) % cols; }
void rotate_up() { row_ofs = (row_ofs+1 ) % rows; }
void rotate_down() { row_ofs = (row_ofs+rows-1) % rows; }
};
(untested)
Edit: Here's an alternative: Use std::deque<std::deque<T> > internally. ;-)
Yes, it does support random access. A deque is not a list. Plus, you don't need to bother anymore with the modulo arithmetic.
Not sure what you mean exactly. Usually right-shift is applied to a buffer or row vector. The answer will depend on how your matrix is stored.
An efficient way to rotate an array, if the memory layout allows it, is to copy the first value to the end of the array and then move the pointer to the array up one element. This will only work if you allocate enough room for the array and don't rotate too many times.
Or, you can just keep the array in place and have an extra pointer to the "left end", taking care to handle all the wrapping around correctly in your other operations.
Otherwise, you will probably have to perform a lot of memcopying.
Edit: I see you just updated the question to include this answer.
Other edit: From the examples, you don't seem to need to shift the rows and columns independently. If that is the case, then you just need to store the coordinates of the "top left" index and modify all the matrix operations to lookup values in the data structure appropriately.
The issue for you then becomes a question of where you want the efficiency. Are you going to be performing many shift operations? If not, then it might not be worth slowing down all the multiplication operations with an extra lookup.
And if you do use the lookup idea, definitely DO NOT use a mod operator. It is incredibly inefficient. Instead, for a shift, just test for greater than row or column length and subtract the length when needed.
Another method, I was considering was implementing a vector of pointers to columns (of the matrix) represented by vectors and swapping them around when a shift operation occurs.
I would do this for the columns (horizontal shift) and another vector for the rows (vertical shift).
I would also create a Matrix object to encapsulate your "real" matrix and these two vectors. The getters/setters of your object would reference those two vectors to access data in your "real" matrix and you would have methods like "horizontalShift(...)" and "verticalShift(...)" that only swap values in your two vectors, like you suggested.
Would it be the fastest implementation ? There one more indirection to access the data (still O(1) though) and the swapping would be O(m) for horizontal shift and O(n) for vertical shift (for a n by m matrix) using vectors.
There are methods that make doing the shift itself very fast, but result in inefficiencies when trying to 'use' the matrix, e.g. print, dot\cross products.
For example, if I had a matrix defined like "int m[3][2];" I might just use an index to define the first column index. Thus a shift is just an add\subtract of that one index (no modification of the data).
Another example; if you want to restrict the matrix to being binary, you could pack the matrix into a single variable and use bit shifts (rotate left\right).
Both of these methods would make other operations more complex however.
I guess it all depends on the scope of how the matrix is going to be used and how generic you want it to be.
Using Eigen library it is very simple:
Eigen::Matrix<int, 3, 3> A;
A << 1, 2, 3,
4, 5, 6,
7, 8, 9;
std::cout << A << std::endl << std::endl;
// Right-shift:
A.col(0).swap(A.col(1));
A.col(0).swap(A.col(2));
std::cout << A << std::endl << std::endl;
// Down-shift:
A.row(0).swap(A.row(1));
A.row(0).swap(A.row(2));
std::cout << A << std::endl << std::endl;
There is a very useful reference guide for Eigen-MATLAB correspondence.
I implemented a recursion C++ version by anti clock wise shift:
// rotateMatrix.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
using namespace std;
void rotatematrix(int M[][3], int row, int col, int rowLen, int colLen)
{
//rowLen & colLen are always the orginal matrix total length
// playRows & playCols are the size for the current recuision
// row & col are the starting position related to the original matrix(0,0)
int playRows = rowLen - 2*row ;
int playCols = colLen - 2*col;
if (playCols <= 1 || playRows <= 1)
return;
//row,col is the starting point pointing to the top left corner element
if (rowLen <= 1 || colLen <= 1) return;
int tmp = M[row][col];
//left shift the top row by one element
for (int j = col; j <= playCols + col - 2; ++j)
M[row][j] = M[row][j + 1];
// up shift the right colunm by one position
for (int i = row; i <= playRows + row - 2; ++i)
M[i][col + playCols - 1] = M[i + 1][col + playCols - 1];
//right shift the bottom row by one
for (int j = col + playCols - 2; j >= col; --j)
M[row+playRows-1][j+1] = M[row+playRows-1][j];
// down shift the left col by one
for (int i = row + playRows - 2; i >= row; --i)
M[i+1][col] = M[i][col];
M[row + 1][col] = tmp;
rotatematrix(M, ++row, ++col, rowLen, colLen);
}
int _tmain(int argc, _TCHAR* argv[])
{
// Test Case 1
/*
int a[4][4] = { { 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12 },
{ 13, 14, 15, 16 } };
int R = 4, C = 4;*/
// Tese Case 2
int R = 3, C = 3;
int a[3][3] = {{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
for (int i = 0; i<R; i++)
{
for (int j = 0; j<C; j++)
cout << a[i][j] << " ";
cout << endl;
}
rotatematrix(a, 0, 0, 3, 3);
// Print rotated matrix
for (int i = 0; i<R; i++)
{
for (int j = 0; j<C; j++)
cout << a[i][j] << " ";
cout << endl;
}
return 0;
}
I have made code for rotating an array in circular fashion layer by layer.
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n;
int value=1;
scanf("%d",&n);
int arr[n][n];
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
arr[i][j]=value++;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
printf("%d\t",arr[i][j]);
printf("\n");
}
for(int r1=0,r2=n-1,c1=0,c2=n-1;r1<=r2;r1++,r2--,c1++,c2--)
{
int temp=arr[c1][r2];
for(int i=r2;i>r1;i--)
arr[c1][i]=arr[c1][i-1];
int temp2=arr[c2][r2];
for(int i=c2;i>c1;i--)
if(i!=c1+1)
arr[i][r2]=arr[i-1][r2];
else
arr[i][r2]=temp;
temp=arr[c2][r1];
for(int i=r1;i<r2;i++)
if(i!=r2-1)
arr[c2][i]=arr[c2][i+1];
else
arr[c2][i]=temp2;
for(int i=c1;i<c2;i++)
if(i!=c2-1)
arr[i][r1]=arr[i+1][r1];
else
arr[i][r1]=temp;
}
printf("\n\n");
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
printf("%d\t",arr[i][j]);
printf("\n");
}
return 0;
}
Sample code working:
Related
I have been doing this problem for 2 days now, and I still can't figure out how to do this properly.
In this program, I have to input the number of sticks available (let's say 5). Then, the user will be asked to input the lengths of each stick (space-separated integer). Let's say the lengths of each stick respectively are [4, 4, 3, 3, 4]. Now, I have to determine if there are pairs (2 sticks of same length). In this case, we have 2 (4,4 and 3,3). Since there are 2 pairs, we can create a canvas (a canvas has a total of 2 pairs of sticks as the frame). Now, I don't know exactly how to determine how many "pairs" there are in an array. I would like to ask for your help and guidance. Just note that I am a beginner. I might not understand complex processes. So, if there is a simple (or something that a beginner can understand) way to do it, it would be great. It's just that I don't want to put something in my code that I don't fully comprehend. Thank you!
Attached here is the link to the problem itself.
https://codeforces.com/problemset/problem/127/B
Here is my code (without the process that determines the number of pairs)
#include<iostream>
#include<cmath>
#define MAX 100
int lookForPairs(int numberOfSticks);
int main(void){
int numberOfSticks = 0, maxNumOfFrames = 0;
std::cin >> numberOfSticks;
maxNumOfFrames = lookForPairs(numberOfSticks);
std::cout << maxNumOfFrames << std::endl;
return 0;
}
int lookForPairs(int numberOfSticks){
int lengths[MAX], pairs = 0, count = 0, canvas = 0;
for(int i=0; i<numberOfSticks; i++){
std::cin >> lengths[i];
}
pairs = floor(count/2);
canvas = floor(pairs/2);
return count;
}
I tried doing it like this, but it was flawed. It wouldn't work when there were 3 or more integers of the same number (for ex. [4, 4, 3, 4, 2] or [5. 5. 5. 5. 6]). On the first array, the count would be 6 when it should only be 3 since there are only three 4s.
for(int i=0; i<numberOfSticks; i++){
for (int j=0; j<numberOfSticks; j++){
if (lengths[i] == lengths[j] && i!=j)
count++;
}
}
Instead of storing all the lengths and then comparing them, count how many there are of each length directly.
These values are known to be positive and at most 100, so you can use an int[100] array for this as well:
int counts[MAX] = {}; // Initialize array to all zeros.
for(int i = 0; i < numberOfSticks; i++) {
int length = 0;
std::cin >> length;
counts[length-1] += 1; // Adjust for zero-based indexing.
}
Then count them:
int pairs = 0;
for(int i = 0; i < MAX; i++) {
pairs += counts[i] / 2;
}
and then you have the answer:
return pairs;
Just an extension to molbdnilo's answer: You can even count all pairs in one single iteration:
for(int i = 0; i < numberOfSticks; ++i)
{
if(std::cin >> length) // catch invalid input!
{
pairs += flags[length] == 1; // add a pair if there is already a stick
flags[length] ^= 1; // toggle between 0 and 1...
}
else
{
// some appropriate error handling
}
}
Note that I skipped subtracting 1 from the length – which requires the array being one larger in length (but now it can be of smallest type available, i.e. char), while index 0 just serves as an unused sentinel. This variant would even allow to use bitmaps for storing the flags, though questionable if, with a maximum length that small, all this bit fiddling would be worth it…
You can count the number of occurrences using a map. It seems that you are not allowed to use a standard map. Since the size of a stick is limited to 100, according to the link you provided, you can use an array, m of 101 items (stick's minimum size is 1, maximum size is 100). The element index is the size of the stick. The element value is the number of sticks. That is, m[a[i]] is the number of sticks of size a[i]. Demo.
#define MAX 100
int n = 7;
int a[MAX] = { 1,2,3,4,1,2,3 };
int m[MAX + 1]; // maps stick len to number of sticks
void count()
{
for (int i = 0; i < n; ++i)
m[a[i]]++;
}
int main()
{
count();
for (int i = 1; i < MAX + 1; ++i)
if (m[i])
std::cout << i << "->" << m[i] << std::endl;
}
Your inner loop is counting forward from the very beginning each time, making you overcount the items in your array. Count forward from i , not zero.
for(int i=0; i<numberOfSticks; i++)
{
for (int j=i; j<numberOfSticks; j++) { // count forward from i (not zero)
if (lengths[i] == lengths[j] && i!=j)
{ // enclosing your blocks in curly braces , even if only one line, is easier to read
count++; // you'll want to store this value somewhere along with the 'length'. perhaps a map?
}
}
}
I am trying to implement a small program that iterates over a 2d vector backwards and adds the value of the element.
If that element have already been added then I want to overwrite the value of the vector with 99.
So for example if number of climbs is four then add the of the program points should have the value 5 and the vector should look like this at the end
{1, 1 ,1},
{99, 1, 1},
{99(should start here), 99, 99}
But I keep getting a segmentation fault and I don't know whether I am iterating over the vector backwards incorrectly.
This is my full code
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<vector<int>> vect
{ {3}, //finish here
{1, 1 ,1},
{2, 1, 1},
{1, 1, 1} //start here
};
int points = 0;
for (int i = 0; i < vect.size(); i++)
{
for (int j = 0; j < vect[i].size(); j++)
{
cout << vect[i][j] << " ";
}
cout << endl;
}
int visited = 99;
int number_of_climbs = 4;
for(int i = 4; i >= 0; i--)
for (int j = 0; j < number_of_climbs; j++)
{
if(vect[i][j] != 99)
{
points += vect[i][j];
vect[i][j] = 99;;
continue;
}
}
return 0;
}
Looping over things backwards always trips me up too, especially when I accidentally declare my loop using an unsigned int. Your backwards loop is close to correct, but can be simplified into:
for (int i = vect.size() - 1; i >= 0; --i)
{
for (int j = vect[i].size() - 1; j >= 0; --j)
{
}
}
You need to start at size() - 1 because the only indices available are [0, size) (that is EXCLUSIVE of size), so in a vector of 4 elements, that's 0, 1, 2 and 3 (and you need to start at 3), which is likely the cause of your segmentation fault since you start your initial loop at 4 so it's immediately out-of-bounds.
Here in the inner loop you can see we account for the vectors being different sizes by just using the size of each vector.
It's also possible to use reverse iterators, but iterators can be confusing to people:
for (auto outer = vect.rbegin(); outer != vect.rend(); ++outer)
{
for (auto inner = outer->rbegin(); inner != (*outer).rend(); ++inner)
{
}
}
Note I've shown both ways to access the iterator, using it-> or (*it). Within the inner loop, you will simply use *inner to get the actual value held by the vector, so if you simply had std::cout << *inner << " "; that would print the 2d vector on one line in reverse order.
Even though we're looping in reverse, we still use ++
I have a large amount of data (GiB to TiB) in a C-style array of 2D data. It is not an array-of-arrays but instead a pointer to data that is interpreted as 2D data. It is very large so I do not want to copy it to std::vectors or similar. I cannot control the source of the data, it comes from an external library.
I need to std::sort the rows of the data based on the data in the columns (not quite lex-sort, but similar concept).
I have figured out how to do it with a compile-time known number of columns. For example:
#define COLUMNS 4
struct Row {
double values[COLUMNS];
};
double* data = ...;
size_t n_rows = ...;
size_t n_cols = COLUMNS;
std::sort((Row*)data, ((Row*)data)+n_rows, comp);
I know I can template the struct for COLUMNS instead of using a macro and instead of using comp could define the operator< than in the Row struct but that doesn't change the compile-time nature of the number of columns*.
The only solution I can think of is to use a custom random-access iterator that knows the stride of each row. But before I make my own iterator (which is always a bit daunting to me) I want to make sure there is no other way.
*These design choices were made due to the fact I am actually writing this in Cython and not C++, but that shouldn't matter, I can't figure out how to do this with C++ without a custom iterator. I am willing to write solutions in C++ but prefer options that can be written Cython (I can convert).
Example code showing the reorder in place in O(n) time below. You'll need to change pa[i]-a which converts a pointer to index to deal with the actual structure for a[].
#include <algorithm>
#include <iostream>
bool compare(const double *p0, const double *p1)
{
return *p0 < *p1;
}
int main()
{
double a[8] = {8.0,6.0,1.0,7.0,5.0,3.0,4.0,2.0};
double *pa[8];
size_t i, j, k;
double ta;
// create array of pointers to a[]
for(i = 0; i < sizeof(a)/sizeof(a[0]); i++)
pa[i] = &a[i];
// sort array of pointers to a[]
std::sort(pa, pa+sizeof(a)/sizeof(a[0]), compare);
// reorder a[] and pa[] according to pa[] in O(n) time
for(i = 0; i < sizeof(a)/sizeof(a[0]); i++){
if(i != pa[i]-a){
ta = a[i];
k = i;
while(i != (j = pa[k]-a)){
a[k] = a[j];
pa[k] = &a[k];
k = j;
}
a[k] = ta;
pa[k] = &a[k];
}
}
for(i = 0; i < sizeof(a)/sizeof(a[0]); i++)
std::cout << a[i] << ' ';
std::cout << std::endl;
return 0;
}
The reorder in place works by undoing the "cycles" in pa[] sorted according to a[]. For this example code, a list of indices 0 to 7 followed by a list of pa[i]-a for i = 0 to 7 results in:
0 1 2 3 4 5 6 7 (i)
2 7 5 6 4 1 3 0 (pa[i] - a)
This shows the "cycles" in pa[] sorted according to a[]. Starting with the 0 in the (i) line, the index below it is 2. Looking at the 2 in the i line, the number below it is a 5. Below 5 is a 1. Below 1 is a 7. Below 7 is a 0, completing that cycle. Using -> to note the next index, there are 3 cycles in this case:
{0->2->5->1->7->0} {3->6->3} {4->4}
What the reorder in place does is undo the cycles for both a[] and pa[]. It finds the first cycle at pa[0] (i != pa[i]-a). Looking at a[], you have ta=a[0], a[0]=a[2], a[2] = a[5], a[5]=a[1], a[1]=a[7], at this point i == 0 == pa[7]-a, the last part of the cycle and it sets a[7] = ta. pa[] is updated in the same manner. The next cycle is ta=a[3], a[3]=a[6], a[6] = ta. The last cycle, 4->4 points to itself, so is skipped (i == pa[i]-a). The time complexity for this is O(n).
There's a youtube video about permutations and cycle notation (in this case it would be (0,2,5,1,7)(3,6) (the (4) is ignored since it's in place). You can do a web search for "permutation cycle" for other articles.
https://www.youtube.com/watch?v=MpKG6FmcIHk
This might do the trick. Define Row as a pointer to the beginning of a row, like so:
struct Row {
double* start;
static int columns;
Row(const Row& row) = default;
// Overload operator= to copy your data.
Row& operator=(const Row& rhs) {
memcpy(start, rhs.start, columns*sizeof(double));
}
Row operator<(const Row& rhs) const {
// your comparison function
}
};
Use like so:
double* data = ...;
size_t n_rows = ...;
size_t n_cols = COLUMNS;
Row::columns = n_cols;
std::vector<Row> rows(n_rows);
for(int i=0;i<n_rows;++i) {
rows[i].start = data + i*n_cols;
}
std::sort(rows.begin(), rows.end());
You'll need to create a std::vector<Row>. Hopefully you don't have so many rows so that's a performance issue.
Question is: write a function that takes an array A of length n and an index i into A, and rearrange the elments such that all elements less than A[i] appear first, followed by elements equal to A[i], followed by elements greater than A[i].
explanation for my code:
Ask user for n numbers, which is 11. And ask him what the index that he wants to rearrange the elements with. It takes it to function1, and creates a for loop and does an if else statement. if A[i] < A{index} , place it in the begining, else if it's less, place it at the end, or place it in the middle:
Here is my code
#include <iostream>
using namespace std;
void function1(int a[], int ind);
int main()
{
int a[11];
int index;
cout << " enter the numbers: " << endl;
for(int i=0; i < 11; i++)
cin >> a[i];
cout << "what is the index ? " << endl;
cin >> index;
function1(a,index);
}
void function1(int a[], int ind)
{
int x = a[ind];
int newArray[11];
for(int i=0; i < 11; i++)
{
if(a[i] < x)
{
newArray[i] = a[i];
}
else if(a[i] > x)
{
newArray[10-i] = a[i];
}
else
{
newArray[10/2] = a[i];
}
}
for(int i=0; i<11; i++)
cout << newArray[i] << " ";
}
The output that I am expecting to get is the rearrangement of the new array which will probably look similar to this:
a[0....x....n-1], where x is the index that represents a[i]
however I am getting incorrect output with numbers randomly scattered across
what is wrong with my logic ?
The problem is that (like Olaf Dietsche pointed out) you take just one index where two are necessary. Further you can't know if the element that is neither smaller not bigger than a[ind] (means equal to a[ind]) is to be inserted in the middle of the new array. (Imagine 3 2 1 and index 3 results in 2 1 3 but 3 isn't in the middle!)
Updated Version (allows for multiple elements with same value as pivot element)
void rearange(int* data, int size, int pivot)
{
int* temp_data = new int[size];
int start_index = 0, end_index = size - 1;
for (int i = 0; i < size; i++)
{
if (data[i] < data[pivot]) // -> insert 'before' pivot element
{
temp_data[start_index] = data[i];
start_index++;
}
else if (data[i] > data[pivot]) // -> insert 'behind' pivot element
{
temp_data[end_index] = data[i];
endIndex--;
}
// else: skip pivot(s)
}
// insert pivot element(s)
for (int i = start_index; i <= end_index; i++)
{
temp_data[i] = data[pivot];
}
for (int i = 0; i < size; i++)
{
std::cout << temp_data[i] << " ";
}
delete[] temp_data;
}
Input:
11 10 9 8 7 7 7 6 5 4 3
5
Output
6 5 4 3 7 7 7 8 9 10 11
As you see, all elements smaller than element 5 (with value of 7) are before, all elements greater are behind the pivot element. All other elements with same value as pivot are wrapped around position 5, wherever there's free space. However the rearranged elements are not yet sorted (apart from being positioned relative to pivot element)!
You use the same index i for the smaller and larger values. This means, if only the last value a[10] is larger than x, you will write it in the first location newArray[10 - 10], even though you already filled all places up to the 10th. Another problem is, when you have multiple middle values. They will all be stored into newArray[5].
What you want to achieve is called partitioning, as used in the quicksort algorithm.
You need to maintain two indexes (pointers), one for the smaller (left) and one for the larger (right) values.
You have to determine the size of your array at the beginning and pass the fixed size of the array to the function as a parameter.
My code is:
#include <iostream>
using namespace std;
void insertion(int*, int);
int main() {
int a[6] = {9, 5, 3, 7, 5, 6};
for (int i = 0; i < 6; i++)
cout << a[i] << " ";
insertion(&a[0], 6);
cout << "now insertion sort \n";
for (int x = 0; x < 6; x++)
cout << a[x] << "\n";
return 0;
}
void insertion(int* l, int m) {
int temp;
for (int i = 0; i < m; i++) {
while (*(l + i) > *(l + 1 + i) && (i > 0)) {
temp = *(l + i);
*(l + i + 1) = *(l + i);
*(l + i) = temp;
i--;
}
}
}
What is wrong with the function sorting?
The output that I'm getting is: 9 5 5 7 7 7
What other details should I add (this is my first doubt in stackoverflow)?
Your logic isn't really correct for an insertion sort. In fact, what you have right now is much closer to a bubble sort (though it's obviously not quite right for that either).
For an insertion sort, the logic goes something like this (assuming 0-based indexing):
for i = 1 to array_length
if array[i] < array[i-1]
temp = array[i]
for j = i downto 1 && temp < array[j-1]
array[j] = array[j-1]
array[j-1] = temp
endif
So the basic idea here is that for each element, we search backwards through the array to find the right place to put that element. As we do so, we shift elements upwards by one spot, so when we got to the right spot, we have a place to put it.
Note, in particular, that this doesn't contain any swap-like code anywhere. We don't normally plan on swapping adjacent elements as you've done. It can/will happen when/if an element happens to be out of place by exactly one position, but it's pretty much incidental when it does.