I am writing a small raffle program (as part of a larger program). The user can input a bunch of names and tickets purchased by that name. At the end, the program draws a random winner. I've been wracking my brain at how to go about this and I have a few ideas but I don't think any are optimal.
So I come to you all looking for some advice/brainstorming on the best way to do this.
Currently I have it set up where the user inputs as many people and associated tickets each of them have purchased. I have them stored in a vector of structures.
1 2 3 4 5 6 7
struct Person
{
string name;
int tickets;
};
...
vector <Person> myvector;
What would be the best way to go about picking a winner? Or multiple winners? Any advice/pseudo code to get me over my coding-block would be appreciated.
edit: basically, I'm looking for the fastest way to get from a random number to a winning ticket.
Here's a pretty simple way to go about it. I'll give you some basic thought process since you know what you're doing :-)
So after you fill the vector of type Person with a bunch of "Persons" you're going to need to determine a winner. What you could do to simulate the "raffle" of the tickets is pick a random index within the bounds of the vector(don't want any run-time errors). I suggest using a for loop. If you don't want to do it that way then just select a random index. I assume you know of rand in C++?
EDIT:
What do you mean when you say optimal? Can you be more specific?
Yes By optimal just meaning as a good way of going about it without hundreds of lines of code -- I know it can be done I am just not good enough to figure it out lol.
The way I am thinking about doing it is keeping a running total of how many tickets have been purchased and then going back and looping through and finding a winner.
For example, the way I am thinking about doing it.. if there were 5 entrance each bought 500 tickets.
I take a random number and get say 2250. My loop would go through each element, starting at the bottom/first entrance, seeing he has 500 and setting a temp running total number to 500. Loop would hit the second guy and see he also had 500 making the temp running total 1000. Third guy 500 temp running total # 1500. Fourth guy 500 temp running # 2000. And finally it would hit the winner since the temp running (2500) total went over the random number (2250) so I know that person had won.
If that makes any sense, that's how I think I want to go about it, but I'm not sure if there is an easier way... it seems like a complicated way of going about it.
Perhaps there's an easier way of doing it by summing the struct members inside of a vector?
edit: hmm a little more searching and it looks like std::accumulate is going to do mostly what I want and save me trouble accumulating tickets, but I'm still not sure the best way to pick the winner, and more specifically, match the random winning ticket with the person.
Do you really need to keep track of how many elements were entered using std::accumulate ;)
try [vectornamehere].size();
EDIT:
You're good enough to do it. Programming isn't hard it's just a lot of thinking, "What can I do better","What happens if I do this". If you have a bug then it's a whole different story! :P
I just looked at std::random_shuffle and while that would work if everyone bought the same amount of tickets I don't think it would work with variable amounts of tickets. It looks like it would give the person who bought 1 ticket the same odds as the person who bought 500 tickets.
all the tickets have different numbers yes or can one person have ticket 1 and another person have ticket 1 also? From the looks of it you have it so each person has only one ticket so you would have to type in the same name multiple times with different numbers right now.
I'm not sure I understand the question completely so I'll give you an example of how I have it set up now:
I have 3 participants in the raffle. The user can input as many names as they want and they are all free to purchase as many tickets as they want, but for this example, they are as follows:
Craig who has bought 100 tickets.
Joe who has bought 1 tickets.
John who has bought 2 tickets.
Therefore...
myVector[0].name is Craig, myVector[0].tickets is 100;
myVector[1].name is Joe, myVector[1].tickets is 1;
myVector[2].name is John, myVector[2].ticket is 2;
It would appear that if I did std::random_shuffle it would give everyone an equal opportunity to win, when clearly Craig should win most of the time.
I would like to be able to pick a random number that is 1 to Max tickets bought and match it to it's ticket holder. In the previous, anything 1-100 would hit Craig as a winner, and 101 would be Joe, and 102&103 would be John.
oh I see. I thought ticket in your struct was the ticket number that makes more sense now. what I would do would be to add all the values up. And then get a random number ex:
1 2 3 4 5 6 7 8 9
srand( ( unsigned ) time( NULL ) );
unsignedshort tickets = 0 , ticketDraw = 0;
for( Person i : myVector )
{
tickets += i.tickets;
}
ticketDraw = rand() % tickets + 1; //( high - low + 1 ) + low where low is 1
std::cout << "The winner of the raffle is " << myVector[ ticketDraw - 1 ].name << std::endl;
//ticketDraw - 1 since vectors start at 0 and not 1 and you wanted to draw from 1 up =p
My line 8 needs to be fixed you need to add the previous tickets before that one and figure out who has what ticket numbers after you figure out that you can see who won.
Yea that helps thank you. So that part of code will get me a random ticket number out of the maximum possible tickets. But like you said that still doesn't get me where I need to be. I'm still lost how I would then take that random number and find it's owner.
Awesome. Just glancing over it that looks like it will do exactly what I want. Bugs/errors are no problem I can sort them... heck I was expecting pseudo code so real code is great.