I think, it's quite easy to generate an int and then check if it matches the rules.
But the address can be found faster if you consider some logical consequences of the rules:
Digit 4: is odd
Digit 3: is either 1 or 2 or 3!
Digit 2: is even!
Digit 1: is Digit 3 multiplied by 3.
Of course, if you now generate an int by these rules, it's really hard to check its digits, so you could consider using a container like std::string
instead. But this will get quite ugly, because you always need to add (and subtract) '0'
, in order to work with the digit as a digit. So I decided to go with std::vector<int>
for your problem.
Before starting, I made a function that returns a random integer in a given range:
#include <random>
int random(int first, int last){
std::random_device now;
std::mt19937 engine(now());
std::uniform_int_distribution<int> r(first,last);
return r(engine);
}
With this, I implemented the "generator"
std::vector<int> generate_adress(){
std::vector<int> address(4);
address[3] = (random(0, 4) * 2) + 1; //last digit: odd number
address[2] = random(1, 3); //second digit: 1 or 2 or 3
address[1] = random(0, 4) * 2; //third digit: even number
address[0] = address[2] * 3; //last digit: second digit * 3
return address;
}
With this, the only 2 things missing, are:
and that's done quite easily:
bool sum27(std::vector<int> address){
int sum = address[0] + address[1] + address[2] + address[3];
return sum == 27;
}
bool unique_digits(std::vector<int> address){
for (int i = 0; i < address.size(); ++i){
for (int j = 0; j < i; ++j){
if (address[j] == address[i]) return false;
}
}
return true;
}
I wrapped these 2 up into one convenient function:
bool valid_address(std::vector<int> address){
return sum27(address) && unique_digits(address);
}
Now let's go to main()
function and use the functions:
int main(){
int ctr = 0;
bool done = false;
while (!done){
++ctr;
std::vector<int> address = generate_adress();
std::cout << "Adress #" << ctr << ": ";
for (int i : address) std::cout << i; //print out address
if (valid_address(address)){
std::cout << " That's the address!" << std::endl;
done = true;
}
else{
std::cout << " not correct...\n";
}
}
return 0;
}
Here is a run of the code:
Adress #72: 3617 not correct...
Adress #73: 6227 not correct...
Adress #74: 6823 not correct...
Adress #75: 6421 not correct...
Adress #76: 9831 not correct...
Adress #77: 9033 not correct...
Adress #78: 9439 not correct...
Adress #79: 9833 not correct...
Adress #80: 3815 not correct...
Adress #81: 3611 not correct...
Adress #82: 3415 not correct...
Adress #83: 6829 not correct...
Adress #84: 9637 not correct...
Adress #85: 3019 not correct...
Adress #86: 9635 not correct...
Adress #87: 6423 not correct...
Adress #88: 3613 not correct...
Adress #89: 6827 not correct...
Adress #90: 9233 not correct...
Adress #91: 3615 not correct...
Adress #92: 9639 not correct...
Adress #93: 9738 That's the address!
only 93 tries is quite good. If you would generate the address completely random, it takes way more time (obviously):
Adress #10054: 2333 not correct...
Adress #10055: 4057 not correct...
Adress #10056: 5753 not correct...
Adress #10057: 3901 not correct...
Adress #10058: 1149 not correct...
Adress #10059: 3029 not correct...
Adress #10060: 2378 not correct...
Adress #10061: 7777 not correct...
Adress #10062: 6870 not correct...
Adress #10063: 0187 not correct...
Adress #10064: 1720 not correct...
Adress #10065: 6101 not correct...
Adress #10066: 9738 That's the address!
10000 tries, though. Anyway, here's the full code:
#include <string>
#include <iostream>
#include <random>
#include <vector>
int random(int first, int last){
std::random_device now;
std::mt19937 engine(now());
std::uniform_int_distribution<int> r(first,last);
return r(engine);
}
std::vector<int> generate_adress(){
std::vector<int> address(4);
address[3] = (random(0, 4) * 2) + 1; //last digit: odd number
address[2] = random(1, 3); //second digit: 1 or 2 or 3
address[1] = random(0, 4) * 2; //third digit: even number
address[0] = address[2] * 3; //last digit: second digit * 3
return address;
}
bool sum27(std::vector<int> address){
int sum = address[0] + address[1] + address[2] + address[3];
return sum == 27;
}
bool unique_digits(std::vector<int> address){
for (int i = 0; i < address.size(); ++i){
for (int j = 0; j < i; ++j){
if (address[j] == address[i]) return false;
}
}
return true;
}
bool valid_address(std::vector<int> address){
return sum27(address) && unique_digits(address);
}
int main(){
int ctr = 0;
bool done = false;
while (!done){
++ctr;
std::vector<int> address = generate_adress();
std::cout << "Adress #" << ctr << ": ";
for (int i : address) std::cout << i; //print out address
if (valid_address(address)){
std::cout << " That's the address!" << std::endl;
done = true;
}
else{
std::cout << " not correct...\n";
}
}
return 0;
}