I am trying to remove every 2nd element from an integer vector in C++
int n = 10001;
std::vector<int> sieve;
for (int i = 2; i <= n; ++i)
sieve.push_back(i);
for (int i = 2; i < sieve.size(); i += 2)
sieve.erase(sieve.begin() + i);
I want to remove every 2nd element from the vector ( which would be multiples of 2 in range from 2-10001). The output is this:
// index, value
0 2
1 3
2 5
3 6
4 8
5 9
6 11
7 12
8 14
9 15
10 17
....
So it removes the 4, 10, and 16 as expected. However there are still many multiples of 2 still in there, ie 6, 8, 12, 14
EDIT Solved using method #Retired Ninja posted in comments. (Do it in reverse)
for (int i = 2; i <= n; i++)
sieve.push_back(i);
for (int i = sieve.size(); i >= p; i -= p)
sieve.erase(sieve.end() - i);
When you are erasing second element the iterator of next element decrease 1.
So increasing 1 time of loop variable is ok.
int n = 100;
std::vector<int> sieve;
for (int i = 2; i <= n; ++i)
sieve.push_back(i);
for (int i = 2; i < sieve.size(); i += 1)
sieve.erase(sieve.begin() + i);
And another way in case of erasing pth element:
int cnt=0;
int l=sieve.size();
for (int i = 2; i < l; i += p){
sieve.erase(sieve.begin() + (i-cnt));
cnt++;
}
How about this? This removes every nth element starting at start from vec.
It's performed in-place, involves only a single array resize, and each element not erased is moved exactly once.
void remove(std::size_t nth, std::size_t start, std::vector<int> &vec)
{
std::size_t step;
for (step = 1; start < vec.size(); ++step, start += nth)
{
for (std::size_t i = 1; i < nth && start + i < vec.size(); ++i)
{
vec[start + i - step] = vec[start + i];
}
}
vec.resize(vec.size() - (step - 1));
}
I have a squared 2D array that I would like to rotate clockwise and counter clockwise.
I was following this answer here for rotating to the right:
Rotating a 2D pixel array by 90 degrees
The code I developed:
void rotateRight()
{
for (int i = 0; i < m_width; i += 1) {
for (int j = i + 1; j < m_height; j += 1) {
std::swap(get(i, j), get(j, i));
}
}
}
However, the array did not rotate. I have a 10x10 array with 5's, and on the top-left corner is a 7. I expected the 7 to go to the top-right corner after rotating, but it's still at the top-left corner.
The member function get() is my own, which just returns a reference to a cell.
T& get(const int x, const int y)
{
return m_array[y * m_width + x];
}
How can I get this to rotate? Does a new array have to be made? Would appreciate the help. Thanks!
Update:
Latest attempt. Okay, so the '7' rotated to the right finally from the top-left corner to the top-right corner. But when rotateRight() is called again, it fails. My 7 on the top-right corner is gone and no longer found. Looking into it.
for (int i = 0; i < m_width; i += 1) {
for (int j = i + 1; j < m_height; j += 1) {
get(j, i) = get(i, j);
}
}
for (int i = 0; i < m_height; i++) {
for (int j = 0, k = m_height - 1; j<k; j++, k--) {
std::swap(get(j, i), get(k, i));
}
}
Output:
Original:
700
000
000
Rotation #1:
J: 1, I: 0
J: 2, I: 0
J: 2, I: 1
J: 0, I: 0, K: 2
Value: 7 J: 0 K: 2
J: 0, I: 1, K: 2
Value: 0 J: 0 K: 2
J: 0, I: 2, K: 2
Value: 0 J: 0 K: 2
007
000
000
Rotation #2:
J: 1, I: 0
J: 2, I: 0
J: 2, I: 1
J: 0, I: 0, K: 2
Value: 0 J: 0 K: 2
J: 0, I: 1, K: 2
Value: 0 J: 0 K: 2
J: 0, I: 2, K: 2
Value: 0 J: 0 K: 2
000
000
000
Final code
// Rotates a squared array clockwise.
void rotateRight()
{
T temp;
int halfwidth_floor = m_width / 2;
int halfwidth_ceil = (m_width + 1) / 2;
for (int j = 0; j < halfwidth_floor; j += 1) {
for (int i = 0; i < halfwidth_ceil; i += 1) {
std::swap(temp, get(i, j));
std::swap(get(i, j), get(j, m_width - i - 1));
std::swap(get(j, m_width - i - 1), get(m_width - i - 1, m_width - j - 1));
std::swap(get(m_width - i - 1, m_width - j - 1), get(m_width - j - 1, i));
std::swap(get(m_width - j - 1, i), temp);
}
}
}
// Rotates a squared array counter-clockwise.
void rotateLeft()
{
T temp;
int n = m_width;
for (int i = 0; i < n / 2; i++) {
for (int j = i; j < n - i - 1; j++) {
std::swap(temp, get(i, j));
std::swap(get(i, j), get(n - j - 1, i));
std::swap(get(n - j - 1, i), get(n - i - 1, n - j - 1));
std::swap(get(n - i - 1, n - j - 1), get(j, n - i - 1));
std::swap(get(j, n - i - 1), temp);
}
}
}
Each iteration of your inner loop is swapping (i, j) with (j, i).
If (i == j), then it will do nothing.
If (i != j), then that swap will be done twice - for example, the swap done when i == 3 and j == 4 will be done again when i == 4 and j == 3. Doing a swap twice of course results in nothing happening overall.
That's why your code will finish with an array that's exactly the same as it started.
What you may want to do instead is to write into a different array to the one you started with.
edit: nevermind, I missed the int j = i + 1 part of the question and thought both loops were iterating from 0 to the width or height. (The above might still be a useful insight for anyone looking to do the same thing though.)
Your code will transpose, not rotate, the array. (Transpose means to reflect along the diagonal from top left to bottom right.) To rotate, you'd want to move each element (i, j) to (j, w-i-1) or to (h-j-1, i). (Though of course, to rotate by 90 degrees, your array needs to be a square, i.e. (w == h)).
edit 2:
If you want to rotate a square array in-place, by 90 degrees, std::swap won't work (because it swaps 2 elements), and raw assignment won't work (because it loses information). What you can do, though, is to iterate over a quarter of the array and rotate a sequence of 4 elements, like so:
void rotateRight()
{
int halfwidth_floor = m_width / 2;
int halfwidth_ceil = (m_width + 1) / 2;
for (int j = 0; j < halfwidth_floor; j += 1) {
for (int i = 0; i < halfwidth_ceil; i += 1) {
value_type temp = get(i, j);
get(i, j) = get(j, m_width-i-1);
get(j, m_width-i-1) = get(m_width-i-1, m_width-j-1);
get(m_width-i-1, m_width-j-1) = get(m_width-j-1, i);
get(m_width-j-1, i) = temp;
}
}
}
Where value_type is the type of your array elements (and m_width == m_height).
On the first iteration, this will move the bottom left to the top left, then the bottom right to the bottom left, then the top right to the bottom right, then the (temporarily saved) top left to the top right. Subsequent iterations will do the same for other points, getting closer towards the center. Note that one for loop iterates to half the size rounded down, and the other rounds up: this is so that in an array with an odd size (e.g. 5x5) it will look at a rectangle of 2x3 and its "rotations" around the square, to avoid rotating the middle elements twice (or not at all).
What you are doing
Transposing the matrix.
What you should be doing
The algorithm to rotate a matrix consists of 2 steps
Transpose the matrix ( if rotating left) . Transpose and reverse the order of the columns if rotating right)
Reverse the columns
Illustrated below
1 2 3 1 4 7 3 6 9
4 5 6 => 2 5 8 => 2 5 8
7 8 9 3 6 9 1 4 7
Code
Like so, (initialize an aux array that will hold the rotated array, because the shape could be not square)
void rotate()
{
for (int i = 0; i < m_width; i += 1) {
for (int j = i + 1; j < m_height; j += 1) {
aux_array[j][i] = get(i, j)
}
}
for (int i=0; i < m_height; i++) {
for (int j=0, int k=m_height-1; j<k; j++,k--) {
swap(aux_array[j][i], aux_array[k][i]);
}
}
}
I need to find a number of monotonus subvectors or arrays in my vector, or arrays, it doesn't mater. For example , I have vector 1234421257843, and here i have 4 monotonus subvectors...
1. 1 2 3 4 4
2. 4 4 2 1
3. 1 2 5 7 8
4. 8 4 3, and number is 4.
I tried something like this ,but doesn't work...
int num(std::vector<int> v){
int p(1),q(1);
for(int i(0);i<v.size()-1;i++){
if (v[i] > v[i+1] ) continue;
else if(v[i] < v[i+1]) continue;
else p++;
} return p;
}
I believe this will help you to find number of monotonus subvectors in one vector:
int num(const std::vector<int>& v) {
int p = 0;
for (int i = 0; i + 1 < v.size(); ) {
p += (v[i+1] >= v[i]);
for (++i; (i + 1 < v.size()) && (v[i+1] >= v[i]); ++i) {
}
if (i + 1 == v.size())
return p;
p += (v[i+1] <= v[i]);
for (++i; (i + 1 < v.size()) && (v[i+1] <= v[i]); ++i) {
}
}
return p;
}
But if you want to find largest monotonus subvector you don't need this. The task can be solved with the help of DP (Dynamic programming): you need two additional vectors a(n) and d(n), where a(i) / d(i) - is the length of longest ascending / descending subvector ending at position i: starting with a[0] = 1 you can easily calculate a[i + 1] = a[i] + 1 if v[i+1] > v[i] or 1 otherwise
So I had to write a program for a computer project for high school and I thought of doing a sudoko solver. The 'solve' algorithm is implemented like this:-
For any points where only one element 'fits' looking at rows, columns, 3x3 set, put that number in. Do this repeatedly till it can't be done anymore. This is seen in the 'singleLeft' function.
If a number 'fits' in some point but nowhere else in the associated row, column or 3x3 set, put that number in. This can be seen in the 'checkOnlyAllowed' function.
If we're not done yet, do a 'guess' - take some number that 'fits' in the point, put it in there and then solve again using this algorithm (recurse) - if it works, we're done.
So far, I have this code:
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
//Prints a message and exits the application.
void error(const char msg[])
{
cout << "An error occurred!" << endl;
cout << "Description: " << msg << endl;
exit(0);
}
//A representation of a sudoku board. Can be read from a file or from memory.
class Sudoku
{
protected:
//For a point x, y and a number n in the board, mAllowed[x][y][n]
//is 1 if n is allowed in that point, 0 if not.
int mAllowed[9][9][10];
int filledIn;
public:
/*
* For mBoard[i][j], the location is (i,j) in the below map:
*
* (0,0) (0,1) (0,2) (0,3) (0,4) (0,5) (0,6) (0,7) (0,8)
* (1,0) (1,1) (1,2) (1,3) (1,4) (1,5) (1,6) (1,7) (1,8)
* (2,0) (2,1) (2,2) (2,3) (2,4) (2,5) (2,6) (2,7) (2,8)
*
* (3,0) (3,1) (3,2) (3,3) (3,4) (3,5) (3,6) (3,7) (3,8)
* (4,0) (4,1) (4,2) (4,3) (4,4) (4,5) (4,6) (4,7) (4,8)
* (5,0) (5,1) (5,2) (5,3) (5,4) (5,5) (5,6) (5,7) (5,8)
*
* (6,0) (6,1) (6,2) (6,3) (6,4) (6,5) (6,6) (6,7) (6,8)
* (7,0) (7,1) (7,2) (7,3) (7,4) (7,5) (7,6) (7,7) (7,8)
* (8,0) (8,1) (8,2) (8,3) (8,4) (8,5) (8,6) (8,7) (8,8)
*
*/
int mBoard[9][9];
//Read in from file with given name.
Sudoku(char filename[])
{
filledIn = 0;
int i, j, k;
//Fill the board with 0s.
for (i = 0; i < 9; ++i)
for (j = 0; j < 9; ++j)
mBoard[i][j] = 0;
//Set every number to 'allowed' initially.
for (i = 0; i < 9; ++i)
for (j = 0; j < 9; ++j)
for (k = 1; k <= 9; ++k)
mAllowed[i][j][k] = 1;
//Read in from the file.
ifstream file(filename);
if (!file)
error("File doesn't exist!");
for (i = 0; i < 9; ++i)
for (j = 0; j < 9; ++j)
if (file)
{
int m;
file >> m;
if (m)
set(i, j, m);
}
else
error("Not enough entries in file!");
}
//Solve the board!
int solve()
{
int prevFilledIn;
do
{
prevFilledIn = filledIn;
singleLeft();
checkOnlyAllowed();
} while (filledIn - prevFilledIn > 3);
if (filledIn < 81)
guess();
return filledIn == 81;
}
//Given a point i, j, this looks for places where this point
//disallows a number and sets the 'mAllowed' table accordingly.
void fixAllowed(int i, int j)
{
int n = mBoard[i][j], k;
for (k = 0; k < 9; ++k)
mAllowed[i][k][n] = 0;
for (k = 0; k < 9; ++k)
mAllowed[k][j][n] = 0;
//Look in 3x3 sets too. First, set each coordinate to the
//highest multiple of 3 below itself. This takes us to the
//top-left corner of the 3x3 set this point was in. Then,
//add vectorially all points (x,y) where x and y each are
//one of 0, 1 or 2 to visit each point in this set.
int x = (i / 3) * 3;
int y = (j / 3) * 3;
for (k = 0; k < 3; ++k)
for (int l = 0; l < 3; ++l)
mAllowed[x + k][y + l][n] = 0;
mAllowed[i][j][n] = 1;
}
//Sets a point i, j to n.
void set(int i, int j, int n)
{
mBoard[i][j] = n;
fixAllowed(i, j);
++filledIn;
}
//Try using 'single' on a point, ie, only one number can fit in this
//point, so put it in and return 1. If more than one number can fit,
//return 0.
int trySinglePoint(int i, int j)
{
int c = 0, m;
for (m = 1; m <= 9; ++m)
c += mAllowed[i][j][m];
if (c == 1)
{
for (m = 1; m <= 9; ++m)
if (mAllowed[i][j][m])
set(i, j, m);
//printBoard();
return 1;
}
return 0;
}
//Try to solve by checking for spots that have only one number remaining.
void singleLeft()
{
for (;;)
{
for (int i = 0; i < 9; ++i)
for (int j = 0; j < 9; ++j)
if (!mBoard[i][j])
if (trySinglePoint(i, j))
goto logic_worked;
//If we reached here, board is either full or unsolvable by this logic, so
//our job is done.
return;
logic_worked:
continue;
}
}
//Within rows, columns or sets, whether this number is 'allowed' in spots
//other than i, j.
int onlyInRow(int n, int i, int j)
{
for (int k = 0; k < 9; ++k)
if (k != j && mAllowed[i][k][n])
return 0;
return 1;
}
int onlyInColumn(int n, int i, int j)
{
for (int k = 0; k < 9; ++k)
if (k != i && mAllowed[k][j][n])
return 0;
return 1;
}
int onlyInSet(int n, int i, int j)
{
int x = (i / 3) * 3;
int y = (j / 3) * 3;
for (int k = 0; k < 3; ++k)
for (int l = 0; l < 3; ++l)
if (!(x + k == i && y + l == j) && mAllowed[x + k][y + l][n])
return 0;
return 1;
}
//If a number is 'allowed' in only one spot within a row, column or set, it's
//guaranteed to have to be there.
void checkOnlyAllowed()
{
for (int i = 0; i < 9; ++i)
for (int j = 0; j < 9; ++j)
if (!mBoard[i][j])
for (int m = 1; m <= 9; ++m)
if (mAllowed[i][j][m])
if (onlyInRow(m, i, j) || onlyInColumn(m, i, j) || onlyInSet(m, i, j))
set(i, j, m);
}
//Copy from a given board.
void copyBoard(int board[9][9])
{
filledIn = 0;
for (int i = 0; i < 9; ++i)
for (int j = 0; j < 9; ++j)
{
if (board[i][j] > 0)
++filledIn;
mBoard[i][j] = board[i][j];
}
}
//Try to solve by 'guessing'.
void guess()
{
for (int i = 0; i < 9; ++i)
for (int j = 0; j < 9; ++j)
for (int n = 1; n <= 9; ++n)
if (!mBoard[i][j])
if (mAllowed[i][j][n] == 1)
{
//Do a direct copy so that it gets the 'mAllowed'
//table too.
Sudoku s = *this;
//Try solving with this number at this spot.
s.set(i, j, n);
if (s.solve())
{
//It was able to do it! Copy and report success!
copyBoard(s.mBoard);
return;
}
}
}
//Print the board (for debug purposes)
void printBoard()
{
for (int i = 0; i < 9; ++i)
{
for (int j = 0; j < 9; ++j)
cout << mBoard[i][j] << " ";
cout << endl;
}
cout << endl;
char s[5];
cin >> s;
}
};
int main(int argc, char **argv)
{
//char filename[42];
//cout << "Enter filename: ";
//cin >> filename;
char *filename = argv[1];
Sudoku s(filename);
if (!s.solve())
error("Couldn't solve!");
cout << "Solved! Here's the solution:" << endl << endl;
for (int i = 0; i < 9; ++i)
{
for (int j = 0; j < 9; ++j)
cout << s.mBoard[i][j] << " ";
cout << endl;
}
return 0;
}
(code including line numbers: http://sprunge.us/AiUc?cpp)
Now I understand that it isn't very good style, but it came out of a late-night coding session and also we use an older compiler in the school lab so I had to do some things differently (in that compiler, the standard headers have the '.h' extension, variables declared in for loops are in outside-for scope, ... ).
The file should contain whitespace-delimited digits for each spot in the board starting from the top-left going left to right and top to bottom, with empty spots signified by '0's.
For the following file, it works rather well:
5 3 0 0 7 0 0 0 0
6 0 0 1 9 5 0 0 0
0 9 8 0 0 0 0 6 0
8 0 0 0 6 0 0 0 3
4 0 0 8 0 3 0 0 1
7 0 0 0 2 0 0 0 6
0 6 0 0 0 0 2 8 0
0 0 0 4 1 9 0 0 5
0 0 0 0 8 0 0 7 9
However, this one gives it trouble:
0 9 4 0 0 0 1 3 0
0 0 0 0 0 0 0 0 0
0 0 0 0 7 6 0 0 2
0 8 0 0 1 0 0 0 0
0 3 2 0 0 0 0 0 0
0 0 0 2 0 0 0 6 0
0 0 0 0 5 0 4 0 0
0 0 0 0 0 8 0 0 7
0 0 6 3 0 4 0 0 8
If I comment out the print statements and track the progress I can see that it starts by heading out in the wrong direction at points. Eventually it gets stuck toward the end and the backtracking never gets far back enough. I think it's something wrong with the 'checkOnlyAllowed' part...
What do you think could be the problem?
Also - I know I could've used a bitfield for the 'mAllowed' table but we don't officially know about bitwise operations yet in school. :P
At line 170 you have a goto that is jumping out of a for loop, then continuing. This could give you some weird behavior with continuing the wrong loop, behavior that might depend on the specific compiler.
Try replacing lines 164-177 with:
164 for (;;)
165 {
166 bool successfullyContributedToTheBoard = false;
167 for (int i = 0; i < 9; ++i)
168 for (int j = 0; j < 9; ++j)
169 if (!mBoard[i][j])
170 if (trySinglePoint(i, j))
171 successfullyContributedToTheBoard = true;
172 if (!successfullyContributedToTheBoard)
173 return;
174 }
I didn't look at your code but your strategy is exactly the same as the one I used to code a Sudoku solver. But I can't remember it being very slow. I got solutions in an instant. The maximum number of "guesses" the program had do make was 3 during my tests. That was for Sudoku problems which were supposed to be very hard. Three is not a big number with respect to back tracking and you can pick a cell which has only a few possibilities left (two or three) which limits the search space to about 20-30 states only (for hard Sudoku problems).
What I'm saying is, it's possible to use this strategy and solve Sudoku problems really fast. You only have to figure out how to optimize your code. Try to avoid redundant work. Try to remember things so you don't need to recalculate them again and again.
Alright, I got it working! It seems that the i, j loop within 'guess' was unecessary - ie., it should only do a guess on one empty spot because its 'child processes' will handle the rest. Fixing this actually made the code simpler. Now it works really well, and actually its very quick!
Thanks for your help, everyone. ;-)