java:Adopting in algorithm? - java

Birthday probability problem
here is the algorithm which i follow, bit i still face problem. The algorithm is
To simplify the problem, we make the assumption that each day of the year (except February 29) is equally likely for a birthday. We will only consider 365 days in a year.
When generating a random birthday for a person, generate a random integer in the range 0-364, each number will represent an individual day in a year (0 for January 1st, and 364 for December 31st). We will use zero-based numbers to match array indexing.
When performing a single simulation, remember you only need to find one pair of matching birthdays to make the simulation count. That is, as soon as you determine that two people have the same birthday you can stop the current simulation and start the next simulation.
To ensure that everyone’s program behaves the same (so that we can auto-grade everyone’s submission), you will need to create a new Random object for each simulation run, and you will need to seed the Random object with the number of the run you are simulating (the first simulation run will use the integer 1 as the seed, the second run will use 2, etc.). You need to create a new Random object per simulation run, not per random number needed [do not use the Math.random() method in this program].
During one simulation, you will need to keep track of the days which ``correspond to someone’s birthday, or alternatively keep track of the number of birthdays that occur on any given day. There are several structures that we studied in this module of the MOOC that could be used to easily solve this problem. You are free to pick the structure of your choice. Note that the goal is to simply determine if two birthdays land on the same date.
When returning the final result, return the percentage in the range 0.0 – 100.0.
enter code here
import java.util.HashSet;
import java.util.Random;
import java.util.Scanner;
import java.util.Set;
public class Logic {
public static void process(int size, int count)
{
int number = 0;
Set<Integer> bdays = new HashSet<>();
int x[] = new int[size];
Random random = new Random();
random.setSeed(1);
int matches = 0;
boolean out = false;
for (int i = 0; i < count; i++) {
for (int j = 0; j < size; j++) {
number=(random.nextInt(365)+1);
}
for (int j = 0; j < count; j++) {
if (bdays.contains(number)) {
matches++;
}
else
{ bdays.add(number);
out = true;
break;}
if (out) {
out = false;
break;
}
}
}
double prob = 100*(double) matches / count;
System.out.println("The probability for two students to share a birthday is " + prob + ".");
}
public static void main(String[] args) {
Scanner inp = new Scanner(System. in );
System.out.println("How many students?");
int num = inp.nextInt();
System.out.println("How many times?");
int times = inp.nextInt();
process(num,times);
}
}

I suspect there are a few things wrong, but here's the first one: You're always adding number to bdays as soon as you assign number. You then later check to see if number is in bdays, which of course it will be - thus why you get the 100% match rate. What you need to do is:
Pick number
Check if number is already in bdays, and increment the counter if it is
Add number to bdays

Related

How do I generate multiple random variables in Java?

I am making a game where the user gets to pick the number of die for each roll. Right now my code is processing the users input correctly, but it only randomly generates the last number, the other numbers are 0. (For example if the user input 4 the roll would appear : [0,0,0,3]
Does anyone know how to get all the numbers to generate random numbers?
Here is my main:
public class game
{
public static void main(String[] args)
{
int play = 1, sum = 0;
int[] wins = new int[15];
while ((play == 1) && (sum < 15))
{
sum = 0;;
int roll = 0;
Config die= new Config();
//starts configuration
die.hand();
System.out.println("\nHere is your roll:\n");
die.get();
}
}
Here is my configure class:
import java.util.Scanner;
import java.util.Random;
import java.util.Arrays;
class Config
{
public static int Dice;
int i;
public void hand()
{
System.out.println("\nLet's Configure the Game...\n");
String file = "Config.txt";
Scanner scan = new Scanner(System.in);
//configures number of dice in hand
System.out.println("Enter the number of dice you would like in your hand (1-5): ");
int hand_count = scan.nextInt();
int[] Dice = new int[hand_count];
System.out.println("Here is your roll: \n");
Random random= new Random();
for (i = 0; i<hand_count - 1; i++);
{
Dice[i] = random.nextInt(6) + 1;
System.out.println(Arrays.toString(Dice));
}
System.out.println("\nNow lets play the game...\n");
//s.close();
}
public int get()
{
return Dice;
}
}
for (i = 0; i<hand_count - 1; i++);
{
Dice[i] = random.nextInt(6) + 1;
System.out.println(Arrays.toString(Dice));
}
You have a semi-colon at the end of the first line of this for loop, resulting in your loop having no contents. Get rid of the semi-colon, and move your opening curly brace onto the same line as the for loop, i.e.
for (i = 0; i<hand_count - 1; i++) {
// do cool stuff
}
The answer by sunrise is good. But I suggest using ThreadLocalRandom instead of java.util.Random. Plus, your code has other issues to resolve.
ThreadLocalRandom
Using the ThreadLocalRandom class is thread-safe in case you ever use background threads. And a single random-number generator per thread is established, available automatically for re-use, so less overhead for repeated use.
Like java.util.Random, ThreadLocalRandom offers some nifty methods for generating a series of numbers as a stream for use in modern Java. We can shorten the code to a single-line.
int countDice = 3;
// Bounds of random number are inclusive, exclusive. So (1,7) for six-sided dice.
int[] results = ThreadLocalRandom.current().ints( countDice , 1 , 7 ).toArray();
System.out.println( "results = " + Arrays.toString( results ) );
When run:
results = [4, 6, 4]
Other issues
Variable names should start in lowercase. So public static int Dice; should be public static int dice;.
Class names start in uppercase, by convention. So public class game should be public class Game.
Your class design is disorganized. A key goal of object-oriented programming (OOP) is to more clearly model the entities being represented within your app. So I suggest you create a Die class to represent each die. That class should have a roll method that generates a new value.
In another class, instantiate some of these Die objects. Collect those instances in a collection named dice. Then for each round of your game, call roll on each die.
I was tempted to write more code for you, but this is obviously homework I'll go no further.

How do you add integer elements from an array and output using JOptionPane?

Heres what i have. The user enters number of appointments for 7 days, but Im confused on how im suppose to add the integers the user inputed from the arrays? any advice on how I can go about doing this?
import javax.swing.JOptionPane;
public class AdvisingAppointmentTracker {
public static void main(String[] args) {
// Step 1: Set any constants needed for the program
final int NUM_DAYS = 7;
final int MIN_NUM_APPOINTMENTS = 0;
// Step 2: Create an array that will hold the number of advising appointments per day
int appointments[] = new int[NUM_DAYS];
// Step 3: Enter the number of advising appointments for all of the days
for(int i = 0; i < appointments.length; i++)
appointments[i] = Integer.parseInt(JOptionPane.showInputDialog("Enter the number of appointments"));
// Step 4: Find the average number of appointments
// Step 5: Output the average number of appointments
}
}
This is one approach
int numberOfAppointments = 0;
for(int appointment : appointments){
numberOfAppointments += appointment;
}
JOptionPane.showMessageDialog(null, numberOfAppointments / appointments.length);
Here is a step by step tutorial.
First, create a variable that stores the total sum of the array elements.
int sum = 0;
Then, it's the hard part!
You see how you can loop through an array with this?
for(int i = 0; i < appointments.length; i++)
And access the an element in the array using this?
appointments[i]
That is exactly what you should do! You should combine those two together!
for(int i = 0; i < appointments.length; i++)
sum += appointments[i];
If you don't quite get it, here is the English translation of the code
for each of the items in the array appointments
add the item to sum
So appointments[i] here basically means "each item in appointments".
You can also rewrite the loop in a more elegant way:
for (int appointment : appointments)
sum += apppointment;
As you can see here, if you use this kind of loop, you don't need to write appointments[i] anymore. You replace that with appointment.
Now you can just calculate the average very easily:
int average = sum / (double)appointments.length;
"Wait a minute! Why (double)?" you asked. Actually, that isn't necessary. You only need this if you want to get a result with decimal places, because an int divided by an int is always an int!

Java Dice Simulation

I am writing a dice roll program. The code works fine in working out the face and number of frequencies. How I can calculate the percentage for the frequency of each face?
import java.util.Random;
public class Dice{
public static void main (String[] args){
Random random = new Random(); // Generates random numbers
int[] array = new int[ 7 ]; // Declares the array
//Roll the die 10000 times
for ( int roll = 1; roll <=10000; roll++ ) {
/*++array[1 + random.nextInt(6)];*/
int dice = 1 + random.nextInt(6);
++array[dice];
}
System.out.printf("%s%10s\n", "Face", "Frequency");
// outputs array values
for (int face = 1; face < array.length; face++) {
System.out.printf("%4d%10d\n", face, array[face]);
}
}
}
The frequency is just the count of each face divided by the total count.
for (int face = 1; face < array.length; face++) {
System.out.printf("%4d%10f\n", face, array[face] / 10000.0);
}
The division must be performed with a double value (otherwise, an integer division would be performed and the result would always be 0), explaining why I divided with 10000.0 and not 10000.
I also changed the String format from %10d to %10f because you want to print a decimal number, not an integer. See the Formatter Javadoc for the list of all token.
Also, I suggest you make a local variable holding the total count so as not to repeat it twice.

Why won't this create multiple sets of random numbers? [duplicate]

This question already has answers here:
Random Number Generator: mainly how to stop repetition of numbers. Java
(6 answers)
Closed 9 years ago.
Ok so the objective is to generate 6 random numbers per line/row. With x number of rows (set by the user via UserInput). Each row MUST have unique numbers (non-duplicated numbers). I'm pretty sure the numbers are unique, however I can't seem to get it to have multiple rows, and I cannot figure out for the life of me what part is preventing multiple rows.
package rtg;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
public class Array {
public static void main(String[] args) {
String name;
int noTickets;
int[] numbers = new int[6];
Set<Integer> randomNumbers = new HashSet<>();
Random rand = new Random();
int ticketCount = 1;
System.out.println("Please input your name");
name = UserInput.readString();
System.out.println("Please input the number of tickets you want");
noTickets = UserInput.readInt();
System.out.println("___________________________________________\n___________________________________________");
System.out.println("___________________________________________\n___________________________________________");
System.out.println("Name: " +name+ "\nNumber of Tickets: " +noTickets+ "\nNumbers: ");
for (ticketCount = 1; ticketCount <= noTickets; ++ticketCount){
while (randomNumbers.size() < 6) {
randomNumbers.add(rand.nextInt(50) + 1);
}
int i = 0;
for (Integer n : randomNumbers) {
numbers[i++] = n;
}
System.out.print( Arrays.toString(numbers) + "\n");
}
}
}
EDIT Thanks a lot everyone, I finally got there, turns out I put the array in the wrong place (it was outside the for loop so only made 1 set of random numbers) Fixed it now. Next challange; having a comparison program to scan 90+ sets of 6 unique numbers, and comparing if any of them match a different set (per row/set >.<)
You can stuff random integers into a Set<Integer> until it has six elements:
Set<Integer> randomNumbers = new HashSet<>();
Random rand = new Random();
while (randomNumbers.size() < 6) {
randomNumbers.add(rand.nextInt(50) + 1);
}
Alternatively, you can generate the numbers 1-50, shuffle them, and pick any six elements:
List<Integer> numbers = new ArrayList<>(50); // known capacity
for (int i = 1; i <= 50; ++i) { numbers.add(i); }
Collections.shuffle(numbers);
List<Integer> sixRandomNumbers = numbers.subList(0, 6);
The first solution does extra work whenever there is a collision; this extra work goes up the greater the ratio is of desired to total numbers. The second does extra work by having to deal with all 50 numbers; the extra work goes down the greater the ratio is of desired to total numbers. It's an interesting question where the cross-over point is.
EDIT (Responding to the edit to the original question) After you use one of the above methods to generate six distinct, random numbers, you need to put them into the variables you are going to use. One way (say, using the first method) is as follows:
int[] numbers = new int[6];
Set<Integer> randomNumbers = new HashSet<>();
Random rand = new Random();
while (randomNumbers.size() < 6) {
randomNumbers.add(rand.nextInt(50) + 1);
}
System.out.println("Six random numbers: " + randomNumbers.toString());
// if you need them as an `int` array:
int i = 0;
for (Integer n : randomNumbers) {
numbers[i++] = n;
}
The numbers array replaces your variables number1, ..., number6.
Use a data type which allows you to check if the int has already been created. For example, adding them to an ArrayList<Integer>.
ArrayList<Integer> numbers = new ArrayList<Integer>();
while(numbers.size() < 6) {
int num = rand.nextInt(50) + 1;
if(!numbers.contains(num)) {
numbers.add(num);
}
}
Of course, as #sanbhat says in the comments, you can use a Set<Integer> and avoid the if() conditional entirely in the loop. However I thought this would be more intuitive for a beginner who doesn't know that the Set API will not add a duplicate element.
Save a sorted list or more efficiently a set of the previously chosen values and check your current selection against the previous ones, if it was previously chosen try again.
If you know the valid range of your random numbers and if the size of that range is not prohibitive, one simple algorithm would be as follows:
Create an array with a size equal to your number range
Consecutively fill your array with the numbers in your number range
Iterate through the list an arbitrarily large number of times; generate two pseudorandom numbers that are within your array indices, and swap the two elements at those indices
After the iteration is complete, you will have an array of uniquely represented numbers that are all within your number range that appear in a random order. This nearly exactly simulates what happens when one shuffles a deck of cards.
You can then write a simple method to consecutively pop numbers out of your array each time it is called.
An advantage of this algorithm is that it can be implemented as an array of primitives, eg. int[], without any need for the Java Collections API.

Rolling-dice class and driver

alright so i have to write a class and driver that has the user input the number of dice and the number of rolls. and then i have to make an array based off the number of dice * 6. but i get errors. like arrayindexoutofboundsexception.
after i make the array i have to fill it with random numbers and use a histogram to display the program. so the program should look like this
Please give any positive help here, im new to this programing this and i would love to learn more. also i cant seem to figure out if statements for the Y/N area to start the program
Welcome to the dice-rolling simulator!
Do you wish to run a simulaton? Y/N: x
that was an invalid option. Please try again.
Do you wish to run a simulation? Y/N: y
How many dise di you wish to roll? 2
How many rolls to you wish to make? 100000
2:######
3:####
4:###########
5:#####
6:##
7:#
8:
9:##########
10:###
11:##############
12:######
//I had to you # signs because * would not work here
here is my program updated! how do i create the histogram?
package dice;
import java.util.Scanner;
import java.util.Random;
public class Dice
{
public static Scanner in = new Scanner (System.in);
private int dice = 0;
private int roll = 0;
private int start;
private int[] diceAr;
private int[] rollAr;
private int simDice;
private String star = "*";
//****************************************************************
public Dice()
{
System.out.println("Welcome to the dice-rolling simulator!\n");
System.out.println("Do you wish to run a simulation? Y/N; ");
//start = in.nextInt();
while (true) {
System.out.print ("How Many Dice Do You Want To Roll? ");
dice = in.nextInt();
simDice = (dice * 6)-1;
diceAr = new int[simDice];
if (dice > 0)
break;
}
while (true) {
System.out.print ("How Many Times Do You Want To Roll? ");
roll = in.nextInt();
rollAr = new int[roll];
if (roll > 0)
break;
}
}
//**********************************************
// public void display()
// {
//
for ( int i = 0; i < simDice; i++)
// {
// diceAr[i] = (int)(Math.random()* simDice);
//
// }
// for(int i = 0; i<simDice; i++)
// {
// System.out.println((i + dice) + ". " + diceAr[i]);
// }
//
// }
//*********************************************************
public void display(int diceAr[], int simDice, int roll)
{
for(int i=0; i < simDice; i++)
{
diceAr[i] = (int) (Math.random()* simDice);
}
for(int i=0; i < roll; i++)
{
}
}
}
Judging from the wording of the questions the program asks and the sample histogram you give, it appears the assignment is to write a program to simulate rolling N dice M times and then make a histogram of the results (i.e. the sum of the numbers on the dice on each roll) of the rolls. So if you enter 3 dice and 100 rolls, it should be as if you rolled 3 dice by hand 100 times.
Even aside from the ArrayIndexOutOfBoundsException issue, that is not what your code is doing. Since this is admitted homework I'm not going to give any code, at least not at this point. But I do have some suggestions/questions that might help you think about the problem better and perhaps you can show us how you've changed your code after thinking about it.
First, consider actually doing the task manually. Find two or three dice and roll them, say, 20 times, and make a histogram of the result on paper. You may find just doing that by itself will give you lots of insight into what your program will have to do and keep track of.
Next, here are some questions that might help focus your thinking:
If you are rolling 2 dice, what's the lowest possible result of a roll? What's the highest?
If you are rolling 3 dice, what's the highest and lowest possible result of a roll?
If you are rolling N dice, what's the highest and lowest possible result of a roll?
When you simulate a roll, how do you determine what the result of the roll is?
What array should you track those results in and how big should it be?
How do you track the results in such a way that you can make a histogram later?
What, if anything, besides the results do you need to store?
Think this all over, do the "experiment" manually, and then get back to us with what changes you've made to your program and what new questions you may have.
You're declaring diceAr to be size 'dice', but then indexing it with a variable which goes up to 'simDice', which = dice * 6.

Categories