-3

Holy digits Batman! The Riddler is planning his next caper somewhere on Pennsylvania Avenue. In his usual sporting fashion, he has left the address in the form of a puzzle. The address on Pennsylvania is a four-digit number where: • All four digits are different • The digits in the thousandths place is three times the digit in the tens place • The number is odd • The sum of the digits is 27 Write a program that uses a loop (or loops) to find the address where the Riddler plans to strike.

I'm not so sure where the program is going wrong. any help will be appreciated.

#include <iostream>
using namespace std;

void splitAddress(int address, int thou, int hund, int tens, int ones) {
while (address >= 1000) {
address = address - 1000;
thou++;
}
while (address >= 100) {
address = address - 100;
hund++;
}
while (address >= 10) {
address = address - 10;
tens++;
}
while (address >= 1) {
address = address - 1;
ones++;
}
}
void areIntsTheSame(int address, int thou, int hund, int tens, int ones) {
if (thou == hund || thou == tens || thou == ones ||
hund == tens || hund == ones || tens != ones) {
address--;
}
}
void thou3tens(int address, int thou, int tens) {
if (thou != 3 * tens) {
address--;
} 
}
void evenOrOdd(int address) {
if (address % 2 == 0) {
address--;
}
} 
void Sum27(int address, int thou, int hund, int tens, int ones) {
if ((thou + hund + tens + ones) != 27) {
address--;
} 
} 
int main() {
int address = 9999;
int thou = 0;
int hund = 0;
int tens = 0;
int ones = 0;

splitAddress(address);
areIntsTheSame(address);
thou3tens(address);
evenOrOdd(address);
Sum27(address);

cout << "the address is " << address << endl;

system("pause");
return 0;
}

thanks in advance.

N.Hezrony
  • 27
  • 1
  • 5
  • 1
    We won't do your homework for you! What's your question? What have you tried? – Charles Oct 23 '16 at 16:57
  • First, you need to call your functions with the right number of arguments. The only one that can be called with a single argument is `evenOrOdd()`, the rest need more than one. Second, your functions pass parameters by value; this means that each function has local variables that it modifies, without changing the actual variables you passed it. You might want to read up on _[pass-by-reference](http://stackoverflow.com/questions/373419/whats-the-difference-between-passing-by-reference-vs-passing-by-value)_, which is what you're looking for. – Justin Time - Reinstate Monica Oct 23 '16 at 17:04
  • (For example, if you pass `int address`, then the function has its own copy of `address`; if it modifies its `address`, `main()`'s `address` remains the same. If you pass `int& address`, then it works directly with the one you passed; if it modifies its `address`, `main()` sees the change in its `address()`.) – Justin Time - Reinstate Monica Oct 23 '16 at 17:06
  • i changed int address, thou... to int & address, int & thou... and int the main splitAddress(address,thou,hund,tens,ones); but im still having problems and i don't really know how to solve the problem – N.Hezrony Oct 23 '16 at 17:23
  • Use the information given to help you determine your for loops. The ones digit is odd, so loop over 1,3,5,7,9. The tens digit is 1,2, or 3. The hundreds digit is any digit not used yet. The thousands digit is 3,6, or 9. Then use the other rule (no digit is the same, and they add to 27) to determine if the number is a match. – MarcD Oct 23 '16 at 17:50
  • With the rules given, there should be about 5*3*3*(10-4) possibilities for the address, or 270 different possibilities. – MarcD Oct 23 '16 at 17:52

1 Answers1

0

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:

  • The digits must be 27 added together.

  • The digits need to be unique.

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;
}
Stack Danny
  • 7,754
  • 2
  • 26
  • 55
  • can someone please take a look at this i have no idea why it wont work – N.Hezrony Oct 23 '16 at 21:08
  • void compTurn(int & totalTp, int userTp, string & turn) { if (totalTp > 4) { totalTp = 4 - userTp; turn = "human"; } else if (totalTp >= 2 && totalTp <= 4) { totalTp = 1; turn = "human"; } else if (totalTp == 1) { cout << "you win " << endl; } } int main() { string turn = "human"; int playerTp = 0; int totalTp = 23; int compTp = 0; while (turn == "comp") { compTurn(totalTp, turn); – N.Hezrony Oct 23 '16 at 21:10