Very simple code, but program freezes every time

Hi!

I'm trying to answer a very simple mathematical question by a program. The question is:
There's a family of 20 people. They all work. Women gain 30$/hour, men, 15$/hour and kids, 5$/hour. If the whole family wins 200$/hour, how many women, men and kids are they?

I've written this code, thinking it would work immediately, but everytime I compile it, I get a message from Windows saying the program stopped working. I tried to do the program without the randomize (I removed the money condition) and it worked well, so I think the problem is from the randomization, but I just can't find it. Here's the 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
#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;


int main()
{
    srand( time( NULL ) );
    int money=0;
    int men=0;
    int women=0;
    int kids=0;
while (money!=200)
    {
       women=rand() % (20 - 1 ) + 1;
       men=rand() % (20-women-1)+1;
       kids=rand()%(20-women-men-1)+1;
       money=30*women+15*men+5*kids;
    }

    cout<<"There are "<<women<<" women, "<<men<<" men and "<<kids<<" kids \n";
    return 0;
}

Thank you!
Probably a divide by zero error. For example, if (20-women-men-1) evaluates as zero, then rand() % 0 will be attempted, and fail.
You only break out of the loop when money is EXACTLY 200... what happens when money jumps from 180 to, say 250? Your loop will keep going.

Perhaps you should end the loop when money is greater than or equal to 200?

@Chervil
I didn't think about that. I figured he was eventually triggering some sort of overflow by running that loop too long. I ran it through the VS2010 debugger and the div by zero is exactly what happened.

@OP The solution I suggested would have not exposed the bug Chervil mentions, since it happened when money == 255. Definitely fix the bug along with your loop condition.
Last edited on
You're solving this problem by jumping around with rand() rather than going through the list of possible combinations of women, men, and children (Side note, women gain more than men and children aren't complete money sinks? Where can I sign up for this utopia?). Like this, the worst case scenario for your program is that it will never end assuming it didn't crash.

Three loops would work better than one loop and three rands.

-Albatross
Last edited on
This is a good exercise for learning how to use the debugger.

I ran your code and experienced the crash. Fortunately, I was running the debugger so when it crashed I was able to see at which line it occurred and the value of each variable.

For me it crashed on line 19.

women = 16, men = 3.

Now if I look at this I see:
1
2
3
4
kids = rand() % (20 - women - men - 1) + 1;
kids = rand() % (20 - (16) - (3) - 1) + 1;
kids = rand() % (20 - 20) + 1;
kids = rand() % (0) + 1;


And that's where our problem is. Try running this application:
1
2
3
4
int main() {
    int a = 5 % 0;
    return 0;
}


You'll see the same crash. You need to avoid the condition where you %0.
Thank you for all the replies! I'll try a different code and avoid the %0.
Just one comment. Is there more than one possible solution, and if so do you need to list them all?
I don't think there are multiple solutions, but I absolutely need to find a combination that gives 200$.
Just a suggestion, it's still not the most efficient way to do this calculation, but instead of using random combinations, try systematically iterating through each set of combinations until you find one or more solutions. This way you are sure not to get the combination over and over and you will eventually find the solution if there is one.

Example:
1
2
3
4
5
6
7
8
9
10
11
const int ppl = 20;
for (int men = 0; men <= ppl; ++men)
{
  for (int women = 0; women <= ppl - men; ++women)
  {
    int kids = ppl - men - women;
    int money=30*women+15*men+5*kids;
    if (money == 200)
      cout<<"There are "<<women<<" women, "<<men<<" men and "<<kids<<" kids \n";
  }
}


Edit: There is one solution that has men, women and children. There are three solutions if 0 is a valid number of one type of person.
Last edited on
@Stewbond Thanks for the suggestion and the code! I also think it's a better idea to not use random numbers, as it gets very complicated (for a beginner like me)
For the one solution
if (money==200&&kids!=0&&women!=0&&men!=0)
If you want the non-zero solution, you could modify the code from Stewbond above so the loops start from 1 rather than 0 and end 2 or 1 iterations short of the current limits, to allow there to be always at least 1 of each category. That cuts down the total iterations from 231 to 171, though it runs very quickly in either case.
Good! Thanks @Chriscpp and @Chervil!
Topic archived. No new replies allowed.