Dungeons and Dragons Dice Roller Reroll - java

import java.util.*;
public class Project2Main {
public static void main(String args[]) {
Scanner kb = new Scanner(System.in);
int numSets = 0;
System.out.println("How many sets of dice would you like to roll?");
numSets = kb.nextInt();
kb.nextLine();
RollingDice roller = new RollingDice();
List<List<Integer>> diceSets = roller.rollSets(numSets);
for (List<Integer> diceRolls : diceSets) {
Integer total = sum(diceRolls);
Integer lowest = Collections.min(diceRolls);
System.out.println("Your roll total is: " + total + " and the lowest roll was a: " + lowest);
}
kb.close();
}
public static int sum(List<Integer> list) {
int sum = 0;
for (int number : list)
sum = sum + number;
return sum;
}
}
import java.util.*;
public class RollingDice {
private Random rand;
public RollingDice() {
this.rand = new Random();
}
public List<Integer> roll4d6DropLowest() {
List<Integer> retList = new ArrayList<Integer>();
for (int i = 0; i < 4; i++) {
retList.add(rand.nextInt(6) + 1);
}
retList.remove(Collections.min(retList));
return retList;
}
public List<List<Integer>> rollSets(int numSets) {
List<List<Integer>> results = new ArrayList<List<Integer>>();
for (int i = 0; i < numSets; i++) {
results.add(roll4d6DropLowest());
}
return results;
}
}
Hello Stackoverflow, I am having a small issue with this program. I am trying to make a program to roll four dice and add the three highest rolls together and then print the lowest of those THREE rolls. I made the mistake of of taking the three highest rolls, adding them together, and then printing out the lowest of the four.
How can I fix this issue? I did a lot of googling to figure out how to use lists and collections, but I can't find anything to fix this issue.
Also, how can I make it to where I force the user to select a set and to reroll that set?
Basically what I want to do is have each set assigned to a number (Set 1 is 1, Set 2 is 2, etc.), and then the user types in a number correlating to the number of sets they have, and then the lowest of the three highest rolls is re rolled.
Any help is greatly appreciated.

Using a List of Lists is a slight case of overbombing here, how about this one:
public class Project2Main {
private static Random rand = new Random(System.currentTimeMillis());
public static void main(String args[]) {
int numSets = 4; //set via Scanner, if wanted
List<Integer> dices = new ArrayList<Integer>(numSets);
for (int c = 0; c < numSets; c++) {
int roll = rand.nextInt(6) + 1;
dices.add(Integer.valueOf(roll));
System.out.println(roll);
}
int[] pair = roll4d6DropLowest(dices);
System.out.println("lowest of three highest: " + pair[0]);
System.out.println("sum of 3 highest is: " + pair[1]);
}
/**#param diceRolls Array of dice rolls
* #return return array of two ints:
0: lowest of three highest
1: sum of three highest */
private static int[] rollXd6DropLowest(List<Integer> array) {
int sum = 0;
int low = 0;
Collections.sort(array);
for (int c = (array.size() - 1); c > 0; c--) {
sum += (int) array.get(c);
if (c == 1) {
low = (int) array.get(c);
}
}
int[] pair = { low, sum };
return pair;
}
}
I admit, returning a int[] is not the best of all solutions, but for that little piece of code it should be ok.
Note the initialisation of Random by current time millis to ensure randomness.
The trick is to store the dice rolls in a List of Integers and sort them according to their "natural ordering" with the help of Collections. Highest is topmost.

Related

how swap between two array values?

When user enter number 1 smaller than number 2 swap does not work,
but when number 1 is larger than number 2 it works. I don't understand why this is occurring. I would appreciate some suggestions or help.
package javaapplication36;
public class JavaApplication36 {
static Scanner s = new Scanner(System.in);
// main method
public static void main(String[] args) {
int[] arr = new int[10];
input(arr);
System.out.println("Enter n1 :");
int n1 = s.nextInt();
System.out.println("Enter n2 : ");
int n2 = s.nextInt();
display(arr);
int temp = 0;
int index_a = index(arr, n1);
int index_b = index(arr, n2);
if (index(arr, n1) != -1 && index(arr, n2) != -1) {
temp = arr[index_a];
arr[index_a] = arr[index_b];
arr[index_b] = temp;
}
for (int i : arr) {
System.out.print(i + " ");
}
System.out.println();
}
public static void display(int[] arr) {
for (int i : arr) {
System.out.print(i + " ");
}
System.out.println();
}
public static void input(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.println("Enter number : " + (i + 1));
arr[i] = s.nextInt();
}
}
public static int index(int[] arr, int n) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == n)
return i;
}
return -1;
}
}
I tried this and could not find anything wrong. To make debugging this easier I recommend you populate your array using random numbers.
Create an instance of Random
Random rand = new Random();
And assign the output to your array variable.
arr = rand.ints(10,1,15).toArray();
The arguments to rand.ints are.
10 - the number of elements
1 - the start of the range of numbers
15 - the end of the range (not including that number)
So that call would generate 10 numbers from 1 to 14 inclusive.
One possibility for any problems could be duplicate numbers in your array and finding the correct one to swap. But I was unable to reproduce the error.

How to generate huge amount of prime numbers in java?

In order to solve a question I have to generate a list of prime numbers from 1 to 3000000, so I tried several ways to do this and unfortunately all failed...
First try: because all prime numbers bigger than 2 are odd numbers, so I first generate a list of odd numbers started with 3 called allOddNums. And then I generate a list of all composite numbers called allComposite. Then I remove all the number in allComposite from allOddNums to obtain prime numbers. Here is my code:
/** Prime Numbers Generation
* Tony
*/
import java.util.*;
public class PrimeNumG {
public static void main(String[] args) {
List <Long> allOddNums = new ArrayList<Long>();
for (long i = 3; i < 200; i += 2) {
allOddNums.add(i);
}
// composite number generator:
List <Long> allComposite = new ArrayList<Long>();
for (long a = 2; a < Math.round(Math.sqrt(3000000)); a += 2) {
for (long b = 2; b < Math.round(Math.sqrt(3000000)); b += 2) {
allComposite.add(a*b);
}
}
// remove duplicated:
Set <Long> hs = new HashSet<Long>();
hs.addAll(allComposite);
allComposite.clear();
allComposite.addAll(hs);
// remove all composite from allRealNums = allPrime
allOddNums.removeAll(allComposite);
allOddNums.add(0, (long)2);
System.out.printf("%s ", allOddNums);
Scanner sc = new Scanner(System.in);
int times = sc.nextInt();
for (int i = 0; i < times; i++) {
int index = sc.nextInt();
System.out.print(allOddNums.get(index) + " ");
}
}
}
In this case, when I need to generate a few prime numbers it works fine. However, if I want to generate until 3000000 it fails me(used up memory).
Second try: I searched online and find an algorithm called sieve of Eratosthenes. then I first generate 2, 3, 5, 7, 9...(all odd numbers + 2), then I remove every 3rd number after 3 and every 5th number after 5. The code is as below:
/** Prime Number Generator
* Tony
*/
import java.util.*;
public class Solution61 {
public static void main(String[] args) {
List<Long> l1 = new ArrayList<Long> ();
// l1 generator: 3 5 7 9 11 ...
for (long d = 3; d < 100; d += 2) {
l1.add(d);
}
l1.add(1, (long)2); // 2 3 5 ...
removeThird(l1); // rm 3rd after 3
removeFifth(l1); // rm 5th after 5, now the l1 will be prime number
Scanner sc = new Scanner(System.in);
int times = sc.nextInt();
for (int i = 0; i < times; i++) {
int index = sc.nextInt();
System.out.print(l1.get(index) + " ");
}
}
/** removeThird : remove every 3rd number after 3
* param List | return void
*/
private static void removeThird(List<Long> l) {
int i = 1;
int count = 0;
while (true) {
if (count == 3) {
l.remove(i);
count = 1;
}
i ++;
count ++;
if (i > l.size()) {
break;
}
}
}
/** removeThird : remove every 5th number after 5
* param List | return void
*/
private static void removeFifth(List<Long> l) {
int i = 2;
int count = 0;
while (true) {
if (count == 5) {
l.remove(i);
count = 1;
}
i ++;
count ++;
if (i > l.size()) {
break;
}
}
}
}
This is still not up to the task because it also runs out of memory.
3rd try:
I tried to generate from 1 to the 3000000, and then remove every number is the product of prime number and another number. The code is as below:
/** print all the prime numbers less than N
* Tony
*/
public class primeGenerator {
public static void main(String[] args) {
int n = 3000000;
boolean[] isPrime = new boolean[n];
isPrime[0] = false; // because 1 is not a prime number
for (int i = 1; i < n; i++) {
isPrime[i] = true;
} // we set 2,3,4,5,6...to true
// the real number is always (the index of boolean + 1)
for (int i = 2; i <= n; i++) {
if (isPrime[i-1]) {
System.out.println(i);
for (int j = i * i; j < n; j += i /* because j is determined by i, so the third parameter doesn't mater*/) {
isPrime[j-1] = false;
}
}
}
}
}
it still fails me, well guess 3000000 is really a big number huh? Is there any simple and brilliant rookie-friendly way to generate prime numbers below 3000000? Thx!
fourth try:
#jsheeran Is this code below what your answer means? when I hit 1093 it gets slower and slower and my IDE still crashed. Plz tell me if I misinterprete your approach, thx!
/** new approach to find prime numbers
* Tony
*/
import java.util.*;
public class PrimeG {
/** isPrime
* To determine whether a number is prime by dividing the candidate number by each prime in that list
*/
static List<Long> primes = new ArrayList<Long> ();
private static void isPrime(long n) {
boolean condition = true;
for (int i = 0; i < primes.size(); i++) {
if (n % primes.get(i) == 0) {
condition = condition && false;
}
}
if (condition) {
findNextPrime(n);
}
}
/** findNextPrime
* expand the list of prime numbers
*/
private static void findNextPrime(long n) {
primes.add(n);
}
public static void main(String[] args) {
primes.add((long)2);
primes.add((long)3);
primes.add((long)5);
primes.add((long)7);
for (int i = 8; i < 3000000; i++) {
isPrime(i);
System.out.printf("%s", primes);
}
}
}
Fixed implementation of Sieve of Eratosthenes (your third try). I believe it should satisfy your needs.
public static void main (String[] args) throws java.lang.Exception {
int n = 3000000;
boolean[] isPrime = new boolean[n+1];
for (int i = 2; i <= n; i++) {
isPrime[i] = true;
}
for (int factor = 2; factor*factor <= n; factor++) {
if (isPrime[factor]) {
for (int j = factor; factor*j <= n; j++) {
isPrime[factor*j] = false;
}
}
}
for (int i = 2; i <= n; i++) {
if (isPrime[i]) System.out.println(i);
}
}
An alternative approach would be to begin with a list of primes consisting of 2 and 3. Have a method isPrime(int) to determine whether a number is prime by dividing the candidate number by each prime in that list. Define another method, findNextPrime(), which isPrime() can call to expand the list as needed. This approach has far lower overhead than maintaining lists of all odd and composite numbers.
Memory is not an issue in your case. Array of size n = 3000000 can be defined inside the stack frame of a function. Actually array of size 10^8 can be defined safely inside a function. If you need more than that define it as a gloabal variable(Instance variable). Coming to your code there is an IndexOutOfBoundsException in your third code. You need to check for factors of a number only uptill sqrt(n). Factors exist in pairs one factor <=sqrt(n) and other >=sqrt(n). So you can optimize the sieve of Eratosthenes algorithm. Here is a link to one wonderful tutorial on various optimizations of sieve.
This can generate prime numbers up to Integer.MAX_VALUE in few milliseconds. It also doesn't take as much memory as in Sieve of Eratosthenes approach.
public class Prime {
public static IntStream generate(int limit) {
return IntStream.range(2, Integer.MAX_VALUE).filter(Prime::isPrime).limit(limit);
}
private static boolean isPrime(int n) {
return IntStream.rangeClosed(2, (int) Math.sqrt(n)).noneMatch(i -> n % i == 0);
}
}

How to create Random Numbers within a range for a specific amount of time

This is basically a tool teachers would use to generate random numbers for the position everyone is in for presentations perhaps.
It keeps creating infinite loops. What am I doing wrong? Thank you.
import java.util.Random;
import java.util.Scanner;
public class WhoGoesFirst {
public static void main(String args[]) {
Random random = new Random();
Scanner input = new Scanner(System.in);
int MIN = 1;
int students = 0;
System.out.print("How many students do you have?");
students = input.nextInt();
int comp = random.nextInt(students - MIN + 1) + MIN;
for (int number = 0; number <= students; comp++) {
System.out.println(random);
}
}
}
Your number doesn't change in a loop. Try this:
for (int number = 0; number <= students; number++) {
int comp = random.nextInt(students - MIN + 1) + MIN;
System.out.println(comp);
}

Generate a permutation x number of times and calculate probability of it's Chi Square Distribution

This question is extremely specific. I have found dozens of places telling you how to generate random permutations in Java, but it never got as far as calculating the probability of the Chi Square Distribution. Let me tell you that setting it up seemed fair enough, with many tutorials online, but one thing about this code that has really nagged me was the fact that in the second part of the assignment, I'm supposed to generate a random permutation of a string from index j where j is chosen randomly between the range of 0 and i. One method is supposed to output a probability of 1.0 all the time, which is biased and unfair, while the second method generates a probability of any number between 0 and 1.0. I've got the first part of that in part 1, but the second part I am having trouble making it not display 1.0 all the time. The assignment says that i simply steps through the array. In this circumstance, two styles of permutation generation were tried:
Method 1:
public static String generatePermutation(String prefix, String t){
int n = 6;
String s = "";
StringBuilder test = new StringBuilder(t);
if (n == 0){
System.out.println(prefix);
}
else {
for(int i = 0; i < n; i++){
int j = randInt(0, i);
char temp = test.charAt(j);
test.setCharAt(j, test.charAt(i));
test.setCharAt(i, temp);
}
s = test.toString();
return s;
}
return s;
}
public static int randInt(int min, int max) {
Random rand = new Random();
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
Method 2:
public static String generatePermutation(String prefix, String t){
char[] letters = t.toCharArray();
shuffle(letters);
String s = new String(letters);
return s;
}
public static void shuffle(char[] array){
int n = array.length;
Random rand = new Random();
while(n > 1){
int k = rand.nextInt(n--);
char temp = array[n];
array[n] = array[k];
array[k] = temp;
}
}
public static int randInt(int min, int max) {
Random rand = new Random();
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
Both methods did not seem to give me a random number probability between 0 and 1.0. The current code for part 2 of the assignment is structured like this:
package math3323assignment7;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Collections;
import org.apache.commons.math3.distribution.ChiSquaredDistribution;
import com.google.common.collect.Multiset;
import com.google.common.collect.TreeMultiset;
public class assignment7part2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
String s = "ABCDEF";
Map<String, Integer> counts = new HashMap<>();
Integer count;
int expected = (int)factorial(s.length());
for(int i = 0; i < 720000; i++){
String t = generatePermutation("",s);
count = counts.get(t);
if(count == null){
count = 1;
}
else {
count = count + 1;
}
counts.put(t, count);
System.out.println(t);
}
for(Entry<String, Integer> entry : counts.entrySet()){
System.out.println(entry.getValue() + " times: " + entry.getKey());
}
double chistat = 0.0;
for(Entry<String, Integer> entry: counts.entrySet()){
double di = entry.getValue() - expected;
chistat += di*di/expected;
}
ChiSquaredDistribution chisq = new ChiSquaredDistribution(719.0);
double prob = chisq.cumulativeProbability(chistat);
System.out.printf("ChiSquare statistic = " + chistat + " the probability is " + prob);
}
public static String generatePermutation(String prefix, String t){
char[] letters = t.toCharArray();
shuffle(letters);
String s = new String(letters);
return s;
}
public static long factorial(int n){
if (n <= 1){
return 1;
}
else {
return n * factorial(n-1);
}
}
public static void shuffle(char[] array){
int n = array.length;
Random rand = new Random();
while(n > 1){
int k = rand.nextInt(n--);
char temp = array[n];
array[n] = array[k];
array[k] = temp;
}
}
public static int randInt(int min, int max) {
Random rand = new Random();
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
}
As you can see, the Apache Math Distribution class from the Apache API is being used to create the Chi Square Distribution. A separate for loop is being used to calculate the Chi Square statistic. Unfortunately, when I run the program, the output always has a similar vein right at the very end to this:
Prints all random permutations 720,000 times
Counts all the times each permutation occurs, and print out the numbers
ChiSquare statistic = 79360.74444444438 the probability is 1.0
I want the final part to print out like this:
ChiSquare statistic = 79360.74444444438 the probability is 0.64
May you please help me fix this to where the final result of the second part of the program looks like the above line?
The expected value you are using is incorrect. Your output should demonstrate a count that is somewhere around 1000 for each random permutation. One would expect each to be exactly 1000 in a non-random setting, because 720000 / 1000 = 720 which is what you are computing with
int expected = (int)factorial(s.length());
Instead try
int expected = 1000;

How to genearte the random number in increasing order

I would like to generate random numbers in ascending order, for instance: 0, 2, 3, 5 .. 100, but not 2, 0, 5 ..
This is what I came up with so far:
public static int vol=5;
public static void main(String[] args) {
int randno = getRandNum();
vol = vol+randno;
System.out.println(getRandNum());
}
private static int getRandNum() {
Random r = new Random();
for (int i =0; i<10; i++)
{
int v=r.nextInt(vol);
System.out.println("r"+v);
}
return vol;
}
How could I achieve the goal stated above?
/**
* Generates random numbers, returning an array of ascending order.
* #param amount The amount of numbers to generate.
* #param max The maximum value to generate.
* #return An array of random integers of the specified length.
*/
public static int[] generateIncreasingRandoms(int amount, int max) {
int[] randomNumbers = new int[amount];
Random random = new Random();
for (int i = 0; i < randomNumbers.length; i++) {
randomNumbers[i] = random.nextInt(max);
}
Arrays.sort(randomNumbers);
return randomNumbers;
}
You could use it like so:
// Generates 10 random numbers of value 0 to 100,
// printing them in ascending order
for (int number : generateIncreasingRandoms(10, 100)) {
System.out.print(number + " ");
}
Or if you're a micro-optimization kind of person and do not wish to sort,
/**
* Generates random numbers, returning an array of ascending order.
* #param amount The amount of numbers to generate.
* #param max The maximum value to generate.
* #return An array of random integers of the specified length.
*/
public static int[] generateIncreasingRandomWithoutSorting(int amount, int max) {
int[] randomNumbers = new int[amount];
double delta = max / (float)amount;
Random random = new Random();
for (int i = 0; i < randomNumbers.length; i++) {
randomNumbers[i] = (int)Math.round(i*delta + random.nextDouble() * delta);
}
return randomNumbers;
}
Use case:
// Generates 10 random numbers of value 0 to 100,
// printing them in ascending order
for (int number : generateIncreasingRandomWithoutSorting(10, 100)) {
System.out.print(number + " ");
}
The reason that each number is between 0-10, 10-20, 20-30.. in this use case is that if I simply allow for the entire range and you get a 100 on the first try you're going to end up with an entire array of 100s.
Being more controlled, with this solution you are not really getting what you're asking for ("10 numbers of 0 to 100 sorted ascendingly") since it modifies the range for each consecutive number. (like any other solution that doesn't require sorting)
Ben Barkay's answer is good, but if you don't want to create a set of numbers in one step, but you want to get one number after another, you can do something like this:
private static final int MAX = 5;
private Random rand = new Random();
private int maxRand = 0;
public int getIncreasingRandomNumber() {
maxRand = rand.nextInt(MAX);
return maxRand;
}
what about this?
public class increasing {
public static void main (String[] args) {
Random r = new Random();
int totalNums = 100;
int count = 0;
int lastVal = 0;
int currVal = 0;
while(count < totalNums) {
currVal = r.nextInt(200);
lastVal = lastVal + currVal;
System.out.println(lastVal + ",");
count++;
}
}
}

Categories

Resources