The program I wrote simulates rolling dice and attempts to calculate the probability of rolling a six in 4 rolls. The issue I'm having is it always calculates 0.66 when it should be around 0.50 and I can't figure out why.
public class Die {
int outcome;
void roll() {
double x = Math.random();
x = 1.0 + (x * 6.0);
outcome = (int) Math.floor(x);
}
}
public class Application {
public static void main(String[] args) {
float sixesIn4 = 0F;
int sixesIn24 = 0;
double sixIn4Probability;
for (int k = 0; k < rolls; k++) {
for (int i = 0; i < 4; i++) {
die.roll();
if (die.outcome == 6) {
sixesIn4++;
}
}
}
sixIn4Probability = sixesIn4 / rolls;
System.out.println(sixIn4Probability);
}
}
Can anyone help me?
The probability of rolling at least one six in four rolls is 1-(5/6)**4, which is just over 0.5.
You are calculating the expected number of sixes from 4 rolls, which is 4*(1/6), 0.67.
You just need to increment your count once for each group of 4 rolls. The smallest change, without rewriting your whole code, is to add a break statement in your inner loop:
for (int i = 0; i < 4; i++) {
die.roll();
if (die.outcome == 6) {
sixesIn4++;
break;
}
}
That way you only count each group of 4 once, if it has a six in it, instead of counting the number of sixes you get from it.
There are a couple of problems in your code. Firstly, you are generating floating point random numbers and then converting to ints. Better to just generate ints. Secondly you are counting all 6s rolled, not just the sequence of rolls that result in at least 1 six.
Split out your 'at least 1 six' into a separate method:
private boolean atLeastOneSix() {
for (int i = 0; i < 4; i++) {
if (random.nextInt(6) + 1 == 6)
return true;
}
return false;
}
Then your counting becomes more obvious:
int sixCount = 0;
for (int t = 0; t < trials; t++) {
if (atLeastOneSix())
sixCount++;
}
double prob = 1.0 * sixCount / trials;
If you are comfortable with streams:
IntStream.range(4).map(i -> random.nextInt(6) + 1).anyMatch(r -> r == 6);
And
long sixCount = IntStream.range(trials).filter(i -> atLeastOneSix()).count();
You want to keep track of a boolean in each roll to determine if there are one or more sixes. My sample gives 0.526, which given your comments should be (close to) correct.
class Die {
int outcome;
void roll() {
double x = Math.random();
x = 1.0 + (x * 6.0);
outcome = (int)Math.floor(x);
}
}
public class Application {
public static void main(String[] args) {
int rolls = 1000;
Die die = new Die();
float sixesIn4 = 0F;
double sixIn4Probability;
boolean sixinRol;
for (int k = 0; k < rolls; k++) {
sixinRol = false;
for (int i = 0; i < 4; i++) {
die.roll();
if (die.outcome == 6) {
sixinRol = true;
}
}
if (sixinRol) sixesIn4 += 1;
}
sixIn4Probability = sixesIn4 / rolls;
System.out.println(sixIn4Probability);
}
}
Related
I'm writing a program in java that basically simulates a random walk by moving 1 x or y value for each step. Ex. starts at (0, 0), using Math.random, I can x++ or y-- which changes the x or y coordinate by one value. This walk terminates once the absolute value of both the x and y value added together gives me the number inputted (by command line argument). There are two command line integers, the first being the number just mentioned and the second being the trials, which is the number of times I have to simulate this walk. By the end of this program, a step counter keeps track of how many steps were taken in each trial, and it is then averaged to give the average number of steps it took for each trial to add up to the number.
The problem I am having is that when I run my program, no error shows up or anything, it just doesn't run which gives me the idea that the runtime is just too long and there are too many iterations to go through. The input for the trials variable is going to be around 100000 to 1000000. I would appreciate any help or ideas on fixing this problem.
Here is my code for the program:
public class RandomWalkers {
public static void main(String [] args) {
int r = Integer.parseInt(args[0]);
double trials = Double.parseDouble(args[1]);
double avgSteps = 0;
double totalSteps = 0;
int x = 0;
int y = 0;
int steps;
for(int j = 0; j < trials; j++ ) {
int trialDistance = 0;
for(steps = 0; trialDistance != r; steps++) {
double random = Math.random();
if(random < 0.25) {
x++;
} else if((0.25 < random) && (random < 0.50)) {
x--;
} else if((0.50 < random) && (random < 0.75)) {
y++;
} else if((0.75 < random) && (random < 1.00)) {
y--;
} else {}
totalSteps = totalSteps + steps;
trialDistance = Math.abs(x) + Math.abs(y);
}
}
avgSteps = totalSteps / trials;
System.out.println("average number of steps = " + avgSteps);
}
}
ok so here an updated version.
public class RandomWalkers {
public static void main(String[] args) {
int radius = Integer.parseInt(args[0]);
int trials = Integer.parseInt(args[1]);
walk(radius, trials);
}
public static void walk(int radius, int trials) {
//not really a radius, but nvm
int totalSteps = 0;
for (int t = 0; t < trials; t++) {
//you need to reset the x and y for every trial!
int x = 0;
int y = 0;
int steps = 0;
while (Math.abs(x) + Math.abs(y) != radius) {
double random = Math.random();
if (random < 0.25) {
x++;
} else if (random < 0.50) {
x--;
} else if (random < 0.75) {
y++;
} else {
y--;
}
steps++;
}
//take this out of the loop or increase only by one!
totalSteps += steps;
}
double avgSteps = totalSteps / (double) trials;
System.out.println("average number of steps = " + avgSteps);
}
}
i moved everthing to another method (doesnt change anything) but what you can change:
remove the first part of the else if's cause if the random is smaller than .25 it wont even trigger the else. You can also change the last one to a normal "else".
take the "totalsteps = totalsteps + steps" out of the loop -> you dont want to add it with every step.
i guess its better to handle the trials as an int and only cast it to a double for the calculation of the avg.
you need to update the x,y and steps with every trial, else the second trial would be immediatly done with the result of the first
it should be fast enough to make 1mil trials or whatever, just be carefull with the "radius" its going to increase the time dramatically
I have this question I am trying to solve. I have tried coding for the past 4 hours.
An integer is defined to be a Smart number if it is an element in the infinite sequence
1, 2, 4, 7, 11, 16 …
Note that 2-1=1, 4-2=2, 7-4=3, 11-7=4, 16-11=5 so for k>1, the kth element of the sequence is equal to the k-1th element + k-1. For example, for k=6, 16 is the kth element and is equal to 11 (the k-1th element) + 5 ( k-1).
Write function named isSmart that returns 1 if its argument is a Smart number, otherwise it returns 0. So isSmart(11) returns 1, isSmart(22) returns 1 and isSmart(8) returns 0
I have tried the following code to
import java.util.Arrays;
public class IsSmart {
public static void main(String[] args) {
// TODO Auto-generated method stub
int x = isSmart(11);
System.out.println(x);
}
public static int isSmart(int n) {
int[] y = new int[n];
int j = 0;
for (int i = 1; i <= n; i++) {
y[j] = i;
j++;
}
System.out.println(Arrays.toString(y));
for (int i = 0; i <= y.length; i++) {
int diff = 0;
y[j] = y[i+1] - y[i] ;
y[i] = diff;
}
System.out.println(Arrays.toString(y));
for (int i = 0; i < y.length; i++) {
if(n == y[i])
return 1;
}
return 0;
}
}
When I test it with 11 it is giving me 0 but it shouldn't. Any idea how to correct my mistakes?
It can be done in a simpler way as follows
import java.util.Arrays;
public class IsSmart {
public static void main(String[] args) {
int x = isSmart(11);
System.out.println("Ans: "+x);
}
public static int isSmart(int n) {
//------------ CHECK THIS LOGIC ------------//
int[] y = new int[n];
int diff = 1;
for (int i = 1; i < n; i++) {
y[0] =1;
y[i] = diff + y[i-1];
diff++;
}
//------------ CHECK THIS LOGIC ------------//
System.out.println(Arrays.toString(y));
for (int i = 0; i < y.length; i++) {
if(n == y[i])
return 1;
}
return 0;
}
}
One of the problems is the way that your populating your array.
The array can be populated as such
for(int i = 0; i < n; i++) {
y[i] = (i == 0) ? 1 : y[i - 1] + i;
}
The overall application of the function isSmart can be simplified to:
public static int isSmart(int n) {
int[] array = new int[n];
for(int i = 0; i < n; i++) {
array[i] = (i == 0) ? 1 : array[i - 1] + i;
}
for (int i = 0; i < array.length; i++) {
if (array[i] == n) return 1;
}
return 0;
}
Note that you don't need to build an array:
public static int isSmart(int n) {
int smart = 1;
for (int i = 1; smart < n; i++) {
smart = smart + i;
}
return smart == n ? 1 : 0;
}
Here is a naive way to think of it to get you started - you need to fill out the while() loop. The important thing to notice is that:
The next value of the sequence will be the number of items in the sequence + the last item in the sequence.
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
System.out.println(isSmart(11));
}
public static int isSmart(int n) {
ArrayList<Integer> sequence = new ArrayList<Integer>();
// Start with 1 in the ArrayList
sequence.add(1);
// You need to keep track of the index, as well as
// the next value you're going to add to your list
int index = 1; // or number of elements in the sequence
int nextVal = 1;
while (nextVal < n) {
// Three things need to happen in here:
// 1) set nextVal equal to the sum of the current index + the value at the *previous* index
// 2) add nextVal to the ArrayList
// 3) incriment index by 1
}
// Now you can check to see if your ArrayList contains n (is Smart)
if (sequence.contains(n)) { return 1; }
return 0;
}
}
First think of a mathematical solution.
Smart numbers form a sequence:
a0 = 1
an+1 = n + an
This gives a function for smart numbers:
f(x) = ax² + bx + c
f(x + 1) = f(x) + x = ...
So the problem is to find for a given y a matching x.
You can do this by a binary search.
int isSmart(int n) {
int xlow = 1;
int xhigh = n; // Exclusive. For n == 0 return 1.
while (xlow < xhigh) {
int x = (xlow + xhigh)/2;
int y = f(x);
if (y == n) {
return 1;
}
if (y < n) {
xlow = x + 1;
} else {
xhigh = x;
}
}
return 0;
}
Yet smarter would be to use the solution for x and look whether it is an integer:
ax² + bx + c' = 0 where c' = c - n
x = ...
I was playing around with this and I noticed something. The smart numbers are
1 2 4 7 11 16 22 29 ...
If you subtract one you get
0 1 3 6 10 15 21 28 ...
0 1 2 3 4 5 6 7 ...
The above sequence happens to be the sum of the first n numbers starting with 0 which is n*(n+1)/2. So add 1 to that and you get a smart number.
Since n and n+1 are next door to each other you can derive them by reversing the process.
Take 29, subtract 1 = 28, * 2 = 56. The sqrt(56) rounded up is 8. So the 8th smart number (counting from 0) is 29.
Using that information you can detect a smart number without a loop by simply reversing the process.
public static int isSmart(int v) {
int vv = (v-1)*2;
int sq = (int)Math.sqrt(vv);
int chk = (sq*(sq+1))/2 + 1;
return (chk == v) ? 1 : 0;
}
Using a version which supports longs have verified this against the iterative process from 1 to 10,000,000,000.
For an assignment I am doing for one of my classes, we have to implement a Sieve of Eratosthenes. I have tried seven times to get a code that works and have tried incorporating numerous solutions I've researched. I finally have one that will output numbers. Unfortunately, it prints both composite and prime numbers, and doesn't print 2.
My code is as follows:
public class EratosthenesSieveAttempt6 {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
int limit;
System.out.print("Please enter the highest number to check "
+ "(number must be greater than 2): ");
limit = keyboard.nextInt();
while (limit <= 2){
System.out.println("Error - number must be greater than 2.");
System.out.println("Please enter the highest number to check: ");
limit = keyboard.nextInt();
}
boolean[] numbers = new boolean[limit + 1];
int newPrime = 2;
for(int i = 0; i < limit + 1; i++){
numbers[i] = true;
}
for(int j = 1; j < limit + 1; j++) {
if (j % 2 == 0) {
numbers[j] = false;
}
for(int k = j + 1; k < limit + 1; k++) {
if(numbers[k] == true){
j = k;
System.out.println(k);
}
}
}
}
}
I'm suspecting that there is a problem with my loops. I fixed the i and j variables for my first two loops so that it would print out from 2 onward, the problem seems to be that it's not marking the composite numbers as false after I've initialized the array to true.
Thank you in advance for your help.
Here's an implementation of the Sieve of Eratosthenes I wrote the other day:
import java.util.BitSet;
public static BitSet composite(int max) {
BitSet composite = new BitSet(max);
max = composite.size();
for (int i = 4; i < max; i += 2) composite.set(i, true);
for (int i = 9; i < max; i += 6) composite.set(i, true);
int p = 5;
while (p*p < max) {
if (!composite.get(p)) {
for (int i = p*p; i < max; i += p*2) composite.set(i, true);
}
p += 2;
if (p*p >= max) break;
if (!composite.get(p)) {
for (int i = p*p; i < max; i += p*2) composite.set(i, true);
}
p += 4;
}
return composite;
}
Notes:
BitSet allocates 64-bit words, so the size may be larger than you requested (for example, if you ask it to go up to 1000, it will go up to 1024; that's the reason for max = composite.size() near the top)
Gets the 2's, 3's out of the way explicitly, and then
Relies on the fact that all primes larger than 3 are congruent to either 1 or 5 mod 6; this is the reason the final loop alternates between adding 2 and 4
It returns a BitSet that tells you which numbers are composite. One way to extract just the primes from it would be:
public static int[] primes(BitSet composite) {
int size = composite.size() - 2 - composite.cardinality();
int[] primes = new int[size];
int index = 0;
for (int i = 2; i < composite.size(); i++) {
if (!composite.get(i)) primes[index++] = i;
}
return primes;
}
I need to find the mean, median, mode, and range from an input file.
[input file has the numbers{60,75,53,49,92,71}]
I don't know how to print the calculations from the range out or calculate the mode.
It's pretty bad, I'm very new to Java.
It would be great if anyone could help me with it.
import java.io.*;
import java.util.*;
public class grades {
public static double avg(double[] num) {
double total = 0;
int j = 0;
for (; j < num.length; j++) {
total += num[j];
}
return (total / j);
}
public double getRange(double[] numberList) {
double initMin = numberList[0];
double initMax = numberList[0];
for (int i = 1; i <= numberList.length; i++) {
if (numberList[i] < initMin) initMin = numberList[i];
if (numberList[i] > initMax) initMax = numberList[i];
double range = initMax - initMin;
}
return range;
}
public static void main(String[] args) throws IOException {
double[] num = new double[12];
File inFile = new File("data.txt");
Scanner in = new Scanner(inFile);
for (int i = 0; i < num.length && in.hasNext(); i++) {
num[i] = in.nextDouble();
// System.out.println(num[i]);
}
double avg = grades.avg(num);
System.out.println("Arithmetic Mean = " + avg);
System.out.printf("Median = %.2f%n", grades.getMedian(num));
System.out.println("Range = " + range);
}
public static double getMedian(double[] num) {
int pos = (int) num.length / 2;
return num[pos];
}
}
I don't know how to print the calculations from the range out or calculate the mode.
You have already written a function to calculate the Range. Here is how you can print the Range.
System.out.println("Range = " + getRange(num));
Here is a quick code snippet to calculate the Mode:
public static double calculateMode(final double[] numberList) {
double[] cnts = new double[numberList.length];
double mode = 0, max = 0;
for (int i = 0; i < numberList.length; i++) {
/* Update Count Counter */
cnts[numberList[i]]++;
/* Check */
if (max < cnts[numberList[i]]) {
/* Update Max */
max = cnts[numberList[i]];
/* Update Mode */
mode = numberList[i];
}
}
/* Return Result */
return mode;
}
try sorting the element into an array.it will give following results:
[49,53,60,71,75,92]
suppose you stored it in array A.
int arrLength=A.length();
for(i=0,sum=0;i<arrlength;i++)
sum=sum+A[i]
mean=sum/arrLength;
median=A[arrLength/2]
I think you didn't sort the elements before finding median.
Do same thing to calculate range.It will be easier , I feel
I tried to create a simple lottery program. Here is a problem: it still prints same numbers. For example I got 33 21 8 29 21 10 as output. Everytime when random number is generated, code checks if that number is already generated, then it creates a new random number but after that it doesn't check again. I couldn't find a way to do that.
public static void main(String[] args)
{
int[] lottery = new int[6];
int randomNum;
for (int i = 0; i < 6; i++)
{
randomNum = (int) (Math.random() * 50); //Random number created here.
for (int x = 0; x < i; x++)
{
if (lottery[i] == randomNum) // Here, code checks if same random number generated before.
{
randomNum = (int) (Math.random() * 50);//If random number is same, another number generated.
}
}
lottery[i] = randomNum;
}
for (int i = 0; i < lottery.length; i++)
System.out.print(lottery[i] + " ");
}
There are 2 problems with your code:
you check if lottery[i] and randomNum are the same, it should be lottery[x]
when you re-generate a random number, you don't check it against the first numbers in lottery.
Here is a corrected version:
public static void main(String[] args) {
int[] lottery = new int[6];
int randomNum;
for (int i = 0; i < 6; i++) {
randomNum = (int) (Math.random() * 50); // Random number created here.
for (int x = 0; x < i; x++) {
if (lottery[x] == randomNum) // Here, code checks if same random number generated before.
{
randomNum = (int) (Math.random() * 50);// If random number is same, another number generated.
x = -1; // restart the loop
}
}
lottery[i] = randomNum;
}
for (int i = 0; i < lottery.length; i++)
System.out.print(lottery[i] + " ");
}
You are changing the random number while you are checking it. You need to pick one random number and check whether it is present or not.
BTW A shorter approach is to use a shuffle.
// give me all the number 1 to 50
List<Integer> list = IntStream.range(1, 51).boxed().collect(Collectors.toList());
// shuffle them.
Collections.shuffle(list);
// give me the first 6
System.out.println(list.subList(0, 6));
A simple solution, between the first (who could be very abstract for a not Java programmer) and the 2nd (not assuring the unicity of the number list).
Collection<Integer> liste = new ArrayList<Integer>();
for (int i = 0; i < 6; i++)
{
Boolean ap = false;
while (!ap)
{
Integer randomNumber = (int) (Math.random() * 50);
if (! liste.contains(randomNumber)){
liste.add(randomNumber);
ap = true;
}
}
}
for (Integer liste1 : liste) {
System.out.print(liste1+" ");
}
try this one, it creates 12 x (6 out of 45)
public static void main(String[] args) {
SecureRandom random = new SecureRandom();
for (int i = 0; i < 12; i++){
Integer[] tipp = new Integer[6];
int n = 0;
do {
int r = random.nextInt(45) + 1;
if (Arrays.asList(tipp).indexOf(r)<0){
tipp[n]= r;
n++;
}
} while (n<=5);
Arrays.sort(tipp);
System.out.println(Arrays.toString(tipp));
}
}
public static void main(String[] arg) {
int[] lottery = new int[6];
int randomNum;
c1:
for (int i = 0; i < 6; i++) {
randomNum = (int) (Math.random() * 50); // Random number created here.
if(randomNum == 0) {
continue c1;
}
for (int x = 0; x < i; x++) {
if (lottery[x] == randomNum ) // Here, code checks if same random number generated before.
{
randomNum = (int) (Math.random() * 50);// If random number is same, another number generated.
x = -1; // restart the loop
}
}
lottery[i] = randomNum;
}
for (int i = 0; i < lottery.length; i++)
System.out.print(lottery[i] + " ");
}
This is the object class for making a ticket, it will create ONE ticket with ascending values at which whatever parameters you choose. This program won't run until you have a main method that you call. Make sure to import TreeSet.
import java.util.TreeSet;
public class TicketMaker{
private int numbersPerTicket;
private int lowestNumber;
private int highestNumber;
TicketMaker(){
numbersPerTicket=0;
lowestNumber=0;
highestNumber=0;
}
TicketMaker(int numbersPerTicket,int lowestNumber,int highestNumber){
if(numbersPerTicket > 0 && lowestNumber >= 0 && highestNumber >= lowestNumber){
this.numbersPerTicket=numbersPerTicket;
this.lowestNumber=lowestNumber;
this.highestNumber=highestNumber;
}
}
public boolean printTicket(int numbersPerTicket,int lowestNumber,int highestNumber){
if(numbersPerTicket > 0 && lowestNumber >= 0 && highestNumber >= lowestNumber){
if(numbersPerTicket > highestNumber){
System.out.println("Error not in-bounds");
return false;
}
int rand;
int count=0;
System.out.println("[Ticket Printed]");
TreeSet<Integer> set = new TreeSet<>();
do{
rand = (int)(Math.random()*highestNumber)+lowestNumber;
set.add(rand);
count++;
}while(set.size() != numbersPerTicket);
System.out.println(set);
return true;
}
else{
System.out.println("Error not in-bounds");
return false;
}
}
public boolean isValidTicketData(int numbers,int lowest,int highest){
if(lowest != 1){
if(highest == numbers)
return false;
}
if(numbers <= highest){
if(numbers > 0 && lowest >= 0 && highest >= lowest)
return true;
}
return false;
}
}