How to genearte the random number in increasing order - java

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++;
}
}
}

Related

Creating a Random Number Generator in Java - Array resetting each time

I am trying to create my own Random Number Generator in Java and have been using the Lagged Fibonacci formula.
It works when I want to grab one random number, but when I want to generate multiple random numbers it is just pulling the same random number for all iterations rather than holding on to the new array to generate the next random number.
public class RNumbers {
public static void main(String[] args) {
RandomNumberGenerator rd = new RandomNumberGenerator();
int number = rd.getNumber();
System.out.println(number);
for (int i = 0; i <= 100; i++) {
int number2 = rd.getNumber();
System.out.println(number2);
}
}
}
public class RandomNumberGenerator {
public static int getNumber() {
long seed = System.currentTimeMillis(); // start seed number for formula
int length = (int) (Math.log10(seed) + 1); // number of digits int the seed number
int j = 3; // will always grab the 3rd value from the seed
int k = 7; // will always grab the 7th value from the seed
int mod = 10; // will always be the mod number for formula
int[] arr = new int[length + 1]; // array for seed numbers
String stseed = String.valueOf(seed); // seed to String for adding digits to array
// Take the seed number and turn it into an array of single digit numbers to mimic a sequence
for (int i = 0; i <= length - 1; i++) {
arr[i] = Character.getNumericValue(stseed.charAt(i));
}
// calculate random number with inputs
int number = (arr[length - j] + arr[length - k]) % mod;
// add random number to the end of the array in the temp index
arr[length] = number;
// update array by shifting all indexes down
for (int i = 0; i <= length - 1; i++) {
arr[i] = arr[i + 1];
}
return number;
}
}
Each time you call getNumber() you re-initialize the state of the generator. If you call this multiple times within the same millisecond, you'll initialize it to the same state every time, so you'll end up with the same value. (Even if you call it multiple times over a longer time period, only some of the digits will change, so you still may end up with the same result.)
You need to cache the state, and initialize it once:
public class RandomNumberGenerator {
private static long seed ; // start seed number for formula
private static int length ; // number of digits int the seed number
private static final int j = 3; // will always grab the 3rd value from the seed
private static final int k = 7; // will always grab the 7th value from the seed
private static final int mod = 10; // will always be the mod number for formula
private static int[] arr ; // array for seed numbers
static {
seed = System.currentTimeMillis();
length = (int) (Math.log10(seed) + 1) ;
arr = new int[length + 1] ;
String stseed = String.valueOf(seed); // seed to String for adding digits to array
// Take the seed number and turn it into an array of single digit numbers to mimic a sequence
for (int i = 0; i <= length - 1; i++) {
arr[i] = Character.getNumericValue(stseed.charAt(i));
}
}
public static int getNumber() {
// calculate random number with inputs
int number = (arr[length - j] + arr[length - k]) % mod;
// add random number to the end of the array in the temp index
arr[length] = number;
// update array by shifting all indexes down
for (int i = 0; i <= length - 1; i++) {
arr[i] = arr[i + 1];
}
return number;
}
}
I'd recommend not making everything static (especially since you don't use it in a static fashion in your main method):
public class RandomNumberGenerator {
private long seed ; // start seed number for formula
private int length ; // number of digits int the seed number
private static final int j = 3; // will always grab the 3rd value from the seed
private static final int k = 7; // will always grab the 7th value from the seed
private static final int mod = 10; // will always be the mod number for formula
private int[] arr ; // array for seed numbers
public RandomNumberGenerator() {
seed = System.currentTimeMillis();
length = (int) (Math.log10(seed) + 1) ;
arr = new int[length + 1] ;
String stseed = String.valueOf(seed); // seed to String for adding digits to array
// Take the seed number and turn it into an array of single digit numbers to mimic a sequence
for (int i = 0; i <= length - 1; i++) {
arr[i] = Character.getNumericValue(stseed.charAt(i));
}
}
public int getNumber() {
// calculate random number with inputs
int number = (arr[length - j] + arr[length - k]) % mod;
// add random number to the end of the array in the temp index
arr[length] = number;
// update array by shifting all indexes down
for (int i = 0; i <= length - 1; i++) {
arr[i] = arr[i + 1];
}
return number;
}
}

Need to Convert Array Output to String Outside of a For Loop

I'm trying to practice with arrays in prep for my Java SE 11 test and I need help getting my random name generator to work. Right now, I'm not concerned about the name being "valid" (a truly random name like Xvtwg is fine).
I have built a loop where a random value between 3 and 10 is generated (length of name) and then a random index between 0 and 25 is chosen for each loop pass to grab a random letter of the alphabet. All of this works, and I am able to take the output array from the loop and turn it into a concatenated string in the loop. The problem occurs later when I need to call the local variable nameFinal as a value for the set function.
I have tried to declare the output string both inside and outside the loop but both ways I return "nameFinal cannot be resolved to a variable." I have also tried moving my output array outside of the loop (and redefining its output), but return the same variable."
I added in a try/catch block to try to illustrate this issue better. Here is my code:
public class Tester {
public static void main(String[] args) {
//Build random values
Random rand = new Random();
//Name random index 3-10 char
int nmax = 10;
int nmin = 3;
int rand1 = (int)(Math.random() * (nmax - nmin + 1) + nmin);
//Create random name from total number of letters
//Define Array of letters
String[] letters = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"};
//Create random index to pull a random letter over the length of the random index
int lmax = 25;
int lmin = 0;
//I have also tried declaring newName and nameFinal here
for(int i = 0; i <= rand1; i++) {
int randl = (int)(Math.random() * (lmax - lmin + 1) + lmin);
String[] newName;
newName[i] = letters[i];
String nameFinal = Arrays.toString(newName);
}
//Concatenate array of random letters into a "name"
try{
String nameFinal = Arrays.toString(newName);
System.out.println(nameFinal);
}catch(Exception e) {
e.PrintStackTrace()
}
//Implementation omitted
}
}
I have changed your code a bit. Hope this will help you!
public static void main(String[] args) {
//Build random values
Random rand = new Random();
Test test = new Test();
test.randomName();
test.createAge();
test.createSSN();
}
//Name random index 3-10 char
public void randomName() {
int nmax = 10;
int nmin = 3;
int rand1 = (int)(Math.random() * (nmax - nmin + 1) + nmin);
//Create random name from total number of letters
//Define Array of letters
String[] letters = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"};
//Create random index to pull a random letter over the length of the random index
int lmax = 25;
int lmin = 0;
ArrayList<String> name = new ArrayList<>(5);
for(int i = 0; i <= rand1; i++) {
int randl = (int)(Math.random() * (lmax - lmin + 1) + lmin);
name.add(letters[rand1]);
}
System.out.println(name.toString());
}
//Age random number between 1 and 100
private void createAge(){
int amax = 100;
int amin = 1;
int rand2 = (int)(Math.random() * (amax - amin + 1) + amin);
}
//SSN random 9 digit number
private void createSSN(){
int smax = 999999999;
int smin = 100000000;
int rand3 = (int)(Math.random() * (smax - smin + 1) + smin);
}
}

Dungeons and Dragons Dice Roller Reroll

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.

Pick a few random numbers in a specific range without duplicates

I want to pick 8 random integers in the range 0-7.
int one = (int) (Math.random()*0)+7;
int two = (int) (Math.random()*0)+7;
// ...
int eight = (int) (Math.random()*0)+7;
However, no duplicate numbers are allowed. How can I improve this code to establish this?
Follow the below snippet and change the maxLimit and noOfItems according to your preference to get desired result.
Here the Set contains unique integers under specified limit.
public class RandomIntegers
{
public static final Random random = new Random();
public static final int maxLimit = 8;
public static final int noOfItems = 8;
public static void main( String[] args )
{
Set<Integer> uniqueRandomIntegerSet = new HashSet< Integer >();
while(uniqueRandomIntegerSet.size() < noOfItems)
uniqueRandomIntegerSet.add( random.nextInt( maxLimit ) );
}
}
I'm not sure if this violates your requirements, but you could just go like this:
public static void main(String[] args) {
List<Integer> randomZeroToSeven = new ArrayList<>();
for (int i = 0; i <= 7; i++) {
randomZeroToSeven.add(i);
}
Collections.shuffle(randomZeroToSeven);
}
Alternatively, you can skip the shuffle and just grab a random element out of the list every time you want a random number from 0-7. EG:
public static void main(String[] args) {
List<Integer> zeroToSeven = new ArrayList<>();
for (int i = 0; i <= 7; i++) {
zeroToSeven.add(i);
}
System.out.println(zeroToSeven.get(new Random().nextInt(8)));
}
Another way is to fill up an array / collection with all possibilities and pick from those. Each picked item is removed from the allowed array and put into the output array until you have picked all items.
This way you skip double picks and the execution is linear.
Something like this:
int desiredSize = 8;
List<Integer> allowed = new ArrayList<>();
for (int i = 0; i < desiredSize; i++) {
allowed.add(i);
}
List<Integer> output = new ArrayList<>();
Random random = new Random();
while (output.size() < desiredSize) {
int index = random.nextInt(allowed.size());
output.add(allowed.get(index));
allowed.remove(index);
}
If you need to generate numbers from min to max (including both), you can write
random.nextInt(max - min + 1) + min
public static void main(String[] args) throws IOException {
HashSet<Integer>list=new HashSet();
Random random=new Random();
while(list.size()<8){
list.add(random.nextInt(7 - 0 + 1) + 0); // OR list.add(random.nextInt(8));
}
System.out.println(list);
}
There are only 8 integers from 0-7 and so what you are really asking is for the numbers from 0-7 in a random order.
The quickest way to do this both coding and execution is to shuffle a set of integers.
public class Test {
public static void main(String[] args){
List<Integer> list = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7);
Collections.shuffle(list);
for(int i : list){
System.out.println(i);
}
}
}
If you want to write a shuffle algorithm yourself you can do so by so swapping every item (bar the last) in an array with a random index. The reason you don't do the last is because it biases the outcome. See Fisher Yates Shuffle
Just because I couldn't resist here is a java implementation of Fisher Yates:
public class Test {
public static void main(String[] args){
Random rnd = new SecureRandom();
int[] arr = new int[]{0,1,2,3,4,5,6,7};
for(int i = 0; i < arr.length - 1; i++){
int swapIndex = rnd.nextInt(8);
int tmp = arr[i];
arr[i] = arr[swapIndex];
arr[swapIndex] = tmp;
}
System.out.println(Arrays.toString(arr));
}
}

Limiting duplicate random numbers

I just want to know how to limit to number of times a random number appears. I have generated random numbers of 1 to 10 and want to limit each number to appear 4 times.
myArray[i][j] = rand.nextInt(11);
for (int i=0; i < myArray.length; i++) {
for (int j=0; j < myArray[i].length; j++) {
myArray[i][j] = rand.nextInt(11);
System.out.print(" " + myArray[i][j]);
The code above creates the randoms numbers. Just want to limit them.
Since you are limited to 10 * 4 = 40 numbers you can use a list and randomize the index :
List<Integer> numbers = new ArrayList<Integer>();
for (int i = 1; i < 11; ++i) {
for (int j = 0; j < 4; ++j)
numbers.add(i);
}
And then when you assign a random number :
int i = rand.nextInt(numbers.size());
myArray[i][j] = numbers.get(i);
numbers.remove(i);
This assumes your two dimensional will not contain more then 40 numbers
My solution stores the result in arrayList:
public class Example {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
final int range = 10;
int[] numbers = new int[range + 1];
int sum = 0;
final int noOfOccurances = 4;
final int size = range * noOfOccurances;
Arrays.fill(numbers, 0);
Random generator = new Random();
List<Integer> numbersArray = new ArrayList<>();
while (sum != size) {
int randomNumber = generator.nextInt(range) + 1;
if (numbers[randomNumber] != noOfOccurances) {
numbers[randomNumber]++;
sum++;
numbersArray.add(randomNumber);
}
}
System.out.println(numbersArray);
}
}
How about storing the count of the generated int's in an array, or Map, or anything?
Map<Integer, Integer> randomCounts = new HashMap<Integer, Integer>();
... your for loops
myArray[i][j] = rand.nextInt(11);
if (randomCounts.containsKey(myArray[i][j])) {
randomCounts.put(myArray[i][j],randomCounts.get(myArray[i][j])+1);
} else {
randomCounts.put(myArray[i][j],1);
}
And if you want to check them, just iterate through your map, and voilá. :)
You can make a method to check if the generated number exists more than 4 times in the array and create a new random number if it does. It should look like this:
import java.util.Random;
public class rndNumberGenerator {
public static void main (String[] args) {
int[][] myArray = new int[2][5];
Random rand = new Random();
int randomNumber;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 5; j++) {
do {
randomNumber = rand.nextInt(11);
} while(overMax(myArray, randomNumber) == true);
myArray[i][j] = randomNumber;
System.out.print(" " + myArray[i][j]);
}
}
}
public static boolean overMax(int[][] array, int number) {
int max = 4;
int count = 0;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 5; j++) {
if (array[i][j] == number) {
count++;
}
}
}
if (count >= max)
return true;
else
return false;
}
}
Hope this helped you, if you have any other questions feel free to ask.
I take suggestion by pshemek (vote up): instead the ArrayList, I use the Set because it can't contain duplicate numbers and you have'nt to espicitate control.
An implementation: the copy{right, left} is of pshemek, I had only extended the idea:)
public class Example {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
int[] numbers = new int[11];
int sum = 0;
final int range = 10;
final int noOfOccurances = 4;
Arrays.fill(numbers, 0);
Random generator = new Random();
Set<Integer> numbersArray = new TreeSet<Integer>();
while (sum != range * noOfOccurances) {
int randomNumber = generator.nextInt(range) + 1;
sum++;//correction for first comment
numbersArray.add(randomNumber); // randomNumber will never be twice: a Set cointains ever one and only one instance of an determinated element
}
System.out.println(numbersArray);
}
}//end class
You could write your own:
public static class CountedRandom {
// My rng.
Random rand = new Random();
// Keeps track of the counts so far.
Map<Integer, Integer> counts = new HashMap<Integer, Integer>();
// The limit I must apply.
final int limit;
public CountedRandom(int limit) {
this.limit = limit;
}
public int nextInt(int l) {
int r;
do {
// Keep getting a new number until we hit one that has'n been overused.
r = rand.nextInt(l);
} while (count(r) >= limit);
return r;
}
private int count(int r) {
// How many times have we seen this one so far.
Integer counted = counts.get(r);
if ( counted == null ) {
// Never!
counted = new Integer(0);
}
// Remember the new value.
counts.put(r, counted + 1);
// Returns 0 first time around.
return counted;
}
}
public void test() {
CountedRandom cr = new CountedRandom(4);
for ( int i = 0; i < 50; i++ ) {
System.out.print(cr.nextInt(4)+",");
}
System.out.println();
}
Note that this will hang if you ask for too may numbers in too small a range (as I have in my test).
Prints
2,0,1,2,1,1,3,3,0,3,0,2,2,0,1,3,
and then hangs.

Categories

Resources