What kind of loop to use? How to limit terms on a line?

This is a program testing Ulam's Algorithm that says any positive integer would always reduce to 1 if the following algorithm was repeated a sufficient number of times:
- If the number is even, divide it by 2
- If the number is odd, multiply it by 3 and then add 1

I need to display all the numbers of each series with a maximum of 10 numbers per line. I have a couple question.

1. What kind of loop should I use for the math?
2. How do I tell the program to display only 10 terms per line?


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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <iostream>
#include <cmath>
#include <iomanip>
#include <cctype>
using namespace std;

const string GET_FIRST = "Enter the first number to test: ";
const string GET_SECOND = "Enter the last number to test: ";
const string GET_INC = "Enter the increment for testing values: ";
const string INVALID1 = "Invalid -- must be between 1 and 1000. Try again: ";
const string INVALID2 = "Invalid -- must be greater than first number. Try again: ";
const string INVALID3 = "Invalid -- must be at least 1, but not larger than the second number. Try again: ";

void testTheory(int& firstNum, int lastNumber1, int inc);
int getIncrement(int firstNumber, int lastNumber);
void readNumbers(int& firstNum, int& lastNum);
int main()
{
	int firstNum;
	int secondNum;
	int userInc;
	
	cout << "Program will test Ulam's algorithm" << endl << endl;
	readNumbers(firstNum, secondNum);
	userInc = getIncrement(firstNum, secondNum);
	testTheory(firstNum, secondNum, userInc);

 cout << endl << endl;
 system ("PAUSE");
 
 return 0;
}

void readNumbers(int& firstNum, int& lastNum)
{
	cout << GET_FIRST;
	cin >> firstNum;
	cout << endl << endl;
	
	while((firstNum < 1) || (firstNum > 1000))
	{
		cout << INVALID1;
		cin >> firstNum;
		cout << endl << endl;
	}
	
	cout << GET_SECOND;
	cin >> lastNum;
	cout << endl << endl;
	
	while (lastNum < firstNum)
	{
		cout << INVALID2;
		cin >> lastNum;
		cout << endl << endl;
	}
}	

int getIncrement(int firstNumber, int lastNumber)
{
	int increment;
	
	if((lastNumber == firstNumber) || (lastNumber - firstNumber == 1))
	{
		increment = 1;
	}
	else
	{
		cout << GET_INC;
		cin >> increment;
		cout << endl << endl;
	}
	while(increment < 1)
	{
		cout << INVALID3;
		cin >> increment;
		cout << endl << endl;
	}
	return increment;
}

void testTheory(int& firstNum, int lastNumber1, int inc)
{
	int seriesNum;
	int incAddition;
	
	seriesNum = firstNum;
	incAddition = inc;
	
	do
	{
		if(firstNum % 2 == 0)
		{
			firstNum = (firstNum / 2);
		}
		else if(firstNum % 2 != 0)
		{
			firstNum = ((firstNum * 3) + 1);
		}
		while(firstNum > 1)
		{
			cout << setw(7) << firstNum << endl;
		}
		
		incAddition = seriesNum + inc;
	} 
	while(incAddition < inc);
}
Hi,

First of all, based on your explanation of Ulam's algorithm, I don't understand why you need to ask for 2 numbers (first and last). Aren't you using the algorithm for just one number?

I also don't understand what is the "increment for testing values".
All I know is that Ulam's algorithm reduces a number to 1 in x number of iterations.

For this algorithm, do-while or while loop would be easier and more convenient.

One more thing,
You have an infinite loop at line 100.
It checks if firstNum is > 1 and if it is true then it displays that number infinitely.

Since I don't understand your goal in this program, I can't tell you how to fix it.
Sorry for not being clear.. The increment increases the first value, and the second number is how high to allow the loop to increment. Here is a sample input/output.

Program will test Ulam's algorithm

Enter the first number to test: 100

Enter the last number to test: 500

Enter the increment for testing values: 200

//ALL OF THESE SHOULD BE SETW(7) AND ONLY 10 TERMS PER LINE.

Series generated for 100
100 50 25 76 38 19 58 29 88 44
22 11 34 17 52 26 13 40 20 10
5 16 8 4 2 1

Total number of terms: 26

Series generated for 300

300 150 75 226 113 340 170 85 256 128
64 32 16 8 4 2 1

Total number of terms: 17

Series generated for 500
500 250 125 376 188 94 47 142 71 214
107 322 161 484 242 121 364 182 91 274
137 412 206 103 310 155 466 233 700 350
175 526 263 790 395 1186 593 1780 890 445
1336 668 334 167 502 251 754 377 1132 566
283 850 425 1276 638 319 958 479 1438 719
2158 1079 3238 1619 4858 2429 7288 3644 1822 911
2734 1367 4102 2051 6154 3077 9232 4616 2308 1154
577 1732 866 433 1300 650 325 976 488 244
122 61 184 92 46 23 70 35 106 53
160 80 40 20 10 5 16 8 4 2
1

Total number of terms: 111

So it starts with 100, which is the first number input, increments by 200 which is the increment value input, and does that until the series increments to 500.
A while loop may be best suited to this.

To output 10 values/line you can either store all values in a vector, then iterate through the vector, printing 10 items, then a new line. Or if you want to print the numbers as you are executing your program you could have a counter that increments each time you write a value, when it gets to 10 put a new line and reset it.
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <iostream>
#include <cmath>
#include <iomanip>
#include <cctype>
using namespace std;

const string GET_FIRST = "Enter the first number to test: ";
const string GET_SECOND = "Enter the last number to test: ";
const string GET_INC = "Enter the increment for testing values: ";
const string INVALID1 = "Invalid -- must be between 1 and 1000. Try again: ";
const string INVALID2 = "Invalid -- must be greater than first number. Try again: ";
const string INVALID3 = "Invalid -- must be at least 1, but not larger than the second number. Try again: ";

void testTheory(int& firstNum);
int getIncrement(int firstNumber, int lastNumber);
void readNumbers(int& firstNum, int& lastNum);
int main()
{
	int firstNum;
	int secondNum;
	int userInc;
	
	cout << "Program will test Ulam's algorithm" << endl << endl;
	readNumbers(firstNum, secondNum);
	userInc = getIncrement(firstNum, secondNum);
    for (int i = firstNum; i <= secondNum; i = i + userInc){
	testTheory(i);
	cout << endl << endl << endl;
}
 cout << endl << endl;
 system ("PAUSE");
 
 return 0;
}

void readNumbers(int& firstNum, int& lastNum)
{
	cout << GET_FIRST;
	cin >> firstNum;
	cout << endl << endl;
	
	while((firstNum < 1) || (firstNum > 1000))
	{
		cout << INVALID1;
		cin >> firstNum;
		cout << endl << endl;
	}
	
	cout << GET_SECOND;
	cin >> lastNum;
	cout << endl << endl;
	
	while (lastNum < firstNum)
	{
		cout << INVALID2;
		cin >> lastNum;
		cout << endl << endl;
	}
}	

int getIncrement(int firstNumber, int lastNumber)
{
	int increment;
	
	if((lastNumber == firstNumber) || (lastNumber - firstNumber == 1))
	{
		increment = 1;
	}
	else
	{
		cout << GET_INC;
		cin >> increment;
		cout << endl << endl;
	}
	while(increment < 1)
	{
		cout << INVALID3;
		cin >> increment;
		cout << endl << endl;
	}
	return increment;
}

void testTheory(int& firstNum)
{
    int tempNum = firstNum;
    int counter  = 0;
	cout << setw(7) << firstNum << "  ";
	do
	{
		if(firstNum % 2 == 0)
		{
			firstNum = (firstNum / 2);
		}
		else if(firstNum % 2 != 0)
		{
			firstNum = ((firstNum * 3) + 1);
		}
		
		cout << firstNum << "  ";
		counter++;
	    if (counter == 10 || counter == 20 || counter == 30) {cout << "\n" << setw(7);}
	} 
	while(firstNum > 1);
	cout << endl;
	cout << endl << " Counts: " << counter << endl;
	firstNum = tempNum;
}


I made some changes in your testTheory function and you main in which you were calling your functions.

Hope this helps!
You guys are the best! Thank you newbiee999 and blatantlyx for the help!
if (counter == 10 || counter == 20 || counter == 30) { ...

What about?

if (0 == (counter % 10)) { ...

i.e. if counter is a multiple of 10

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

int main() {
    for(int counter = 1; counter <= 100; ++counter) {
        if (counter == 10 || counter == 20 || counter == 30) {
            cout << counter << " => counter = 10 or 20 or 30\n";
        }
        if (0 == (counter % 10)) {
            cout << counter << " => 0 = counter % 10\n";
        }
    }
    return 0;
}


10 => counter = 10 or 20 or 30
10 => 0 = counter % 10
20 => counter = 10 or 20 or 30
20 => 0 = counter % 10
30 => counter = 10 or 20 or 30
30 => 0 = counter % 10
40 => 0 = counter % 10
50 => 0 = counter % 10
60 => 0 = counter % 10
70 => 0 = counter % 10
80 => 0 = counter % 10
90 => 0 = counter % 10
100 => 0 = counter % 10


Andy
Last edited on
Hi Andy!
That's a good idea.
I knew checking for counter == 10, 20, and 30 is not the right way but I just couldn't think of a better way of doing this.
Last edited on
Topic archived. No new replies allowed.