Coin toss simulation/game in Java - java

I'm currently doing a course in computer science which is technically for beginners, but I feel all the assignments they are giving me are more complicated than I can handle.
This assignment asks me to make a coin toss simulation. Three people play the game and each of them has specific requirements to win:
One wins if there are 2 results head and the total number of tosses
is even
One wins if there are 2 results tails and the total number of tosses is even
One wins if there are 2 results tails OR heads and the total number of tosses is odd
What I should do is run an experiment 300 times. Each time I should determine who of the three won and how many times. And I'm really stuck. I barely have any code but I do have an very basic idea of what the code should be like, but I can't put it into Java language.
For my assignment, I need to display the binary sequence that caused a person to win.
My idea:
Initialize a counter (1, 2, 3) for every person so that I can keep track of how many times they win
Initialize a head count and a tails count to keep track of the randomly generated sequence
Use a for loop for practically the whole experiment. There should be an outer loop that defines the experiment should be run 300 times and the inner loop should contain the if statements that check who has won. There should be a counter in every if statement, so that I can update it for every person. And I need a System.out.println(); to print every single result of the experiment.
Print the final outcome of the experiment, using the previously determined counters
EDIT:
I've tried to change what everyone said and it does look better now, thanks! But it's still not doing what it's supposed to do and I wonder why. I run the code and I only get one output; not the 300 times I want it to run. Furthermore, the counters at the end don't hold the information about who has won, they reset every single time. And sometimes two people win, while that should not be possible. Could anyone clarify this?
EDIT:
This is another update of the code. I believe it does run 300 times now! A problem now is the output. Sometimes it says; 1 Bernie wins, while you obviously need at least 2 results for Bernie to win. Also, it says 1 Penny wins, while that also shouldn't be possible. Did I mess something up in my if statements?
import java.util.Random;
public class Assignment3e
{
public static void main(String[] args)
{
int counter1 = 0;
int counter2 = 0;
int counter3 = 0;
Random coin = new Random();
for(int i = 0; i <= 300; i++){
int headCount = 0;
int tailsCount = 0;
for(int coinToss = 0; coinToss <= 3; coinToss++){
int random = (int) (Math.random() * 6) + 1;
String binary = Integer.toBinaryString(random);
boolean result = coin.nextBoolean();
if(result){
headCount++;
}
else{
tailsCount++;
}
if(headCount == 2 && binary.length() % 2 ==0){
//Amy wins
counter1 = counter1 + 1;
System.out.println(binary + " Amy wins.");
}
else if(tailsCount == 2 && binary.length() % 2 == 0){
//Penny wins
counter2 = counter2 + 1;
System.out.println(binary + " Penny wins.");
}
else if(headCount == 2 || tailsCount == 2 && binary.length() % 2 != 0){
//Bernie wins
counter3 = counter3 + 1;
System.out.println(binary + " Bernie wins.");
}
}
}
System.out.println("Amy wins " + counter1 + " times.");
System.out.println("Penny wins " + counter2 + " times.");
System.out.println("Bernie wins " + counter3 + " times.");
}
}

You almost got it right.
This part is not relevant anymore since OP add a requirement in comments.
Your second for loop only need to run a maximum of 3 times as there will be at least 2 heads or 2 tails, not 10.
Edit: you can do it with a maximun of 2 tosses: if there is 1 head and 1 tail, the winner is the 3rd player (Bernie)
Now, on each iteration, you can draw a random decimal number, between 0 and 1 and assume if it's over 0.5 it's a head so you increment the headCount, else you increment the tailCount. Then you can perform the test on the counters (and the number of tosses).
It's easier than using a binary String.
Edit:
To answer your comment:
Look where you initialized the headCountand tailCount. Remember that once one has won, those counters must be reset.
As it's homework, I won't post code :)
Edit:
OP jsut add a comment stating he need to print the sequence that lead to the result of each game.
We assume a binary 1 is a head, and a 0 is a tail. You need to toss the coin 3 times to know the sequence if Bernie wins. So the integer value random which is converted in binary string only need to be made of 3 bits (1 bit = 1 toss).
random can only take values between 0 and 7.
As you get all values in one shot, you don't need the coinToss for loop anymore. All you need to do is to check if the beginning of the binary string matches any win pattern (11 for 2 heads, 00 for 2 tails, else Bernie wins)

So there are a couple of things I'm noticing here:
You don't update headCount or tailCount anywhere. This should be what you're using to keep track of the number of coin flips.
When you go back to reuse these in subsequent loops, be sure to zero them out again.
You're using a very wide range for your result, when a simple nextBoolean would be all that needs to suffice. You could use it as this in your loop:
boolean result = coin.nextBoolean(); // this renames dice to coin
if(result) {
headCount++;
} else {
tailCount++;
}
The total number of tosses is always the current iteration's current value (plus 1). So, in your case, you could simply replace sum with j, but you'd want to give it a more meaningful name, like coinTosses instead.

If you're using a Random() object anyways for the coin nextBoolean(), why not replace the int random = (int) (Math.random() * 6) + 1; with int random = coin.nextInt([range here])?

Related

My Birthday Problem code is not printing anything

I am an absolute beginner to learning programming and I was given this assignment:
Birthday problem. Suppose that people enter a room one at a time. How people must enter until two share a birthday? Counterintuitively, after 23 people enter the room, there is approximately a 50ā€“50 chance that two share a birthday. This phenomenon is known as the birthday problem or birthday paradox.
Write a program Birthday.java that takes two integer command-line arguments n and trials and performs the following experiment, trials times:
Choose a birthday for the next person, uniformly at random between 0 and nāˆ’1.
Have that person enter the room.
If that person shares a birthday with someone else in the room, stop; otherwise repeat.
In each experiment, count the number of people that enter the room. Print a table that summarizes the results (the count i, the number of times that exactly i people enter the room, and the fraction of times that i or fewer people enter the room) for each possible value of i from 1 until the fraction reaches (or exceeds) 50%.
For more information on the assignment
However, my code won't print. I would really appreciate if someone could help me find the problem to my assignment.
public class Birthday {
public static void main(String[] args) {
int n = Integer.parseInt(args[0]); //number of days
int trials = Integer.parseInt(args[1]);
boolean[] birthdays = new boolean[n];
int[] times = new int[n + 2]; //number of times i people entered the room
int r;
for (int t = 1; t <= trials; t++) {
for (int k = 0; k < n; k++) { //reset birthday
birthdays[k] = false;
}
for (int i = 1; i <= n; i++) { //number of times
r = (int) (Math.random() * (n - 1)); //random birthday
if (birthdays[r] = false) {
birthdays[r] = true;
continue;
}
else if (birthdays[r] = true) {
times[i]++; //number of times i people entered the room + 1
break;
}
}
}
int j = 1;
while ((double) times[j] / trials <= 0.5) {
System.out.print(j + "\t" + times[j] + "\t" + ((double) times[j] / trials));
j++;
System.out.println("");
}
}
}
I can spot two errors from your code
As Scary Wombat pointed out, you are miss double equal sign inside of your if statement.
The assignment is asking you to calculate "fraction of times that i or fewer people enter the room", meaning you need to do a summation for the first i indices and divided by trials.
For example, among 1 million trials, the fraction in which first duplicate birthday happens when 4th person enters is
(times[0] + times[1] + times[2] + times[3])/ 1000000
Here is what I got:
1 0 0.0
2 2810 0.00281
3 5428 0.008238
4 8175 0.016413
As you can see the fraction is calculated by adding the first three elements together and then divided by 1000000 (2810 + 5428 + 8175 = 16413) / 1000000 = 0.016413
The way you are calculating the fraction ((double) times[j] / trials) is not correct.
You are not adding the previous counts as shown in the example. To do so, you can create a new variable to store the sums of previous counts. and use it as your while loop condition. For instance, see below..
csum += times[j]; // this adds the previous counts into a cumulative sum.
This cumulative sum is supposed to be the one u use to divide by trials to get your probability. Cheers!

Create random generator to make and count odd even pairs of numbers

I'm really, really stuck and confused. I've net searched several times, and can't find anything that helps me with this precise homework problem.
Involved: Java, while loops, randomly generating numbers, and scanner console input.
We have to finish the code in main method so it takes two separate inputs from the console and generates a number of "rolls" , then displays the results when they are a pair of numbers, one even, one odd.
Edit: It was pointed out to me my phrasing was confusing. Joseph Larson phrased it better:
"You are to ask for the upper bound of the random numbers, and then a number of times to run, correct?" Yes, that's it.
I have two primary problems. If these get fixed, I'm fairly sure I can figure out the rest.
1) I know I'm supposed to do something to complete the while loop, but nothing I've tried gets the required results.
2) I think I've declared the randUpBound and oddeven items incorrectly, but I can't figure out what I might have done wrong if I have.
The weirdest part is most of my attempts have created a blank infinite loop -nothing is displayed, but IntelliJ swears the program is running, and it doesn't stop until I make it stop. Not even the strings in quotes appear.
Expected display and code below. I've stuck //added to the lines where it's my code, and left in the teacher's instructions.
Thanks for any help you can give!
Expected Display
Enter random upper bound? 12
Enter number of odd even pairs to count? 2
Numbers rolled: 11, 2
Odd+even pair found! 11,2
Numbers rolled: 1, 8
Odd+even pair found! 1, 8
Numbers rolled: 1, 1
Total Roll count: 6
Code
import java.util.*; //added
public class OddEvenPairs {
public static void main(String[] args) {
//.....[add in missing code here - make declarations and add console input for the random number upper bound,
// and the number of odd-even pairs to be counted]
//read two consecutive numbers - fencepost
Scanner console = new Scanner(System.in); //added
Random rand = new Random(); //added
int randUpBound = console.nextInt(); //added
int oddeven = console.nextInt(); // added
System.out.println("Enter random upper bound? " + randUpBound); //added
System.out.println("Enter number of odd even pairs to count? " + oddeven); //added
int roll1 = rand.nextInt(randUpBound);
int roll2 = rand.nextInt(randUpBound);
System.out.println("Numbers " + roll1 + ", " + roll2);
int rollcount = 2;
int oddEvenNum = roll1 + roll2;
//process the numbers
while (oddeven < oddEvenNum) {
oddeven = oddEvenPair(roll1, roll2, oddeven);
roll1 = rand.nextInt(randUpBound);
roll2 = rand.nextInt(randUpBound);
System.out.println("Numbers " + roll1 + ", " + roll2);
rollcount += 2;
//.....[complete missing code here]
}
}
//method to figure out odd-even pair
public static int oddEvenPair(int roll1, int roll2, int oddeven) {
//boolean oddEvenFound = false;
if (roll1 % 2 == 1) {
if (roll2 % 2 == 0) {
//oddEvenFound = true;
oddeven++;
System.out.println("Odd even " + oddeven);
System.out.println("Odd+even pair found!" + roll1 + "," + roll2);
}
}
return oddeven;
}
}
Okay, there are a few problems with your code. First, this:
int randUpBound = console.nextInt(); //added
int oddeven = console.nextInt(); // added
System.out.println("Enter random upper bound? " + randUpBound); //added
System.out.println("Enter number of odd even pairs to count? " + oddeven); //added
These will happen in order, which means you'll accept input from the console and THEN prompt the user. This will be confusing.
Next, I would change the variable name for oddeven to something like "numberOfTries". Oddeven doesn't really explain what it's really for.
Once you have those two numbers, you need a loop.
for (int thisTry = 1; thisTry <= numberOfTries; ++thisTry) {
...
}
This will then run your code the proper number of times.
Inside that loop is where you will generate your two random numbers and then call your oddEvenPair method. Then just print out the results.
Your function is really weird and probably doesn't do what you want.
Here's the thing. You let yourself get confused by thinking about too much at once. Break it down. How would you do it on paper? Break it into little pieces. You really have 5:
-Get data from the user (with prompts)
-Loop the proper number of times
-Generate two random numbers in the proper range
-Determine both odd/both even/one of each
-Print the results
Think about things in those terms, and then the amount of code for each step is REALLY small.

straights algorithm in yahtzee

For a school assignment we are working on implementing the yahtzee game in java, but I am having some problems with making algorithms for the straights (small and large straight, which means 4/5 consecutive numbers for a small straight and 5/5 for a large).
I have made one algorithm that I believe should be working, but in reality it always puts out 0 so I should be missing something:
private void straights(int category) {
Arrays.sort(dices);
int nonConsecCount = 0;
for(int currDice = 0; currDice < N_DICE - 2; currDice++) {
if(dices[currDice] != dices[currDice + 1] + 1) {
nonConsecCount++;
}
}
if(nonConsecCount == 0 && category == LARGE_STRAIGHT) {
score[currPlayer - 1][category - 1] = 40;
display.updateScorecard(category, currPlayer, 40);
} else if(nonConsecCount <= 1 && category == SMALL_STRAIGHT) {
score[currPlayer - 1][category - 1] = 30;
display.updateScorecard(category, currPlayer, 30);
} else {
score[currPlayer - 1][category - 1] = 0;
display.updateScorecard(category, currPlayer, 0);
}
}
N_DICEis equal to 5.
My theory behind this algorithm was; everytime you find a number in the (sorted) array of dicevalues that doesn't have a consecutive number as the next one, add one to the non consecutive count, and in the end check for this counter when handing out the score to the player.
Any help would we greatly appreciated!
According to the rules of the game which I quickly skimmed through the article in the wikipedia
Small Straight - Is 4 sequential dices (30 score) that is
1,2,3,4 or 2,3,4,5 or 3,4,5,6
Large Straight - Is 5 sequential dices (40 score) that is
1,2,3,4,5 or 2,3,4,5,6
If small straight, then you should have a nonConsecCount equal to 1 because 5 - 1 is 4 and that gives us the four consecutive dices. If large straight, then you should have a nonConseCount equal to 0 because 5 - 0 gives us all five elements as consecutive.
If I understand the game correctly (taking into account the fact that I just skimmed it), you need the following modifications in your code:
Your for loop condition should be N_DICE - 1, this would result the
for loop to execute 4 times, one less than size of array hence, you
are guaranteed not to get ArrayOutOfBoundException
You need to change your if condition such that, add to the value
of the left part of condition and then check that with value of right part of the condition that is one ahead. As a result of this, swapping you can use N_DICE - 1 instead of N_DICE - 2. N_DICE - 2 skips one array element and only checks 3 consecutive elements (not what the games rules say).
Make the following changes to your code:
int nonConsecCount = 0;
for(int currDice = 0; currDice < N_DICE - 1; currDice++) {
if(dices[currDice] + 1 != dices[currDice + 1]) {
System.out.println("failed consecutive match!");
nonConsecCount++;
} else {
System.out.println("passed consecutive match for "+ dices[currDice]);
}
}
System.out.println(nonConsecCount);
I provided the above code the following dices and got nonConsecCount as show in the comment line:
int[] dices = new int[]{3,4,5,1,2};
//output 0 - this is largest straight
int[] dices = new int[]{3,4,5,6,2};
//output 0 - this is largest straight too
int[] dices = new int[]{3,4,5,2,2};
//output 1 - this is smallest straight
int[] dices = new int[]{3,4,2,2,2};
//output 2 - this is none of the two

Calculate Average of Previous Loop - Java

So, I am working on this code for my AP Computer Science class, and I ran into a problem.
First, here is my code:
//loop counters
int counterOne = 0;
int counterElse = 0;
int loop = 1;
int iNum = 1000;
//create file
PrintWriter outFile = new PrintWriter(new File("newFile.txt"));
for (int counter = 1; counter <= iNum; counter++)
{
while (loop >= 1)
{
Random rand = new Random();
int iRand = rand.nextInt(5)+1;
if (iRand != 1)
{
counterElse++;
loop++;
}//end of if of if-else
else
{
counterOne++;
loop = 0;
}//end of else of if-else
}//end of while loop
int tries = counterElse+counterOne;
//int average = (tries + prevTriesSum) / counter
System.out.println("It took " + tries + " try/tries to win!");
//outFile.println("It tool an average of " + average + " tries to win.");
}//end of for loop
How do I calculate the average of the trials? As you can see from the end of my code, I commented out a line that I would want to calculate the average. This is because I don't know how to calculate prevTriesSum, which represents the sum of all of the other trials. Here is an example: Assume the loop runs six times, and with the first run, it takes 3 tries, 5 on the second run, 7 on the third, 11 on the fourth, 2 on the fifth, and 4 on the sixth (the most recent one. now tries = 4).
I would want prevTriesSum to equal 3 + 5 + 7 + 11 + 2 + 4.
How do I get the program to calculate that?
Your average is computed in integer arithmetic which means any fractional part is discarded. Consider using a floating point type for the average, and prefix the right hand side of the assignment with 1.0 * to force the calculation to occur in floating point.
You must not reinitialise the random generator in the loop, else you ruin its statistical properties. Do it once before you enter the loop.
Before the while loop, add
int prevTriesSum = 0;
Replace your commented int average = line with
prevTriesSum += tries;
And after the for loop add
double average = (prevTriesSum + 0.0) / counter;
outFile.println("It tool an average of " + average + " tries to win.");
As for the random number generator, Bathsheba is correct. You must move that above the for loop. Just move the declaration.
You'll also need to change your for loop slightly. As it stands, it will equal 1001 when the for loop terminates. Change it as follows:
for (int counter = 0; counter < iNum; counter++)
This will ensure that your average calculation is correct.

Alternating factorial terms using Java

I'm trying to write a loop in Java that can output the sum of a series which has this form... 1! -3! + 5! ā€“ 7! + ... up to n (user gives n as a positive odd number). For example, if the user inputs 5 for n, then the series should calculate the sum of 1! -3! + 5! (hard part) & display it to the user with a basic print statement (easy part). If the user gives 9, then the sum calculated would come from 1! -3! + 5! - 7! + 9!.
For ease, just assume the user always puts in a positive odd number at any time. I'm just concerned about trying to make a sum using a loop for now.
The closest code I've come up with to do this...
int counter = 1;
int prod = 1;
n = console.nextInt();
while (counter <= n)
{
prod = prod * counter;
counter++;
}
System.out.println(prod);
This does n!, but I'm finding it hard to get it do as specified. Any pointers would be great.
As you calculate the factorials, keep a running total of the series so far. Whenever counter % 4 == 1, add the factorial to the running total. Whenever counter % 4 == 3, subtract the factorial from the running total.
You said "any pointers" - I assume that means you don't want me to write the code for you.
Update
This is closely based on your original code, so that it would be as easy as possible for you to understand. I have changed the bare minimum that I needed to change, to get this working.
int counter = 1;
long prod = 1;
long total = 0;
n = console.nextInt();
while (counter <= n)
{
prod = prod * counter;
if( counter % 4 == 1 ) {
total += prod;
} else if (counter % 4 == 3) {
total -= prod;
}
counter++;
}
System.out.println(total);
First up, notice that I have changed prod to a long. That's because factorials get very big very fast. It would be even better to use a BigInteger, but I'm guessing you haven't learnt about these yet.
Now, there are those two conditions in there, for when to add prod to the total, and when to subtract prod from the total. These both work by checking the remainder when counter is divided by 4 - in other words, checking which factorial we're up to, and doing the right operation accordingly.
First of all, you need to introduce a variable int sum = 0; to store the value of the alternate series.
To only sum every second value, you should skip every second value. You can check that using the modulo operation, e.g. if( counter % 2 == 1 ).
If that is true, you can add/subtract the current value of prod to the sum.
To get the alternating part, you can use a boolean positive = true; like this:
if( positive ) {
sum += prod;
} else {
sum -= prod;
}
positive = !positive;
Based on the boolean, the prod is either added or subtracted. The value is altered afterwards.
Because factorials become very large very fast, it would be better to use variables of type long.

Categories