bool and vector functions help

Pages: 12
A user should be able to input a 4-digit number that satisfies the following:
--each digit is unique
--the tens place is three times the thousands place
--an odd number
--the sum of each digit is 27

the different_number(int number) function is a bit wonky.
sometimes when I enter 1231, the program accepts instead of giving an error message

I also want to use the vector function if it's a better way. Maybe I can use it in different_numbers, three_times, and sum_number

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
109
110
111
112
113

#include <iostream>
#include <cmath>
#include <string>
#include <vector>

using namespace std;

void Ch3_Programming_Project_13();

vector<int> separate_number(int number);

bool different_numbers(int number);
bool three_times(int number);
bool odd_number(int number);
int sum_number(int number);
int inputInteger(string prompt, int startRange, int endRange);

int main(){
    Ch3_Programming_Project_13();
    return 0;
}
  
void Ch3_Programming_Project_13(){
    // correct answer is 9738 || 9837

    int address_number = inputInteger("Guess an address number: ", 1000,9999);

    while (!different_numbers(address_number) || !three_times(address_number) || !odd_number(address_number) || sum_number(address_number) != 27){
        cout << "Sum of the guess: " << sum_number(address_number) << endl << endl;

        // just to check
        if (!different_numbers(address_number)) 
            cout << "Each digit must be unique" << endl;
        if (!three_times(address_number))
            cout << address_number << " != tens*3==thousands" << endl;
        if(!odd_number(address_number)) 
            cout << address_number << " != odd number" << endl;
        if (sum_number(address_number) != 27) 
            cout << "Sum of the guess must be 27" << endl << endl;

        cout << "Incorrect guess." << endl << endl;
        address_number = inputInteger("Guess an address number: ", 1000,9999);
    }
    
    cout << "Sum of the guess: " << sum_number(address_number) << endl;
    cout << "The correct address number: " << address_number << endl;
}

// this could be used for different_numbers, three_times, and sum_number
vector<int> separate_number(int number){
    vector<int> temp_arr;
    temp_arr[0] = (number / 100) % 10; // ones
    temp_arr[1] = (number / 10) % 10;  // tens
    temp_arr[2] = number % 10;         // hundreds
    temp_arr[3] = number / 1000;       // thousands

    return temp_arr;
}

// different_numbers is a bit wonky.
bool different_numbers(int number){
    int temp_arr[4];
    temp_arr[0] = (number / 100) % 10; // ones
    temp_arr[1] = (number / 10) % 10;  // tens
    temp_arr[2] = number % 10;         // hundreds
    temp_arr[3] = number / 1000;       // thousands

    return temp_arr[0] != temp_arr[1] != temp_arr[2] != temp_arr[3];
}

bool three_times(int number){
    // find thousands place
    int thousands = number / 1000;
    // find tens place
    int tens = (number / 10) % 10;

    return tens*3==thousands;
}

bool odd_number(int number){
    return number%2==0;
}

int sum_number(int number) {
	int sum_number = 0;
	while (number > 0) {
		sum_number += number % 10;
		number /= 10;
	}
    
	return sum_number;
}

int inputInteger(string prompt, int startRange, int endRange) {

    int input;
    do {
        cout << prompt;
        if (!(cin >> input)) {
            cout << "ERROR-3A: Invalid input. Must be an integer type.\n";
            cin.clear();
            cin.ignore(999, '\n');
        }
        else if (!(input >= min(startRange, endRange) && input <= max(startRange, endRange)))
            cout << "ERROR-3A: Invalid input. Must be from " << startRange << "..." << endRange << ".\n";
        else
            break;
    } while (true);
    return input;
}

Last edited on
I am not sure line 69 does what you think it does.
Its late and I get mixed up on the rules for weird expression evaluations, but if its not working, try writing it another way.

yes, you can split the number one time and reuse that work. I am not sure ones tens hundreds and thousands are all exactly right, though.
ones is x %10
... you have them out of order.
Last edited on
@jonnin thank you for your response.

Thank you for pointing out that the digit separation was a bit off.

I've changed the line 69 into the following:
1
2
3
4
5
6
return temp_arr[0] != temp_arr[1] || 
           temp_arr[0] != temp_arr[2] || 
           temp_arr[0] != temp_arr[3] ||
           temp_arr[1] != temp_arr[2] ||
           temp_arr[1] != temp_arr[2] ||
           temp_arr[2] != temp_arr[3];

^I've also tried other variations. it's not working.

I also just realized that my odd_number function is incorrect. I changed the return to:
 
return number%2!=0;


Let's say I want to split the number once and just reuse the work, how do I go about that? I've tried the following, but i got an error:
 
for(auto i : separate_number(address_number)) cout << i << " " ;
Last edited on
FWIW: Obviously not yours but I had a play around with this. According to this there is only one number that satisfies all the conditions.

Substituting C-arrays for <vector>'s is very easy.

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
#include <iostream>

int main()
{
    const int NO_OF_DIGITS{4};
    int digits[NO_OF_DIGITS];
    
    int digit;
    bool acceptable_number = false;
    
    int sum_of_digits{0};
    
    int checker[10];
    
    while(std::cout << "Enter 4 digit number: " && acceptable_number == false)
    {
        std::cin >> digit;
        
        acceptable_number = true;
        if(digit < 1000 or digit > 9999 )
        {
            acceptable_number = false;
            std::cout << "Not a 4-digit number\n";
        }
        
        for(int i = 0; i < 10; i++)
        checker[i] = -1;
        
        sum_of_digits = 0;
        for(int i = 0; i < NO_OF_DIGITS; i++)
        {
            digits[i] = digit % 10;
            
            sum_of_digits += digits[i];
            
            if(checker[digits[i]] >= -1)
                checker[ digits[i] ] = -74;
            else
            {
                acceptable_number = false;
                std::cout << "Digits duplicated\n";
            }
            
            digit /= 10;
        }
        
        // DISPLAY DIGITS
        for(int i = NO_OF_DIGITS - 1; i >= 0; i--)
        std::cout << digits[i] << ' ';
        
        if(digits[1] != 3*digits[3])
        {
            acceptable_number = false;
            std::cout << "10's != 3*1000's\n";
        }
        
        if(digits[0] % 2 == 0)
        {
            acceptable_number = false;
            std::cout << "Not an oddnumber\n";
        }
        
        if(sum_of_digits != 27)
        {
            acceptable_number = false;
            std::cout << "Digit sum != 27\n";
        }
        
        if(acceptable_number == true)
            std::cout << "Number accepted\n";
        else
            std::cout << "Number rejected ... Try again\n";
    }
    
    return 0;
}
--the tens place is three times the thousands place



From the given 2 correct answers (9738 || 9837), do you mean the thousands place is three times the tens place (9 is 3x 3)?
1
2
3
4
5
6
7
8
9
#include <iostream>
using namespace std;

int main()
{
   int n;
   cout << "Enter a four-digit number: ";   cin >> n;
   cout << ( n == 3897 ? "Yes" : "No" );
}


It would be a lot more interesting if there were 5 digits.
Last edited on
--the tens place is three times the thousands place

9738 isn't allowed because it's an even number, so 9837 is the sole answer with that way of looking at the '3 times' test.

The alternative, which my interpretation codes, gives the sole answer of 3897.
( tens_place = 3 * thousands_place, ie 3897 ie 9 = 3*3 )
It definitely would be more fun with 5 (or more) digits!
cout << ( n == 3897 ? "Yes" : "No" ); How cruel is that for a one-liner? :)
Fulfillls the requirement for testing the entered number! :)
To return to the original OP post:

return temp_arr[0] != temp_arr[1] != temp_arr[2] != temp_arr[3];
I can't actually work out what that will return ... but it definitely isn't right!

I suspect the quickest way would just be to construct a set (hence, no duplicates) and check that its size was 4. Something like
return set<int>( temp_arr, temp_arr+4 ).size() == 4;
Alternatively, keep a bool or int array (as @againtry's code) to tick off the digits already used.
Last edited on
I tried it and there is nothing useful.
IIRC the word is transitive and the string of != 's doesn't make it. set's solve that.
BTW I tried 5 digit numbers under the same rules and there were no acceptable numbers which is a surprise.
5-digit ones (I think!)
83691
63891
83295
63495
43695
23895
63297
23697
92763
72963
32967
92367
42867
82467
32769
72369
61839
81639
Might be some more. These were done by hand.
For an alternative 'take':

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
#include <iostream>
#include <cctype>
#include <iterator>

int main()
{
	enum errs {OK = 0, DUPDIG, TOOFEW, TOOMANY, NOTNUM, BADNUM, NOTODD, BADTENS};
	const char* errmsg[] {"OK!", "Duplicate digit", "Too few digits", "Too many digits", "Not a number", "Incorrect digit sum", "Not an odd number", "Tens not 3 times thousands"};
	constexpr size_t nodigits {4};
	constexpr size_t total {27};

	char ch {};
	int digits[nodigits] {};
	size_t sum {}, nod {};
	int err {OK};

	static_assert (BADTENS == std::size(errmsg) - 1);

	std::cout << "Enter number to check: ";

	for (bool dup[10] {}; !err && (ch = std::cin.get()) != '\n' && nod < nodigits && std::isdigit(ch); dup[digits[nod++]] = true) {
		sum+= (digits[nod] = ch - '0');
		err = dup[digits[nod]] == true;
	}

        err += (!err && ch == '\n' && nod < nodigits) * TOOFEW;
	err += (!err && std::isdigit(ch) && nod == nodigits) * TOOMANY;
	err += (!err && (ch != '\n' || nod != nodigits)) * NOTNUM;
	err += (!err && sum != total) * BADNUM;
	err += (!err && digits[nodigits - 1] % 2 == 0) * NOTODD;
	err += (!err && digits[nodigits - 4] != 3 * digits[nodigits - 2]) * BADTENS;

	std::cout << errmsg[err] << '\n';
}

Last edited on
I found my blooper, the limits weren't reset to extend to 5 digits .


23697
23895
32769
32967
42867
43695
61839
63297
63495
63891
72369
72963
81639
82467
83097
83295
83691
92367
92763
Program ended with exit code: 0
The error messages beat spag-code. try-catch exceptions would be the pinnacle.

Maybe 4-digit numbers are the only ones that give a single answer - 3, 2 and 1 won't give 27.
FWIW:
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
#include <iostream>

int main()
{
    const int NO_OF_DIGITS{5};
    int digits[NO_OF_DIGITS];
    
    int digit;
    bool acceptable_number = false;
    
    int sum_of_digits{0};
    
    int checker[10];
    
    for(int it = 10235; it < 98765; it+=2)
    {
        digit = it;
        acceptable_number = true;
        
        for(int i = 0; i < 10; i++)
        checker[i] = -1;
        
        sum_of_digits = 0;
        for(int i = 0; i < NO_OF_DIGITS; i++)
        {
            digits[i] = digit % 10;
            
            sum_of_digits += digits[i];
            
            if(checker[digits[i]] >= -1)
                checker[ digits[i] ] = -2;
            else
                acceptable_number = false;
            
            digit /= 10;
        }
        
        if(digits[1] != 3*digits[3])
            acceptable_number = false;
        
        //if(digits[0] % 2 == 0)
            //acceptable_number = false;
        
        if(sum_of_digits != 27)
            acceptable_number = false;
        
        if(acceptable_number == true)
            std::cout << it << '\n';
    }
    
    return 0;
}
Last edited on
Looking at 4, 5, 6, 7, 8 & 9 digits, and allowing leading 0, the count of the numbers that satisfy the conditions are:


4 digits have 1 number(s)
5 digits have 20 number(s)
6 digits have 168 number(s)
7 digits have 456 number(s)
8 digits have 0 number(s)
9 digits have 0 number(s)


Based upon my previous code:

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
#include <iostream>
#include <cctype>
#include <iterator>
#include <string>
#include <sstream>
#include <iomanip>
#include <vector>
#include <cmath>

int main()
{
	enum errs { OK = 0, DUPDIG, TOOFEW, TOOMANY, NOTNUM, BADNUM, NOTODD, BADTENS };
	const char* errmsg[] {"OK!", "Duplicate digit", "Too few digits", "Too many digits", "Not a number", "Incorrect digit sum", "Not an odd number", "Tens not 3 times thousands"};
	constexpr size_t total {27};
	constexpr size_t startnum {1035};

	constexpr size_t maxdigits {9};

	static_assert (BADTENS == std::size(errmsg) - 1);

	for (size_t nodigits = 4; nodigits <= maxdigits; ++nodigits) {
		size_t cnt {};

		for (size_t n = startnum, maxnum = std::pow(10, nodigits) - 1; n < maxnum; n += 2) {
			std::string sno {std::to_string(n)};
			std::stringstream iss;

			iss << std::setw(nodigits) << std::setfill('0') << sno << '\n';
			iss.seekg(0);

			char ch {};
			std::vector<int> digits(nodigits);
			size_t sum {}, nod {};
			int err {OK};

			for (bool dup[10] {}; !err && (ch = iss.get()) != '\n' && nod < nodigits && std::isdigit(ch); dup[digits[nod++]] = true) {
				sum += (digits[nod] = ch - '0');
				err = dup[digits[nod]] == true;
			}

			//err += (!err && ch == '\n' && nod < nodigits) * TOOFEW;
			//err += (!err && std::isdigit(ch) && nod == nodigits) * TOOMANY;
			//err += (!err && (ch != '\n' || nod != nodigits)) * NOTNUM;
			err += (!err && sum != total) * BADNUM;
			//err += (!err && digits[nodigits - 1] % 2 == 0) * NOTODD;
			err += (!err && digits[nodigits - 4] != 3 * digits[nodigits - 2]) * BADTENS;

			if (err == 0) {
				//std::cout << std::setw(nodigits) << std::setfill('0') << n << '\n';
				++cnt;
			}
		}

		std::cout << nodigits << " digits have " << cnt << " number(s)\n";
	}
}

Last edited on
Oh, I actually meant: The digit in the thousands place is three times the digit in the tens place
so I think return tens*3==thousands; is right and 9837 is the correct answer

Since I wanted to reuse the vector function, I just used
1
2
auto dif = unique(temp_arr.begin(), temp_arr.end());
    return dif==temp_arr.end();
though the unique doesn't work quite as good as set

I came about this article that shows how to use a function that returns a static array (but i don't know much about pointers)
1
2
3
4
5
6
7
8
9
10
int *sep_num(int number){
    static int temp_arr[4] = {
        (number % 10),       // ones
        (number / 10) % 10,  // tens
        (number / 100) % 10, // hundreds
        (number / 1000)      // thousands
    };

    return temp_arr;
}
^so I used that here:
1
2
3
4
bool different_numbers(int number){  
    int *temp_arr = sep_num(number);
    return set<int>( temp_arr, temp_arr+4 ).size() == 4;
}
but what do you know it tells me that even 1235 is not a unique number

I reused the same function in sum_number:
1
2
3
4
5
6
7
int sum_number(int number) {
    int sum_number = 0;
    int *temp_arr = separate_number(number);
    for(int i = 0; i < 4; i++) sum_number += *(temp_arr + i);
    
	return sum_number;
}


I really just want to practice reusing a function wherever it can be reused. I want to learn how to reuse it in different_numbers first and then three_times
Last edited on
Pages: 12