How to loop over pairs and odds in the same loop?

Hey,

I question comes in mind is there any option to write a loop (for, while, do while)
that allows looping over pairs then impairs

something like this
1
2
3
4
5
6
for( ...)
  cout << i<< endl;

std output:
0 2 4 6 8 
1 3 5 7 9 
Last edited on
There's something ugly like this.

1
2
3
4
5
6
7
8
9
10
11
    bool looped = false;
    for (int i = 0; i < 10; i+=2)
    {
        std::cout << i << '\n';
        
        if (!looped && (  i==limit - 2 || i == limit-1))
        {
            i = -1;
            looped = true;
        }
    }
Last edited on
@Repeater

What is limit? It is undefined here.
you can load up a container with the values you want to loop over and do a range-based for loop. This is extra useful when there is no simple pattern to the values, eg 2 digit pairs of pi (31 41 59 ...)

or you can use a pattern if one exists to control a loop variable.

if you need to deal with pairs you can do that too, there is a pair container for that.

can you describe exactly what you want to DO here? We can make that output print a dozen ways, but if you need to do something with values in some way, we need a better understanding.
Last edited on
What is limit? It is undefined here.

See if you can guess, based on the context at hand.
Repeater, yeah but then why hardcode the 10 then?

Anyway, here's my attempt.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// Example program
#include <iostream>

int unit_step(int n)
{
    return (n >= 0) ? 1 : 0;   
}

void print_sequence(int start, int end, int N)
{
    constexpr static auto u = unit_step;
    
    int offset = (N-1)/2 + 1;
    for (int n = start; n < end; n++)
    {
        std::cout << 2 * n * u(n) - (N-1) * u(n - offset) << "\t";
    }
    std::cout << "\n";
}

int main()
{    
    int N = 10;
    int cutoff = N;
    
    N = N + N % 2;

    print_sequence(0,   N/2,    N);
    print_sequence(N/2, cutoff, N);
}


Example output, N = 10
0	2	4	6	8	
1	3	5	7	9	


Example output, N = 11
0	2	4	6	8	10	
1	3	5	7	9	 
Last edited on
Repeater, yeah but then why hardcode the 10 then?


Who knows. I expect I just threw down some code as an example. If you'd like to change it, please go ahead.
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
using namespace std;
int main ()
{
   const int limit = 10;
   stringstream ss[2];
   for( int i = 0, line = 0; i < limit; i++, line = 1 - line ) ss[line] << setw( 3 ) << i;
   cout << ss[0].str() << '\n' << ss[1].str() << '\n';
}
Ooh, alternating the line printed between 0 and 1, very succinct.
@lastchance, You can get rid of line and just use ss[i % 2]
In this instance, yes. But i might not always be running between 0 and 9.
Whatever.
I think the answers show that the cleanest solution is two loops.
1
2
3
4
for (size_t i=0; i<10; i+=2)  cout << i << ' ';
cout << '\n';
for (size_t i=1; i<10; i+=2)  cout << i << ' ';
cout << '\n';


If you're really pressed for space, you could put it in a function:
1
2
3
4
5
6
7
8
9
10
11
void printEveryOther(unsigned from, unsigned 10)
{
    for (size_t i=from; i<to; i+=2)  cout << i << ' ';
    cout << '\n';
}

int main()
{
    printEveryOther(0, 10);
    printEveryOther(1, 10);
}

Why not this?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>

using namespace std;


int main() {

	int a = 12;

	for (int i = 0; i <= a; i += 2) {
		cout << i << "\t";
	}

	cout << endl;

	for (int i = 1; i <= a; i += 2) {
		cout << i << "\t";
	}
	

	
	cin.get();
	
	return 0;
}
That's way too deconvoluted! :)
Last edited on
it's definitely unusual to iterate over every other index but still care about the indices skipped.

Thus, as lastchance wrote, some form of storage is required. You could output the evens as you go (since this is the first line), storing just the odds, but take care on choosing your starting and ending points. A few ways to do that; for example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <sstream>

using namespace std;

int main() 
{
    const int limit = 10;
    ostringstream oss;
    cout << "0 ";
    for (int i=2; i<=limit; i+=2)
    {
        cout << i << ' ';
        oss << (i-1) << ' ';
    }
    cout << '\n' << oss.str() << '\n';

    return 0;
}

0 2 4 6 8 10 
1 3 5 7 9 
Last edited on
Hey, I could obfuscate with the best of em'. Don't push me. :P
Besides, here is the same in a single loop.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>

using namespace std;


int main() {

	int a = 12;

	for (int i = 0; i <= a; i += 2) {
		cout << i << "\t";
		if (i + 2 > a && i % 2 == 0) {
			i = -1;
			cout << endl;
		}
	}


	
	cin.get();
	
	return 0;
}
manga wrote:
Hey, I could obfuscate with the best of em'. Don't push me. :P

I'm working on it ...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <iomanip>
using namespace std;

void output( int imin, int imax, int di, int nlines, int i, int line )
{
   if ( i > imax ) { line++;   cout << '\n';   i = imin + line * di; }
   if ( line == nlines ) return;
   cout << setw( 4 ) << i;
   output( imin, imax, di, nlines, i + nlines * di, line );
}


int main()
{
   output( 0, 11, 1, 2, 0, 0 );
}
   0   2   4   6   8  10
   1   3   5   7   9  11
@lastchance

I smell a bit of recursion in that one... nice. :)

Just remember to use function calls in your argument list.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <iomanip>
using namespace std;

void output(int imin, int imax, int di, int nlines, int i, int line)
{
	if (i > imax) { line++;   cout << '\n';   i = imin + line * di; }
	if (line == nlines) return;
	cout << setw(4) << i;
	output(imin, imax, di, nlines, i + nlines * di, line);
}

int fluxCap(int x) {
	x > 0 ? x = x - x: x = 0;
	return x;
}


int main()
{
	output(fluxCap(3), abs(-10 - 1), sizeof(true), sizeof(short), fluxCap(-1), fluxCap(18));
}
Last edited on
Topic archived. No new replies allowed.