This question already has answers here:
Generate n random numbers whose sum is m and all numbers should be greater than zero
(8 answers)
Closed 2 years ago.
How can I do this? I know how to generate random numbers but not in a fixed range.
why dont you just simply random the sum. then generate n random numbers with that sum
public static void random(int n, int min, int max) {
Random random = new Random();
int sum = random.nextInt(max - min) + min;
List<Integer> list = new ArrayList<>();
int currentSum = 0;
for (int i = 0; i < n - 1; i++) {
int value = random.nextInt((int) (sum - currentSum) / (n - 1 - i)) + 1;
currentSum += value;
list.add(value);
}
list.add(sum - currentSum);
}
reference: Generate n random numbers whose sum is m and all numbers should be greater than zero
Here is a possible solution:
First we can call our method that will get us our sum value.
Then we get a random number between 0 and the sum we calculated which will give our first number.
Subtract our first number from the sum get another random for the second and the final value will be the 2nd from the sum again.
//Get the random number between two values
public static int startRange(int x, int y) {
Random rand = new Random();
return rand.nextInt(Math.abs(x-y)) + Math.min(x, y);
}
public static void main(String[] args) {
Random rand = new Random();
int sum = startRange(30, 50);
int firstNum = rand.nextInt(sum);
sum -= firstNum;
int secNum = rand.nextInt(sum);
int thirdNum = sum - secNum;
System.out.println(String.format("The nums are %d, %d and %d totaling %d",
firstNum, secNum, thirdNum, firstNum + secNum + thirdNum));
}
I assume you want to generate a random combination of N integers such that—
each integer is 0 or greater,
the integers have a sum that lies in the interval [minsum, maxsum],
the integers appear in random order, and
the combination is chosen uniformly at random from among all combinations that meet the other requirements.
This can be described as—
choosing a random sum (according to the number of combinations possible for that sum), then
choosing a random combination for that sum.
Part 2 is trivial thanks to the Smith and Tromble algorithm, and I give Ruby code for this algorithm in a question for a related problem.
Part 1 is the trickier part. It involves—
counting the number of valid combinations for each sum in [minsum, maxsum] (more formally, the number of partitions of each sum into N parts, where each part can be empty and occur more than once), then
choosing a random sum with probability proportional to the number of valid combinations (partitions) for that sum.
This is only a sketch of the problem, since I don't know the exact formula that meets the first three requirements stated above in this answer. All I know is that the number of partitions of N into k non-empty parts is equal to the Sterling number of the second kind (but I don't know a similar formula for the case where the parts can be empty or the parts can occur more than once).
This is probably your best bet for a generic solution:
int[] randomNumbersWithSumBetween(int num, int min, int max, Random random) {
if (min > max) throw new IllegalArgumentException("min > max");
if (num < 1) throw new IllegalArgumentException("No random numbers to generate");
int[] result = new int[num];
result[0] = min + random.nextInt(max - min);
for (; num-- > 1; ) {
result[num] = random.nextInt(result[0]);
result[0] -= result[num];
}
return result;
}
Related
thanks in advance for any help I'm in an intro to java class and our home work was to generate 10 random numbers between 1&50 which I got and then average the generated numbers. I can't figure out how to average them here's what I have. Is there a way to store each random number as a variable?
public class randomNumberGen
{
public static void main(String [] args)
{
Random r=new Random();
for (int i=1;i<=10;i++){
System.out.println(r.nextInt(50));
System.out.println();
int average = (i/4);
System.out.println("your average is"+average);
}
}
}
use streams with java 8
final int numberOfRandom = 10;
final int min = 0;
final int max = 50;
final Random random = new Random();
System.out.println("The ave is: "+random.ints(min, max).limit(numberOfRandom).average());
First of all you have to replace "r.nextInt(50)" for "r.nextInt(50) + 1" because r.nextInt(n) returns a number between 0 (inclusive) and n (exclusive). Then, you know that an average is just a sum of n values divided by n. What you can do is just declare a "total" variable initialized to 0 before the loop. On each iteration you add to this variable the random value generated by r.nextInt(50). After the loop you can just divide the total by 10 so you get the average.
PS: it's a good practice to don't use "magic numbers", so it would be perfect (and luckily your teacher will have it in count) if you declare a constant for the number of iterations and then use it both in the loop condition and in the average calculation. Like this, if you have to make it for 100 numbers you only have to change the constant value from 10 to 100 instead of replacing two 10's por two 100's. Also this gives you the chance to give semantic value to these numbers, because now they will be "AMOUNT_OF_NUMBERS = 10" instead of just "10".
Like every average, it's sum of elements / amount of elements. So let's apply it here:
import java.util.Random;
public class randomNumberGen
{
public static void main(String [] args)
{
Random r=new Random();
double sum = 0; // is double so to prevent int division later on
int amount = 10;
int upperBound = 50;
for (int i = 0; i < amount; i++){
int next = r.nextInt(upperBound) + 1; // creates a random int in [1,50]
System.out.println(next);
sum += next; // accumulate sum of all random numbers
}
System.out.println("Your average is: " + (sum/amount));
}
}
Store variables outside of the loop to store both the total amount of numbers generated as well as the sum of those numbers. After the loop completes, divide the sum by the total amount of numbers.
public static void main(String [] args)
{
Random r=new Random();
double sum = 0;
int totalNums;
for (totalNums=1;totalNums<=10;totalNums++){
int randomNum = r.nextInt(50);
sum += randomNum;
System.out.println(randomNum);
}
double average = sum/totalNums;
System.out.println("your average is: "+average);
}
Average = Sum of numbers / amount of numbers
int sum = 0;
for (int i=1;i<=10;i++){
sum += r.nextInt(50) +1; //nextInt 50 produces value 0 to 49 so you add 1 to get 1 to 50 OR as suggested in the comments sum/10d
}
System.out.println("Average is: " + sum/10) // If you want the result in double (with decimals) just write sum*1.0/10
You could also do the same with a while loop.
int i = 0;
int sum = 0;
while(i < 10){
sum += r.nextInt(50) +1;
i++;
}
System.out.println("Average is: " + sum*1.0/i);
Or even shorter with lambda expressions: (/java 8 streams)
OptionalDouble average = IntStream.range(1, 10).map(x-> x = r.nextInt(50) +1).average();
System.out.println("Average is "+ average.getAsDouble());
.map(x-> x = r.nextInt(50) +1) // maps (changes) each value from 1 to 10 to a random number between 1 and 50
.average(); // calculates the average.
Simply create a variable sum starting at zero that you increment at each iteration. After the loop, simply divide by the number of elements..
Average means you should add everything up and devide it by the number of elements (50).
import java.util.Random;
class Homework {
public static final Random RANDOM = Random(); // never regenerate randoms
public static void main(String args[]) {
final int N = 50;
int sum = 0;
for (int i = 0; i < N; ++i) {
sum += RANDOM.nextInt(50)+1;
}
System.out.println("Avg: "+ sum / (float) N);
}
}
This should do the trick. Try to learn from it not just C+P.
Ps: Friggin annoying to write code on a phone.
I found answers on how to generate random numbers but nowhere how to generate all the numbers in the range without duplication in Java. Please share if you have a solution. Below is what I did but it simply generates randomly the numbers. I need to print out all numbers in the range without duplication!
package com.company;
import java.util.*;
public class RandomizeNumbers {
public static void main(String[] args) {
//Create Scanner
Scanner userInput = new Scanner(System.in);
//Ask for numbers N and M
System.out.println("Please enter two numbers and the program will randomize the numbers between them. " +
"The first number N must be bigger or equal to the second number M");
System.out.println("Please enter the first number N");
int n = userInput.nextInt();
System.out.println("Please enter the second number M");
int m = userInput.nextInt();
Random randomGenerator = new Random();
int difference = n - m;
//Randomize the numbers
if (m<=n){
for(int i = 0; i<= difference; i++ ) {
int randomInt = randomGenerator.nextInt(n - m + 1) + m;
System.out.println(randomInt);
}
}
else{
System.out.println("Please enter M less or equal to N");
}
}
}
What you need maybe generating a random permutation, pls see this link How to generate a random permutation in Java?
You can store generated number in a array.then after generate the next number check is there this number in array or no.
There are many ways to achieve this, lets suppose you want 50 numbers between A and B, then use a java.util.Set, since this collection does "ignore" duplicated values: following snippet describe it better:
Set<Integer> setA = new HashSet<Integer>();
Random r = new Random(System.currentTimeMillis());
int low = 10;
int high = 100;
int rnd = r.nextInt(high - low + 1) + low;
int maxCount = 50;
while (setA.size() < maxCount ) { //<--how many random numbers do you need?
rnd = r.nextInt(high - low + 1) + low;
setA.add(rnd);
}
and be careful, not to get in an infinite loop.
(there are only "B-A" possible integer options between A and B, so MaxCount<= B-A)
What I suggest you to do is to create a List and then shuffle it.
ArrayList<Integer> list = new ArrayList();
int high = 20;
int low = 10;
for(int i = low; i <= high; ++i)
list.add(i);
Collections.shuffle(list);
And then create a function to get a random Unique number each time.
static int index = 0;
public int roll(ArrayList<Integer> list)
{
return list.get(index ++);
}
You can put all the numbers between n & m into a list and then use Collections.shuffle(list) to make the numbers ordered randomly in the list.
if (difference > 0) {
List<Integer> integers = new ArrayList<>();
for (int i = 0; i <= difference; ++i) {
integers.add(m + i);
}
Collections.shuffle(integers);
for (Integer randNum : integers) {
System.out.print(randNum + "\t");
}
System.out.println();
} else {
System.out.println("Please enter M less or equal to N");
}
I need to create an array of random integers which a sum of them is 1000000 and an average of these numbers is 3. The numbers in the array could be duplicated and the length of the array could be any number.
I am able to find the array of random integers which the sum of them is 1000000.
ArrayList<Integer> array = new ArrayList<Integer>();
int a = 1000000;
Random rn = new Random();
while (a >= 1)
{
int answer = rn.nextInt(a) + 1;
array.add(answer);
a -= answer;
}
However, I don't know how to find the random numbers with average of 3.
that's mathematically not possible:
you are looking for n values, sum of which makes 1000000, and the average of them is 3, which is 1000000/n. since n can only take integer values it is not possible.
If they are constrained to an average and random, they must be constrained to a value range. A range of 1 to 5 (median is 3) seems reasonable. Also reasonable is a smooth distribution, which gives a known total and average.
This simple code will do all that:
List<Integer> numbers = new ArrayList<>(333334); // 1000000 / 3
// one instance of 5 must be omitted to make total exactly 1000000
numbers.addAll(Arrays.asList(1, 2, 3, 4));
for (int i = 0; i < 333330; i++)
numbers.add((i % 5) + 1); // add 1,2,3,4,5,1,2,3,4,5,etc
Collections.shuffle(numbers);
// Check sum is correct
numbers.stream().reduce((a,b) -> a + b).ifPresent(System.out::println);
Output:
1000000
Note that it is mathematically impossible for the average to be exactly 3 when the total is 1000000 (because 1000000/3 has a remainder of 1/3), however this code gets pretty close:
1000000/333334 => 2.999994
I would transverse the list twice, and IF the integers at these two positions added together and divded by 2 == 3 then return, else, increment your integer.
As Göker Gümüş said it is mathematically impossible to have the average be exactly 3 and the sum be a million.
The average = sum / number of elements.
This means that number of elements = sum / average.
In this case it would need 1000000 / 3 = 333333.(3) elements. Since you can't have a third of an element with value 3 it means your average or your sum will need to be slightly off your target for it to match up.
The less notable needed difference would definitely be the average as it would only need to be a millionth of a unit off, i.e 3.000001 for you to be able to have 333333 elements summing to 1000000
I think that you need to write a simple average function like:
public double average(ArrayList<Integer> array){
long sum = 0;
int count = 0;
for (Integer item : array){
sum += item;
count++;
}
return sum/count;
}
Then use it in your code like:
ArrayList<Integer> array = new ArrayList<Integer>();
int a = 1000000;
Random rn = new Random();
boolean isDone = true;
while (a >= 1)
{
int answer = rn.nextInt(a) + 1;
array.add(answer);
a -= answer;
if (average(array) % 3 != 0){
isDone = false;
break;
}
}
The idea is each time we adding a new number to the array, we checking that the average can be divide with 3, if not, we getting out of the while loop.
To let us know if the algorithm went well, we need to check isDone variable at the end.
And the more efficient way is:
ArrayList<Integer> array = new ArrayList<Integer>();
int a = 1000000;
Random rn = new Random();
boolean isDone = true;
long sum = 0;
while (a >= 1)
{
int answer = rn.nextInt(a) + 1;
array.add(answer);
a -= answer;
sum += answer;
if ((sum/array.size()) % 3 != 0){
isDone = false;
break;
}
}
there are many answers to this question but lets say we want our random number to be 10 max (which we can change). I guess this would give a satisfactory answer.
import java.util.Random;
import java.util.ArrayList;
public class RandomSumAverage {
public static void main(String[] args) {
Random random = new Random();
ArrayList<Integer> arr = new ArrayList<Integer>();
double sum = 0;
double avg = 0;
int k = 1;
while (sum < 1000000) {
avg = sum / k;
if (avg < 3) {
int element = random.nextInt(10)+1;
sum += element;
arr.add(element);
k++;
} else {
int element = random.nextInt(3)+1;
sum += element;
arr.add(element);
k++;
}
}
System.out.println(arr);
System.out.println(sum);
System.out.println(avg);
}
}
I am trying to write a program that selects 5 integers at random between 1 and 6. I then need the program to display the missing integer. I can't figure out how to have it not display "0" as an integer. This is what I have so far...
import java.util.Random;
public class Task6
{
public static void main(String[] args)
{
int[] numbers = new int[5];
Random random = new Random();
for(int n = 1; n < 5; n++)
{
int select = random.nextInt(n + 1); //shuffle generator so it will not duplicate numbers
numbers[n] = numbers[select];
numbers[select] = n;
}//end for statement
for(int number : numbers)
{
System.out.println("Numbers selected : " + number);
}//end for
}
}
I have to have a O(n^2) operation in this as well.
If I understand correctly, you want your random numbers to only be between 1 and 6 (inclusive)? If that's the case then you need to restrict the range of what the RNG can actually spit out, using code similar to this:
/**
* Returns a pseudo-random number between min and max, inclusive.
* The difference between min and max can be at most
* <code>Integer.MAX_VALUE - 1</code>.
*
* #param min Minimum value
* #param max Maximum value. Must be greater than min.
* #return Integer between min and max, inclusive.
* #see java.util.Random#nextInt(int)
*/
public static int randInt(int min, int max) {
// NOTE: Usually this should be a field rather than a method
// variable so that it is not re-seeded every call.
Random rand = new Random();
// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
Also, your for loop:
for(int n = 1; n < 5; n++) { ... }
will not generate 5 numbers, it will generate 4. Think about the constraints of the loop; it will run through once with n = 1, 2, 3, 4, and then stop (5 is not less than 5).
If you want 5 iterations, you can do this:
for (int n = 0; n < 5; n++) { ... }.
or this:
for (int n = 1; n <= 5; n++) { ... }
Your number of iterations and your random number range don't need to be related.
Check this excellent answer for more detail if you need it.
Create a method that applies your constraints to the random number. Here is an example.
// this assumes that only 0 is unacceptable.
private static int myRandomBlammy()
{
int returnValue;
do
{
returnValue = blam; // replace blam with some way of generating a random integer.
} while (returnValue == 0);
return returnValue;
}
You should have an if statement on your loop that goes through the numbers.
for(int number : numbers)
{
if(number != 0){
System.out.println("Numbers selected : " + number);
}
}//end for
I am trying to write a program that selects 5 integers at random
between 1 and 6. I then need the program to display the missing
integer. I can't figure out how to have it not display "0" as an
integer.
From your question, there may be a case where your 5 random integers will not all be unique, and there may be more than one unique number that was not generated.
I would handle this with an array that counts how many of each number is generated:
import java.util.Random;
public class RandomCounter
{
/**
* An example that uses array indices to count how many random
* numbers are generated in a range.
*/
public static void main(String[] args)
{
//use an array of size n + 1 (ignore the zero index)
int[] numbers = new int[7];
Random r = new Random();
//generate random numbers
for (int i = 1; i < 6; i++){
int next = r.nextInt(6) + 1;
numbers[next]++; //count each number at the index
}
//print any numbers that didn't occur at least once.
for(int i = 1; i < numbers.length; i++){
if(numbers[i] != 0){
System.out.println(i);
}
}
}
}
Replace the last for-loop with this code snippet to see how many of each number occurred:
//print how many of each number occurred.
for(int i = 1; i < numbers.length; i++){
System.out.println (i + ": " + numbers[i]); }
}
Array index counting is a useful way to dynamically count occurrences of numbers.
So the riddle is:
John has written down k sequential odd numbers: n{1}, n{2}, ..., n{k-1}, n{k} (where n{2} = n{1} + 2 and so on). We know that:
The sum of the first four numbers is a fourth power of some prime number (so n{1} + n{2} + n{3} + n{4} = p{1} where p{1}^4 is a prime number.
The sum of the last five numbers is a fourth power of some prime number (so n{k} + n{k-1} + n{k-2} + n{k-3} + n{k-4}= p{2}^4 where p{1} is a prime number.
The question is - how many numbers have been written down (k=?).
Below is my attempt to solve it in Java:
import java.math.BigInteger;
import java.util.Set;
//precalculate prime numbers
public class PrimeSieve {
public static boolean[] calculateIntegers(int N) {
// initially assume all integers are prime
boolean[] isPrime = new boolean[N + 1];
for (int i = 2; i <= N; i++) {
isPrime[i] = true;
}
// mark non-primes <= N using Sieve of Eratosthenes
for (int i = 2; i*i <= N; i++) {
// if i is prime, then mark multiples of i as nonprime
// suffices to consider mutiples i, i+1, ..., N/i
if (isPrime[i]) {
for (int j = i; i*j <= N; j++) {
isPrime[i*j] = false;
}
}
}
return isPrime;
}
}
The solving class:
public class Solver {
static boolean[] isPrime = PrimeSieve.calculateIntegers(100000);
public static void main(String[] args) {
int minNumberCount = 5;
int maxNumberCount = 2000;
int startInt = 2;
int endInt = 1000000;
for (int numberCount = minNumberCount; numberCount < maxNumberCount+1; numberCount++) {
System.out.println("Analyzing for " + numberCount + " numbers");
int[] numbers = new int[numberCount];
//loop through number sets
for (int firstNum = startInt; firstNum < endInt; firstNum+=2) {
//populate numbers array
for(int j=0; j<numberCount; j++){
numbers[j] = firstNum + j*2;
}
long bottomSum=0;
long topSum=0;
//calculate bottom sum
for(int iter=0; iter<4; iter++){
bottomSum+=numbers[iter];
}
//calculate top sum
for(int iter=numberCount-1; iter>numberCount-6; iter--){
topSum+=numbers[iter];
}
//check if the sums match the sulution criteria
if(checkPrime(quadRoot(bottomSum)) && checkPrime(quadRoot(topSum))){
System.out.println("SOLUTION!");
for (int i = 0; i < numbers.length; i++) {
System.out.print(numbers[i] + " ");
}
System.exit(0);
}
}
}
}
private static boolean checkPrime(int i){
return isPrime[i];
}
private static boolean checkPrime(double i){
return ((i % 1) == 0) && checkPrime((int) i);
}
private static double quadRoot(long n){
return Math.sqrt(Math.sqrt(n));
}
}
Using this algorithm with the assumed parameters (max k=2000, max n{1}=100000) - I've found no solution. My question is: are the parameter assumptions wrong (no solution in this range), or do I have some algorithmic/numeric error and that is the reason I've found no solution?
EDIT: sorry - my mistake - it should be ODD instead of EVEN.
It is still easier to solve this directly than to write a program.
The first sum is even so it must be 16 (since 2 is the only even prime). The first four numbers are therefore 1,3,5,7.
The sum of five consecutive odd numbers is 5 times the middle number hence must be divisible by 5. Since it is a fourth power of a prime it must be 625 and the last five numbers are therefore 121,123,125,127,129
It is now an easy task to determine k=65
As said in the comments, your riddle has no solution.
Let's suppose there was a solution, then n1 + n2 + n3 + n4 == p1^4 . We know that n1,n2,n3,n4 are even from the definition of the riddle and therefore as a sum of even numbers, n1 + n2 + n3 + n4 is even as well. This leads us to the fact that p1^4 is even. We know that a multiplication of two odd numbers results only an odd number, hence p1^4 = p1 * p1 * p1 * p1 means that p1 must be an even number. However, p1 is prime. The only prime number which is also even is 2. It's easy to see that there are no four consecutive even numbers that sum up to 16 and therefore p1 is not prime. This contradicts the assumption that p1 is a prime, hence, no solution.
If there are only even numbers, the sum of those is an even number. If I understood correctly, your sum has to be the result of the fourth power of a prime number. Considering the sum is an even number, the only number to satisfy your condition is 16 (2*2*2*2), where 2 is a prime number, so your sum of 4 even number has to be 16. Now, if you're certain there's a sequence, then the sum is computed by adding the first and the last number in the sequence, then multiplying the result with the number of elements in the sequence, and dividing the result of the multiplication by 2. For example, 2+4+6+8=(2+8)*4/2=10*4/2=20. Similarly, for your example, n{1}+n{2}+...+n{k}=(n{1}+n{k})*k/2
On a side note, your smallest sum of 4 even numbers (20), the example I used, is already above your only 4th power of the prime number (16), so yes, there is no valid example in your sequence.
I hope this made some sense