Implementing Random Int in Java - java

I am using Blue J for reference.
What I need to do is after defining 2 constants, MIN = 60 and MAX = 180, which I already did, I am supposed to define the processtime as a random integer between 60 and 240, instead of the constant 120.
Problem is that I am unsure how to do that.
Here is the class, TicketCounter, in which that is supposed to be implemented in.
public class TicketCounter
{
final static int PROCESS = 120;
final static int MAX_CASHIERS = 10;
final static int NUM_CUSTOMERS = 200;
final static int ARR_TIME = 20;
final static int MIN = 60;
final static int MAX = 180;
public static void main ( String[] args)
{
Customer customer;
LinkedQueue<Customer> customerQueue = new LinkedQueue<Customer>();
int[] cashierTime = new int[MAX_CASHIERS];
int totalTime, averageTime, departs;
System.out.printf("%-25.30s %-30.30s%n", "Number of Cashiers", "Average Time (in seconds)");
/** process the simulation for various number of cashiers */
for (int cashiers=0; cashiers < MAX_CASHIERS; cashiers++)
{
/** set each cashiers time to zero initially*/
for (int count=0; count < cashiers; count++)
cashierTime[count] = 0;
/** load customer queue */
for (int count=1; count <= NUM_CUSTOMERS; count++)
customerQueue.enqueue(new Customer(count*ARR_TIME));
totalTime = 0;
/** process all customers in the queue */
while (!(customerQueue.isEmpty()))
{
for (int count=0; count <= cashiers; count++)
{
if (!(customerQueue.isEmpty()))
{
customer = customerQueue.dequeue();
if (customer.getArrivalTime() > cashierTime[count])
departs = customer.getArrivalTime() + PROCESS;
else
departs = cashierTime[count] + PROCESS;
customer.setDepartureTime (departs);
cashierTime[count] = departs;
totalTime += customer.totalTime();
}
}
}
/** output results for this simulation */
averageTime = totalTime / NUM_CUSTOMERS;
System.out.printf("%10s %30s%n", (cashiers+1), averageTime);
}
}
}
Thank you in advance!

I'm not fully sure if I understand what you're looking for, but what I am certain of is that you want to randomize an integer. This can easily be done by the Random class.
What I'm not sure about is whether you want to randomize a number between 60-120 (MIN-MAX) or 60-280. Whether the case it should look something like this.
Random r = new Random();
int randomInt = r.nextInt(MAX - MIN + 1) + MIN;
This code will now result the variable to be an integer between MIN and MAX, now you can easily replace those with constants or set values to them for nice and understandable code.
For further information of what the code exactly does, I would recommend you again, to take a look at the Random class, I find it very useful in many cases.

If you have MIN and MAX, and can use Random you might do -
Random random = new Random();
int MIN = 60;
int MAX = 180;
int val = random.nextInt(MAX + 1) + MIN;
Which will generate a random value between 60 inclusive and 240 inclusive. Random.nextInt(int) which (per the Javadoc),
Returns a pseudorandom, uniformly distributed int value between 0 (inclusive) and the specified value (exclusive).

Related

searching for the highest and the smallest value in a specific range - Random

so far in the program the values were searched randomly, but I want to modify the program to search for random numbers in a given range. Generally speaking, My point is that the draw should be from the given range (from-to), and not up to 1000 random numbers as in the above code, so my question is:
How can I pass the value from and to random: rand.nextInt (?) so that the numbers are randomly drawn in a given range. so I generally need to get a printout from the program like in the question: expected output
// Create array to be searched
final int[] arrayToSearch = new int[20];
Random rnd = new Random();
for (int i = 0; i < arrayToSearch.length; i++)
arrayToSearch[i] = rnd.nextInt(1000);
System.out.println(Arrays.toString(arrayToSearch));
final int PARTITIONS = 4;
Thread[] threads = new Thread[PARTITIONS];
final int[] partitionMin = new int[PARTITIONS];
final int[] partitionMax = new int[PARTITIONS];
for (int i = 0; i < PARTITIONS; i++) {
final int partition = i;
threads[i] = new Thread(new Runnable() {
#Override
public void run() {
// Find min/max values in sub-array
int from = arrayToSearch.length * partition / PARTITIONS;
int to = arrayToSearch.length * (partition + 1) / PARTITIONS;
int min = Integer.MAX_VALUE,
max = Integer.MIN_VALUE;
for (int j = from; j < to; j++) {
min = Math.min(min, arrayToSearch[j]);
max = Math.max(max, arrayToSearch[j]);
}
partitionMin[partition] = min;
partitionMax[partition] = max;
});
so far:
partition 0: from=0, to=5, min=23, max=662 //the draw in the range 0-5, draw is outside the specified range
expected output:
partition 1: from=0, to=5, min=1, max=3 // the draw takes place within the given range 0 to 5
partition 2: from=20, to=30, min=22, max=29 //the draw takes place within the given range 20 to 30
How can I pass the value from and to random: rand.nextInt (?) so that the numbers are randomly drawn in a given range
Try it like this. This will generate values between from and to inclusive.
int from = -100;
int to = 100;
int draw = ThreadLocalRandom.current().nextInt(from, to);
You can actually generate your own Supplier to just get random numbers in a specified range.
The BiFunction returns a Supplier. And the Supplier can be called to get the a random number in the range.
BiFunction<Integer, Integer, IntSupplier> rndGen = (f,
t) -> () -> ThreadLocalRandom.current().nextInt(f, t+1);
IntSupplier rnd = rndGen.apply(from,to);
So each time rnd.getAsInt() is invoked, you will get a number in the desired range.
Note: There are of course methods that do this pretty much automatically. But I presumed you wanted to work out the logic of finding min and max yourself so I did not include those.
Class Random has method ints (long streamSize, int randomNumberOrigin, int randomNumberBound) to generate IntStream of random numbers in the given range, and then the summary statistics may be collected for such stream:
static void printMinMax(int size, int from, int to) {
IntSummaryStatistics stats = new Random()
.ints(size, from, to)
.summaryStatistics();
System.out.printf("min = %d, max = %d%n", stats.getMin(), stats.getMax());
}
Test:
printMinMax(20, 20, 200); // min = 30, max = 198
Create a random number of your choosing however you want.
If it's under your From value, add your From value to it.
If it's over your To value mod it by your To value.

Java Loops and Random numbers

Hi I am having some problems with using random numbers inside of loops.
private void SetMines()
{
Random randRowGen = new Random();
Random randColGen = new Random();
int mineCount = 0;
int numMines = (ROWS * COLUMNS)* (int)0.156;
while(mineCount <= numMines)
{
int randRow = randRowGen.nextInt(ROWS)+1;
int randCol = randColGen.nextInt(COLUMNS)+1;
grid[randRow][randCol] = new Character('*');
mineCount++;
}
}
Here is my method it is going through an array size 25 * 25 and picking random spots and putting "mines" there. The only problem is it only selects one location to put a "mine" in and it needs to put 97 mines in random spots.
Any help will be appreciated thanks!!
Your numMines calculation will always return 0, because when you cast a double that is less than 1 to an int, it will be set to 0, which means that the statement in your while loop will only be run a single time, hence only a single mine being placed.
The problem isn't Random, it's int numMines = (ROWS * COLUMNS)* (int)0.156;. Have you checked what that value is? It's 0, because (int) 0.156 equals 0.
Perhaps you want int numMines = (int) ((double) 0.156 * ROWS * COLUMNS);. The problem with integer maths is that you can lose a LOT of precision.
Make your computer suffer and make it drop all those mines.
Remember. The definition of "computation" is "to force a machine do a boring job that nobody else would like to do" :-)
public static void main(String[] args) {
int rows = 25;
int cols = 25;
boolean[][] mines = new boolean[rows][cols];
while(mineCount(mines) < 97){
dropMine(mines);
}
for(int i=0;i<rows;i++){
for(int j=0;j<cols;j++){
System.out.print("[");
if (mines[i][j]){
System.out.print("*");
}else{
System.out.print(" ");
}
System.out.print("] ");
}
System.out.println();
}
}
private static void dropMine(boolean[][] mines) {
int x = (int)(Math.random()*25);
int y = (int)(Math.random()*25);
mines[x][y] = true;
}
private static int mineCount(boolean[][] mines) {
int count = 0;
for(int i=0;i<25;i++){
for(int j=0;j<25;j++){
if (mines[i][j]){
count++;
}
}
}
return count;
}

TreeSet search taking long time ,puzzle: to find lucky numbers

It actually is problem to find lucky number - those numbers whose sum of digits and sum of square of digits are prime. I have implemented Sieve of Eratosthenes. Now to optimize it further I commented my getDigitSum method, that I suppose was heavy and replaced with two hard-coded value , but it is still taking minutes to solve one test case. Here is a reference to actual problem asked
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Set;
import java.util.TreeSet;
public class Solution {
private static int[] getDigitSum(long num) {
long sum = 0;
long squareSum = 0;
for (long tempNum = num; tempNum > 0; tempNum = tempNum / 10) {
if (tempNum < 0) {
sum = sum + tempNum;
squareSum = squareSum + (tempNum * tempNum);
} else {
long temp = tempNum % 10;
sum = sum + temp;
squareSum = squareSum + (temp * temp);
}
}
int[] twosums = new int[2];
twosums[0] = Integer.parseInt(sum+"");
twosums[1] = Integer.parseInt(squareSum+"");
// System.out.println("sum Of digits: " + twoDoubles[0]);
// System.out.println("squareSum Of digits: " + twoDoubles[1]);
return twosums;
}
public static Set<Integer> getPrimeSet(int maxValue) {
boolean[] primeArray = new boolean[maxValue + 1];
for (int i = 2; i < primeArray.length; i++) {
primeArray[i] = true;
}
Set<Integer> primeSet = new TreeSet<Integer>();
for (int i = 2; i < maxValue; i++) {
if (primeArray[i]) {
primeSet.add(i);
markMutiplesAsComposite(primeArray, i);
}
}
return primeSet;
}
public static void markMutiplesAsComposite(boolean[] primeArray, int value) {
for (int i = 2; i*value < primeArray.length; i++) {
primeArray[i * value] = false;
}
}
public static void main(String args[]) throws NumberFormatException,
IOException {
// getDigitSum(80001001000l);
//System.out.println(getPrimeSet(1600));
Set set = getPrimeSet(1600);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int totalCases = Integer.parseInt(br.readLine());
for (int cases = 0; cases < totalCases; cases++) {
String[] str = br.readLine().split(" ");
long startRange = Long.parseLong(str[0]);
long endRange = Long.parseLong(str[1]);
int luckyCount = 0;
for (long num = startRange; num <= endRange; num++) {
int[] longArray = getDigitSum(num); \\this method was commented for testing purpose and was replaced with any two hardcoded values
if(set.contains(longArray[0]) && set.contains(longArray[1])){
luckyCount++;
}
}
System.out.println(luckyCount);
}
}
}
what I should use to cache the result so that it takes lesser amount of time to search, currently it takes huge no. of minutes to complete 10000 test cases with range 1 99999999999999(18 times 9 -the worst case) , even thought the search values have been hard-coded for testing purpose( 1600, 1501 ).
You need a different algorithm. Caching is not your problem.
If the range is large - and you can bet some will be - even a loop doing almost nothing would take a very long time. The end of the range is constrained to be no more than 1018, if I understand correctly. Suppose the start of the range is half that. Then you'd iterate over 5*1017 numbers. Say you have a 2.5 GHz CPU, so you have 2.5*109 clock cycles per second. If each iteration took one cycle, that'd be 2*108 CPU-seconds. A year has about 3.1*107 seconds, so the loop would take roughly six and a half years.
Attack the problem from the other side. The sum of the squares of the digits can be at most 18*92, that's 1458, a rather small number. The sum of the digits itself can be at most 18*9 = 162.
For the primes less than 162, find out all possible decompositions as the sum of at most 18 digits (ignoring 0). Discard those decompositions for which the sum of the squares is not prime. Not too many combinations are left. Then find out how many numbers within the specified range you can construct using each of the possible decompositions (filling with zeros if required).
There are few places in this implementation that can be improved. In order to to start attacking the issues i made few changes first to get an idea of the main problems:
made the total start cases be the value 1 and set the range to be a billion (1,000,000,000) to have a large amount of iterations. also I use the method "getDigitSum" but commented out the code that actually makes the sum of digits to see how the rest runs: following are the methods that were modified for an initial test run:
private static int[] getDigitSum(long num) {
long sum = 0;
long squareSum = 0;
// for (long tempNum = num; tempNum > 0; tempNum = tempNum / 10) {
// if (tempNum < 0) {
// sum = sum + tempNum;
// squareSum = squareSum + (tempNum * tempNum);
// } else {
// long temp = tempNum % 10;
// sum = sum + temp;
// squareSum = squareSum + (temp * temp);
//
// }
// }
int[] twosums = new int[2];
twosums[0] = Integer.parseInt(sum+"");
twosums[1] = Integer.parseInt(squareSum+"");
// System.out.println("sum Of digits: " + twoDoubles[0]);
// System.out.println("squareSum Of digits: " + twoDoubles[1]);
return twosums;
}
and
public static void main(String args[]) throws NumberFormatException,
IOException {
// getDigitSum(80001001000l);
//System.out.println(getPrimeSet(1600));
Set set = getPrimeSet(1600);
//BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int totalCases = 1;
for (int cases = 0; cases < totalCases; cases++) {
//String[] str = br.readLine().split(" ");
long startRange = Long.parseLong("1");
long endRange = Long.parseLong("1000000000");
int luckyCount = 0;
for (long num = startRange; num <= endRange; num++) {
int[] longArray = getDigitSum(num); //this method was commented for testing purpose and was replaced with any two hardcoded values
if(set.contains(longArray[0]) && set.contains(longArray[1])){
luckyCount++;
}
}
System.out.println(luckyCount);
}
}
Running the code takes 5 minutes 8 seconds.
now we can start optimizing it step by step. I will now mention the various points in the implementation that can be optimized.
1- in the method getDigitSum(long num)
int[] twosums = new int[2];
twosums[0] = Integer.parseInt(sum+"");
twosums[1] = Integer.parseInt(squareSum+"");
the above is not good. on every call to this method, two String objects are created , e.g. (sum+"") , before they are parsed into an int. considering the method is called billion times in my test, that produces two billion String object creation operations. since you know that the value is an int (according to the math in there and based on the links you provided), it would be enough to use casting:
twosums[0] = (int)sum;
twosums[1] = (int)squareSum;
2- In the "Main" method, you have the following
for (long num = startRange; num <= endRange; num++) {
int[] longArray = getDigitSum(num); \\this method was commented for testing purpose and was replaced with any two hardcoded values
if(set.contains(longArray[0]) && set.contains(longArray[1])){
luckyCount++;
}
}
here there are few issues:
a- set.contains(longArray[0]) will create an Integer object (with autoboxing) because contains method requires an object. this is a big waste and is not necessary. in our example, billion Integer objects will be created. Also, usage of set, whether it is a treeset or hash set is not the best for our case.
what you are trying to do is to get a set that contains the prime numbers in the range 1 .. 1600. this way, to check if a number in the range is prime, you check if it is contained in the set. This is not good as there are billions of calls to the set contains method. instead, your boolean array that you made when filling the set can be used: to find if the number 1500 is prime, simply access the index 1500 in the array. this is much faster solution. since its only 1600 elements (1600 is greater than max sum of sqaures of digits of your worst case), the wasted memory for the false locations is not an issue compared to the gain in speed.
b- int[] longArray = getDigitSum(num);
an int array is being allocated and returned. that will happen billion times. in our case, we can define it once outside the loop and send it to the method where it gets filled. on billion iterations, this saved 7 seconds, not a big change by itslef. but if the test cases are repeated 1000 times as you plan, that is 7000 second.
therefore, after modifying the code to implement all of the above, here is what you will have:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Set;
import java.util.TreeSet;
public class Solution {
private static void getDigitSum(long num,int[] arr) {
long sum = 0;
long squareSum = 0;
// for (long tempNum = num; tempNum > 0; tempNum = tempNum / 10) {
// if (tempNum < 0) {
// sum = sum + tempNum;
// squareSum = squareSum + (tempNum * tempNum);
// } else {
// long temp = tempNum % 10;
// sum = sum + temp;
// squareSum = squareSum + (temp * temp);
//
// }
// }
arr[0] = (int)sum;
arr[1] = (int)squareSum;
// System.out.println("sum Of digits: " + twoDoubles[0]);
// System.out.println("squareSum Of digits: " + twoDoubles[1]);
}
public static boolean[] getPrimeSet(int maxValue) {
boolean[] primeArray = new boolean[maxValue + 1];
for (int i = 2; i < primeArray.length; i++) {
primeArray[i] = true;
}
for (int i = 2; i < maxValue; i++) {
if (primeArray[i]) {
markMutiplesAsComposite(primeArray, i);
}
}
return primeArray;
}
public static void markMutiplesAsComposite(boolean[] primeArray, int value) {
for (int i = 2; i*value < primeArray.length; i++) {
primeArray[i * value] = false;
}
}
public static void main(String args[]) throws NumberFormatException,
IOException {
// getDigitSum(80001001000l);
//System.out.println(getPrimeSet(1600));
boolean[] primeArray = getPrimeSet(1600);
//BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int totalCases = 1;
for (int cases = 0; cases < totalCases; cases++) {
//String[] str = br.readLine().split(" ");
long startRange = Long.parseLong("1");
long endRange = Long.parseLong("1000000000");
int luckyCount = 0;
int[] longArray=new int[2];
for (long num = startRange; num <= endRange; num++) {
getDigitSum(num,longArray); //this method was commented for testing purpose and was replaced with any two hardcoded values
if(primeArray[longArray[0]] && primeArray[longArray[1]]){
luckyCount++;
}
}
System.out.println(luckyCount);
}
}
}
Running the code takes 4 seconds.
the billion iterations cost 4 seconds instead of 5 minutes 8 seconds, that is an improvement. the only issue left is the actual calculation of the sum of digits and sum of squares of digits. that code i commented out (as you can see in the code i posted). if you uncomment it, the runtime will take 6-7 minutes. and here, there is nothing to improve except if you find some mathematical way to have incremental calculation based on previous results.

Java/Android Biased Number Generator

I have been set a task to create a Android app in which the user chooses four numbers (1-6), I then compare it against four randomly generated numbers and then tell them how many of there numbers were correct.
My problem is that whenever I generate any numbers the first three shown are always the same, except from the last number.
Random a1 = new Random();
random1 = new ArrayList<Integer>();
for (int index = 0; index < 6; index++)
{
random1.add(a1.nextInt(5)+ 1);
}
Random a2 = new Random();
random2 = new ArrayList<Integer>();
for (int index = 0; index < 6; index++)
{
random2.add(a2.nextInt(5)+ 1);
}
This is the code I use for the random number generation, each number uses the exact same code, which makes it even more confusing, if they were all the same I could understand that because it's the same code it generates the same number or something along those lines but the last one is always different, any help would always be appreciated.
Try not create two Random instances but reuse single instance instead. May be two Randoms with close seeds produces close output.
Check if below code works for you. Code taken from http://www.javapractices.com/topic/TopicAction.do?Id=62. Modified according to your requirements.
public final class RandomRange {
public static final void main(String... aArgs) {
int START = 1;
int END = 6;
Random random = new Random();
List<Integer> first = new ArrayList<Integer>();
List<Integer> second = new ArrayList<Integer>();
for (int idx = 1; idx <= END; ++idx) {
first.add(showRandomInteger(START, END, random));
second.add(showRandomInteger(START, END, random));
}
System.out.println(first);
System.out.println(second);
first.retainAll(second);//Find common
System.out.println(first);
}
private static int showRandomInteger(int aStart, int aEnd, Random aRandom) {
if (aStart > aEnd) {
throw new IllegalArgumentException("Start cannot exceed End.");
}
// get the range, casting to long to avoid overflow problems
long range = (long) aEnd - (long) aStart + 1;
// compute a fraction of the range, 0 <= frac < range
long fraction = (long) (range * aRandom.nextDouble());
int randomNumber = (int) (fraction + aStart);
return randomNumber;
}
}

Does Java's Random Object create random numbers through equal opportunity?

I'm trying to write a short program that plays a dice game (normal 6 sided dice) for me. The first roll's number is added to the score. After the first roll, if I roll a 6 then the game stops and the score is recorded (without adding the 6). If a 6 is rolled on the first roll, that's fine and it's added like any other number 1 through 5. I'm trying to run a bunch of iterations of this game such that I have a long list of scores pre-bust (a bust being a rolled 6). I rearrange those scores to be in order from smallest to largest and then find the median of the list which is the score at which it is optimal to stop.
For some reason I keep getting 13 when I run the program but I know for a fact that the answer should be 15. Would using Random in Java would have some sort of effect on the median? I don't exactly know how Random generates the numbers and whether it creates them with equal opportunity. Also, is there anything that just pops out that shouldn't work?
import java.util.*;
public class DiceRoller {
private static Random r = new Random();
private static final int games = 10001;
private static int[] totalScores = new int[games];
private static int index = 0;
public static void main(String[] args) {
int score = 0; boolean firstRoll = true;
while (index < games) {
int roll = roll();
if (firstRoll) {
score += roll;
firstRoll = false;
} else {
if (roll == 6) {
totalScores[index] = score;
index++;
score = 0; firstRoll = true;
} else {
score += roll;
}
}
}
System.out.println("The median is " + median() + ".");
}
public static int roll() {
return r.nextInt(6) + 1;
}
public static int median() {
Arrays.sort(totalScores);
int temp = totalScores[games / 2];
return temp;
}
}
You get 13 because that's the correct result. A little mathematics: if S is the random variable representing the score of any one of these games, then you can consider the Probability generating function f(z) of S. From the description of the game, this probability generating function satisfies the equation:
f(z) = (z + z^2 + z^3 + z^4 + z^5 + z^6) / 36 + f(z)(z + z^2 + z^3 + z^4 + z^5) / 6
This takes a bit of thought, or familiarity with this sort of construction: the left-hand term on the right-hand side takes account of the probabilities of getting 1 through 6 in a simple 2-roll game; the right-hand term involving f(z) takes account of games involving 3 or more rolls, expressing them in terms of the final pre-6 roll (which must be in the range 1 through 5) and the preceding rolls, whose probabilities we can express recursively using f again.
Anyway, after getting this far, one can rearrange to describe f as a rational function of z, and then expand as a power series, which begins:
f(z) = 1/36*z + 7/216*z^2 + 49/1296*z^3 + 343/7776*z^4 + 2401/46656*z^5 + 16807/279936*z^6 + 63217/1679616*z^7 + 388087/10077696*z^8 + 2335585/60466176*z^9 + 13681927/362797056*z^10 + 77103313/2176782336*z^11 + 409031959/13060694016*z^12 + 2371648321/78364164096*z^13 + 13583773735/470184984576*z^14 + ...
(I used Pari/GP to get this.)
The coefficient of z^k then describes the probability of the value of the game being k; thus there's a 1 in 36 chance of the score being 1, a 7 in 216 chance of getting 2, and so on. The sum of the first 12 coefficients is 0.472828864487196328..., while the sum of the first 13 coefficients is 0.5030933144224321950968.... So the median is indeed 13.
To provide an independent check, I wrote a quick Python program:
from __future__ import division
import random
def roll():
return random.randint(1, 6)
def play():
score = roll()
while True:
throw = roll()
if throw == 6:
break
score += throw
return score
all_scores = sorted(play() for _ in xrange(1000001))
print "median is: ",all_scores[len(all_scores) // 2]
print "fraction of scores <= 12: ",all_scores.index(13) / len(all_scores)
print "fraction of scores <= 13: ",all_scores.index(14) / len(all_scores)
Sure enough, here are the results:
iwasawa:~ mdickinson$ python dice_game.py
median is: 13
fraction of scores <= 12: 0.472811527188
fraction of scores <= 13: 0.502863497137
So to answer your question, the results you're seeing are not evidence of any sort of weakness in Java's random number generation.
Random is not perfectly random and has some deficiencies. However for this use case you are very unlikely to notice the difference. You can assume every value 1 to 6 is equally likely.
For comparison here is another solution which counts the number of occurrences of a total rather than recording every value. As you can see this performs well even if you have 1000x more games. This works best when you have a small number of outcomes and a high number duplicates. It is naturally sorted.
import java.util.Random;
public class DiceRoller {
private static final int MAX_VALUE = 300; // assume at most this total
private static final int GAMES = 10000001;
public static void main(String... args) {
int[] count = new int[MAX_VALUE];
Random rand = new Random();
for (int i = 0; i < GAMES; i++)
count[totalScore(rand)]++;
System.out.println("The median is " + median(count, GAMES) + ".");
}
private static int median(int[] count, int games) {
int findTotal = games/2;
for (int i = 0; i < count.length; i++) {
findTotal -= count[i];
if (findTotal <= 0) return i;
}
throw new AssertionError();
}
private static int totalScore(Random rand) {
int total = rand.nextInt(6) + 1;
for(int n;(n = rand.nextInt(6) + 1) != 6;)
total += n;
return total;
}
}
Here is some code that shows you the distribution of the results. It doesn't really answer the question, but maybe it helps you in your research.
package so7297660;
import java.util.Random;
public class DiceRoller {
private static final int N = 10000000;
private static final Random r = new Random();
private static final int[] result = new int[100];
public static int roll() {
return r.nextInt(6) + 1;
}
private static int singleGame() {
int score = roll();
while (true) {
int roll = roll();
if (roll == 6) {
return score;
} else {
score += roll;
}
}
}
private static int median() {
int n = 0;
for (int i = 0; i < result.length; i++) {
if (n + result[i] >= N / 2) {
return i;
}
n += result[i];
}
throw new IllegalStateException();
}
public static void main(String[] args) {
for (int i = 0; i < N; i++) {
int score = singleGame();
int index = Math.min(score, result.length - 1);
result[index]++;
}
for (int i = 0; i < result.length; i++) {
System.out.println(i + "\t" + result[i]);
}
System.out.println("median\t" + median());
}
}

Categories

Resources