I've been revising on my coding skills recently and then I made a program that outputs the contents of a multidimensional array. It is simple but when I experimented with the code this is what that happened:
int dv[3][3] {
{1,2,3},
{4,5,6},
{7,8,9}
};
for (auto col = dv; col != dv + 3; ++col) {
for (auto row = *dv; row != *col + 3; ++row) {
cout << *row << " ";
}
}
Output:
1 2 3 1 2 3 4 5 6 1 2 3 4 5 6 7 8 9
Can anybody please tell me why is this happening?
Why does my code outputs so ?
Your error is inside the second loop initialization : auto row = *dv;. By doing so, you systematically come back to the beginning. Then, you go to *col + 3.
Look at it this way :
First loop turn :
col = dv;
row = *dv;
Prints each number until row == *col + 3
Output : 1 2 3
Second loop turn :
col = dv + 3;
row = *dv;
Prints each number until row == *col + 3 but col is dv + 3
Output : 1 2 3 4 5 6 --> It started from the beginning (dv)
Total output with turn 1 and 2 : 1 2 3 1 2 3 4 5 6
Try this instead :
for (auto col = dv; col != dv + 3; ++col) {
for (auto row = *col; row != *col + 3; ++row) { // (1)
cout << *row << " ";
}
}
// (1) : Starting at current `column` then printing until `column + 3`
Live example : https://ideone.com/Y0MKrW
Your inner loop is starting at *dv. That is probably not what you meant to do.
Related
I am trying to traverse a 2D matrix diagonally and the function below prints all elements in a diagonal.I want to skip the first row and first column elements and start the diagonal traversal from matrix[1][1] because the values in the 0th row and 0th column are not required.So it is like slicing the matrix from the top and starting from [1][1] but not making any changes to the bottom of the matrix.
void diagonalOrder(int matrix[][COL])
{
for(int line = 1;
line <= (ROW + COL - 1);
line++)
{
int start_col = max(0, line - ROW);
int count = min(line, (COL - start_col), ROW);
/* Print elements of this line */
for(int j = 0; j < count; j++)
cout << setw(5) <<
matrix[minu(ROW, line) - j - 1][start_col + j];
cout << "\n";
}
I will update my question with an example to make it clear.Consider the following matrix.
0 1 2 3 4
matrix[5][5] = 1 8 5 3 1
2 4 5 7 1
3 6 4 3 2
4 3 4 5 6
The above function will print the values of this diagonally.
Output:
0
1 1
2 8 2
3 4 5 3
4 6 5 3 4
3 4 7 1
4 3 1
5 2
6
I want to skip the elements of the first row and the first column and starting at matrix[1][1] want to traverse the matrix diagonally.
Desired Output:
8
4 5
6 5 3
3 4 7 1
4 3 1
5 2
6
From your example it looks like you want to print antidiagonals not diagonals, ie third line is 3 4 5 3 not 3 5 4 3.
To get started keep things simple: Indices (i,j) along an antidiagonal are those i and j where i+j == some_constant. Hence this is a simple (not efficient) way to print elements along one antidiagonal:
void print_antidiagonal(int matrix[5][5],int x){
for (int i=4;i >= 0; --i) {
for (int j=0;j < 5; ++j) {
if (i+j == x) std::cout << matrix[i][j] << " ";
}
}
std::cout << "\n";
}
Further there are nrows + (ncols-1) antidiagonals, hence you can print them all via:
for (int i=0;i < 5+4; ++i) {
print_antidiagonal(matrix,i);
}
The function above isnt very efficient, but it is simple. It is obvious how to skip the first row and first column:
for (int i=4;i >= 1; --i) { // loop till 1 instead of 0
for (int j=1;j < 5; ++j) { // loop from 1 instead of 0
This is sufficient to produce desired output (https://godbolt.org/z/7KWjb7qh7). However, not only is the above rather inefficient, but also the code is not very clear about its intent. print_antidiagonal prints elements along a single anti-diagonal, hence iterating all matrix elements is a bad surprise.
I suggest to print the indices rather than the matrix elements to get a better picture of the pattern (https://godbolt.org/z/TnrbbY4jM):
1,1
2,1 1,2
3,1 2,2 1,3
4,1 3,2 2,3 1,4
4,2 3,3 2,4
4,3 3,4
4,4
Again, in each line i+j is a constant. And that constant increments by 1 in each line. In each line i decrements while j increments, until either i == 1 or j==4. The first element is such that i is maximum and j = constant - i.
Hence:
void print_antidiagonal(int matrix[5][5],int x){
int i = std::min(x-1,4);
int j = x - i;
while (i >= 1 && j <= 4) {
std::cout << matrix[i][j] << " ";
--i;
++j;
}
std::cout << "\n";
}
Live Example.
PS: I used hardcoded indices, because I considered it simpler to follow the logic. For a more realistic solution the matrix size and offset should be parametrized of course.
I don't really get what your code is trying to do but just going by the description you need to iterate over the array items with equal row and column indices until there either are no more rows or no more columns i.e.
void print_tail_of_diagonal(int matrix[ROWS][COLS])
{
int n = std::min(ROWS, COLS);
for (int i = 1; i < n; ++i) {
std::cout << matrix[i][i] << " ";
}
std::cout << "\n";
}
void vectorDeduplicator(std::vector<std::string>& inputVector){
for(int i = 0; i < inputVector.size() - 1; i++){
for(int x = 1; x <= inputVector.size() - 1; x++)
if(inputVector.at(i) == inputVector.at(x) && i != x){
inputVector.erase(inputVector.begin() + x);
}
}
}
Input: 1 1 2 2 4 4 3 3 1 1 3 3 3 2 2
Output: [1,2,4,1,3,2]
You can see the function I'm trying to use to remove duplicates inside of a vector. It works when duplicates are adjacent. I wouldn't like to use a faster and an efficient method without knowing anything about it that already exists within the standard library or anything else. I'd like to learn the algorithm behind it as this is for learning purposes.
The problem is you ignore one value as you erase. You need to decrement x:
#include <vector>
#include <iostream>
void vectorDeduplicator(std::vector<int>& inputVector)
{
for(int i = 0; i < inputVector.size() - 1; i++)
{
for(int x = 1; x < inputVector.size(); x++)
{
if(inputVector.at(i) == inputVector.at(x) && i != x)
{
inputVector.erase(inputVector.begin() + x);
x--; // go one back because you erased one value
}
}
// to debug
for(const auto& x : inputVector)
std::cout << x << " ";
std::cout << std::endl;
}
}
int main(){
std::vector<int> vector{1, 1, 2, 2, 4, 4, 3, 3, 1, 1, 3, 3, 3, 2, 2};
vectorDeduplicator(vector);
// output
for(const auto& x : vector)
std::cout << x << " ";
return 0;
}
The output then is:
1 2 2 4 4 3 3 3 3 3 2 2
1 2 4 4 3 3 3 3 3
1 2 4 3 3 3 3 3
1 2 4 3
1 2 4 3
I have created a 2-D array with random integers stored in each location. My question is that I want to compare each row element with the next two and also each column element with the next two so that no same number is generated 3 times consecutively either in a row or column.
Eg: the array should ideally be like=
1 1 2 3 0 2 4 4
3 2 2 1 0 2 1 1
0 0 5 2 0 4 3 2 //no 3 same in rows or columns..
And no something like:
1 1 2 3 0 4 4 4
3 2 2 1 0 2 1 1
0 0 2 2 0 4 3 2
I have written my code which compares the rows of the array first and changes the values if there are any same and then after the rows are done it checks the columns. Now my code works sometimes and sometimes it doesn't. Can anyone tell me where I'm going wrong? Here is my code:
int array_1[10][15] = { { 0 } }; //creates a new 2-D array with zeros.
for (int row = 0; row<10; row += 1) //puts random values in array in range 0 to 5
{
for (int col = 0; col <15; col += 1)
{
array_1[row][col] = rand() % 6;
}
}
for (int row = 0; row <8; row++)
{
for (int col = 0; col <13; col++)
{
if (array_1[col][row] == array_1[col][row + 1] && array_1[col][row]== array_1[col][row + 2]) // checks each row for 3 consecutive
{
array_1[col+1][row] = rand()%6;
}
if (array_1[col+1][row] == array_1[col + 1][row] && array_1[col][row] == array_1[col + 1][row]) // checks each column for 3 consecutive
{
array_1[col][row] = rand()%6;
}
}
}
And please don't use any inbuilt functions from c++, I am trying to do this with only logical and comparison statements.
Your indexing in the nested loop is wrong. When you do array_1[col][row] you will go out of bounds when col becomes equal or larger than 10. That of course leads to undefined behavior.
I suspect you mean array_1[row][col] (like in the initialization loop).
I feel you should split your logic into two parts for simplicity and better checking. 1st part for verifying rows and 2nd for verifying columns.
Also in your code, you need take care that rand()%6 should not generate same no. again. I have also written logic for the same.
You can check following code.
// Loop for row
for(row=0;row<8;row++)
{
for(col=0;col<13;col++)
{
if(array_1[row][col] && array_1[row][col+1] && array_1[row][col+2] )
{
// Make sure that rand()%6 should not generate same number
while(array_1[row][col+1] == array_1[row][col+2])
{
array_1[row][col+1] = rand()%6;
}
}
}
}
//Loop for column
for(col=0;col<13;col++)
{
for(row=0;row<8;row++)
{
if(array_1[row][col] && array_1[row+1][col] && array_1[row+2][col] )
{
// Make sure that rand()%6 should not generate same number
while((array_1[row+1][col] == array_1[row+2][col]) && (array_1[row+1][col] == array_1[row+1][col+1]))
{
array_1[row+1][col] = rand()%6;
}
}
}
}
Here is my solution to create a 2D array without any value repeating 3 times consecutively either in a row or in a column.
#include <iostream>
#include <string>
#include <time.h>
int main()
{
srand(time(NULL));
int array_1[10][15] = { { 0 } }; //creates a new 2-D array with zeros.
for (int row = 0; row < 10; row++) //puts random values in array in range 0 to 5
{
for (int col = 0; col < 15; col++)
{
array_1[row][col] = rand() % 6;
if (col > 1 && array_1[row][col - 1] == array_1[row][col - 2])
{
while (array_1[row][col] == array_1[row][col - 1])
{
array_1[row][col] = rand() % 6;
}
}
if (row > 1 && array_1[row - 1][col] == array_1[row - 2][col])
{
while ((array_1[row][col] == array_1[row - 1][col]) ||
(array_1[row][col] == array_1[row][col - 1] && array_1[row][col - 1] == array_1[row][col - 2]))
{
array_1[row][col] = rand() % 6;
}
}
std::cout << array_1[row][col] << " ";
}
std::cout << std::endl;
}
return 0;
}
"Number pong" is what I am trying to do. Ex:
0 1 2 3 4 5 4 3 2 1 0 1 2 3 4 5 4 etc
I have tried several different things, incrementing one number, modal operators. I could not figure this out, and I could not figure out correct search words.
So:
int offset = 0;
int number = 0;
while(true) {
offset++;
number = offset%5; // idea 1
number = (offset%5)-5 // idea 2
number = (offset/5)%5 // idea 3
number = 5 - (offset%5) // idea 4
}
None of those work, obviously. I get patterns like 0 1 2 3 4 5 0 1 2 3 4 5 or just continuous numbers.
I would wrap this in an if(offset % 10 <= 5) { ... } else { ... } and use your existing ideas.
Regardless you're going to want to work % 10 since that's how long your cycle is.
Hint These sequences are very closely related:
0 1 2 3 4 5 4 3 2 1 0 1 2 3 4 5 4 ...
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 ...
#include <iostream>
int main()
{
int i = 0;
bool plus = true;
while(true) {
std::cout << i << std::endl;
if (plus) i++; else i--;
if (i == 5 || i == 0) plus = !plus;
}
}
Is there a requirement to generate the numbers in a single statement with variables and operators?
If not, then use an bool variable which switches its value (true means increasing, false means decreasing) from true to false and vice versa.
i.e.
int start = 0 ;
bool which_way = true ;
int loop_times = 100 ;
while(--loop_times) {
std::cout << start ;
start += which_way ? 1 : -1 ;
if(start % 5 == 0)
which_way = !which_way ;
}
Here is a crazy way of outputting the number pong (with set limit)
#include <stdio.h>
int main()
{
bool bFlip = false; //Decides if number will increase or decrease
int nLimit = 5; //How far up the number will count.
//Start at 0, keep going as long as number never reaches past the limit
//And increase/decrease depending on bFlip
for(int nNum = 0; nNum <= nLimit; (bFlip ? nNum++ : nNum--))
{
printf("%d ", nNum);
//When number reaches either end, do a barrel roll!
if (nNum % nLimit == 0)
{
bFlip = !bFlip;
}
}
return 0;
}
Be warned that this loop will go on forever so if you are going to go with this approach then you will need to set a limit on how many numbers you want to display.
Yet another crack at generating the sequence you're after:
#include <iostream>
#include <list>
#include <iterator>
int main() {
std::list<int> nums = {{0, 1, 2, 3, 4, 5}};
auto begin = nums.begin();
auto iterator = nums.begin();
auto end = nums.end();
auto loop_times = 100;
while (--loop_times) {
while (iterator != end) {
std::cout << *iterator++;
}
iterator--;
while (iterator != begin) {
std::cout<< *--iterator;
}
iterator++;
}
}
Thanks for the tips. I got it working with a single statement.
int count = 0;
int num = 0;
int out = 0;
while (count++ < 100) {
cout << abs( (num%10) - 5 ) << endl;
num++;
}
// Output: 5 4 3 2 1 0 1 2 3 4 5 4 etc
I'd probably do something like this:
// If you want in the range -val to val
//#define PONG(val, i) (abs(val%(i*4)-i*2) - i)
// If you want the range 0 to val
#define PONG(val, i) (abs(val%(i*2)-i))
int main() {
for(int i = 0; i < 100; i++) {
cout << PONG(i, 5) << endl;
}
}
Prints:
5 4 3 2 1 0 1 2 3 4 5 4 3 2 1 0 1 2 ...
I have implemented the first part of this problem but failed to achieve the second part. What I'm trying to do is that I have two vectors
std::vector<double> A = {1,1,2,2};
std::vector<double> B = {3,3,4,4,5,5};
I have to go through two loops and make subtraction of two math vectors. For example,
For the first iteration:
C = [1;1] (Note: the first two elements of A vector)
Because C is 2x1, I have to construct from B three math vectors of the same size, therefore the output for the first iteration is
1 - 3
1 - 3
------
1 - 4
1 - 4
------
1 - 5
1 - 5
For the second iteration, the C matrix is expanded by two elements per iteration , therefore the new C matrix is C = [1;1;2;2]. Now we need to make the subtraction again, the output for the second iteration is
1 - 3
1 - 3
2 - 4
2 - 4
------
1 - 4
1 - 4
2 - 5
2 - 5
------
1 - 5
1 - 5
2 - 3
2 - 3
As you can see, the second math vector is shifted by two elements where the first math vector remains as it is.
A and B matrices have this assumption size % 2 = 0 where 2 is the size of C matrix.
Replicating your ouput, for first iteration you would have:
std::vector<double> A = {1,1,2,2};
std::vector<double> B = {3,3,4,4,5,5};
std::vector<double> C (A.begin(), A.begin()+2);
// bg - index of group of 2 elements in B
for (int bg = 0; bg < 3; ++bg) {
for (int ci = 0; ci < int(C.size()); ++ci) {
// bi - index of element in B
int bi = (2*bg + ci) % int(B.size());
std::cout << C[ci] << " - " << B[bi] << std::endl;
}
std::cout << "------" << std::endl;
}
For second iteration you would have to change one line:
// line changed...
std::vector<double> C (a.begin(), a.begin()+4);
Edit: OK, here's more general form that outputs both cases you specified for the change of iteration counter it. Hope it works when you extend the vectors.
for (int it = 1; it <= int(A.size())/2; ++it) {
std::vector<double> C (A.begin(), A.begin()+it*2);
// bg - index of group of 2 elements in B
for (int bg = 0; bg < int(B.size())/2; ++bg) {
for (int ci = 0; ci < int(C.size()); ++ci) {
// bi - index of element in B
int bi = (2*bg + ci) % int(B.size());
std::cout << C[ci] << " - " << B[bi] << std::endl;
}
std::cout << "------" << std::endl;
}
std::cout << std::endl;
}