0

I am to draw 3 balls from an urn of 24 and add up the total discount the balls represent. I am not allowed to replace the balls after drawing, so there can be no duplicate balls drawn. The discounts are 1, 2, 3, 4, 5, 6, 7, 8, and there are 3 of each.

My solution to this problem was to create multiple while loops that roll out of 24 and re-roll until no duplicates are drawn. I have done a loop like this in the past that would loop random numbers until a non-duplicate was chosen and it worked fine, so I set this program up the same way.

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

int draw(int urn[], int draws[]);

int main()
{
    int discountSum,discount;
    int urn[24]={1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,8,8,8};
    int draws[1000]={0};
    draw(urn,draws);
    cin >> discount;
    int averageDiscount=discount/1000;


    return 0;
}

int draw(int urn[], int draws[])
{
    static int discountSum=0;
    int i; //simulations counter
    int ball1, ball2, ball3;
    int score1, score2, score3;
    int totalDiscount;
    srand(time(0));

    for(i=0;i<1000;i++)
    {
        ball1=rand()%24;
        while (ball2==ball1)
        {
            ball2=rand()%24;
        }
        while ((ball3==ball2)||(ball3==ball1))
        {
            ball3=rand()%24;
        }
        score1=urn[ball1];
        score2=urn[ball2];
        score3=urn[ball3];
        totalDiscount=score1+score2+score3;
        draws[i]=totalDiscount;
        cout << "1) " << draws[i] << " percent discount.\n";
        discountSum+=totalDiscount;
    }
    return discountSum;
}

When I run this code, instead of receiving an error, the program runs with no output, and a return of a negative garbage value instead of 0. I would like to see the output from each discount up to the 1000th loop.

  • 1
    There may be additional bugs. For example, _draw()_ returns a value (`discountSum`), but that value isn't assigned to anything. Did you mean something like `int discount = draw(urn,draws);`? – B. Shefter Apr 16 '19 at 19:48
  • 2
    Probably simpler solution is to create `std::vector` or `std::array` with 24 elements from 0 to 23, random shuffle it and then get first 3 values see `std::iota` and `std::shuffle` examples on cppreference.com – Slava Apr 16 '19 at 19:50

2 Answers2

2

It looks as if the bug is that ball2 and ball3 are compared before they're ever set to anything. They're never even initialized, which is the likely cause of your "garbage value." It'll probably work if you "draw" each ball before comparing it, as:

ball1=rand()%24;
ball2=rand()%24;
while (ball2==ball1)
{
    ball2=rand()%24;
}
ball3=rand()%24;
while ((ball3==ball2)||(ball3==ball1))
{
    ball3=rand()%24;
}

An even better way would be to use do...while loops instead, which always run once, as:

ball1=rand()%24;
do
{
    ball2=rand()%24;
} while (ball2==ball1);
do
{
    ball3=rand()%24;
} while ((ball3==ball2)||(ball3==ball1));
B. Shefter
  • 877
  • 7
  • 19
1

A much simpler way to do this is to use the facilities build into the C++ standard library:

#include <iostream>
#include <algorithm>
#include <random>

std::mt19937 gen(std::random_device{}()); // initialize random number generator

 /*
  * or
std::mt19937 gen(std::time(NULL));
  * if std::random_device is not well-implemented
  */


int draw()
{
    static int urn[24]={1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,8,8,8};

    std::shuffle(std::begin(urn), std::end(urn), gen); // shuffle array

    return urn [0] + urn[1] + urn[2]; // pick first three balls from array
}

int main()
{
    int discount = draw();

    // Use discount. For example, 
    std::cout << discount;

    return 0;
}

Documentation:

std::mt19937

std::random_device

std::shuffle

user4581301
  • 33,082
  • 7
  • 33
  • 54