Array of random integers with fixed average in java - java

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

Related

How to generate random numbers between 1 and 60 [duplicate]

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

Factors In Java

I am trying to compute a list of prime factors of the ​factorial of n, with the prime factors sorted in increasing order and with each in this list exactly as many times as it would appear in the prime factorization of the factorial.
I have a program that computes a linkedlist of prime numbers up to a specified number, but I'm not sure how to implement that while appending the prime factors of the integer that is currently being multiplied into the factorial:
public static List<Integer> getFactorialPrimeFactors(int n)
{
List <Integer> primes = primeNum(n);
ArrayList <Integer> primeDivisors = new ArrayList<>();
for(int i: primes)
{
int count = 0;
for(int num = i; num <= n; num *= i)
{
count += n/num;
}
while(count > 0)
{
primeDivisors.add(i);
count--;
}
}
return primeDivisors;
}
Explanation - https://math.stackexchange.com/a/642220
Lets say you have computed all the prime numbers from [2..N] and lets call this set P, then for each p in P you can get each number n from [2..N] and check how many times p divides n and put it on the linked list. If you think a little bit more about what MT756 said on the comment above you can make the algorithm i said a little bit faster. I didn't put the java code to make this task a little bit fun for you. : )
You should also have a method that computes the prime factors of a number and returns it as a list. You pass in the list of primes you got from primeNum, which returns the list of primes up to a number.
public static List<Integer> primeFactors(int number, List<Integer> primes) {
List<Integer> ans = new ArrayList<>();
// test condition includes number >= primes.get(i)
// so the loop exits when the current prime is greater than the number
for(int i = 0; i < primes.size() && number >= primes.get(i); i++){
while(number % primes.get(i) == 0){
ans.add(primes.get(i));
number = number / primes.get(i);
}
}
return ans;
}
Then in your main method you can write a forloop that iterate through all number from 1 up to n and call this primeFactors method every loop. You iterate thruogh the result you get from calling this method and add those prime numbers to a list. Last you can sort the list if you want the numbers to be in order.
List<Integer> primes = primeNum(n);
for(int i = 1; i <= 10; i ++){
List<Integer> temp = primeFactors(i,primes);
for(int j = 0; j < temp.size(); j++){
list.add(temp.get(j));
}
}
This is yet another way. It includes several checks to ensure unnecessary testing so as to exit the loops as soon as possible. It works the same way if one wants to find the number of 0's at the end of N factorial. To do that, just add up the quotients of dividing N by successive powers of 5 (as 5 is the larger factor of 10).
This works by adding up the quotients of the N by continuously dividing by each prime.
public static List<Integer> getNFactorialFactors(int n, List<Integer> primes) {
List<Integer> factors = new ArrayList<>();
int nn = n;
for (int p : primes) {
while (nn > 1) {
for (int i = nn / p; i > 0; i--) {
factors.add(p);
}
nn /= p;
}
nn = n;
}
return factors;
}

How can I find out the four unique random numbers in Android within the range of 1 to 60?

This is what I tried so far in my app.
I got this code by searching it from Google.
Inside the Button OnClick() I called the Arandom() method:
public void Arandom(View view) {
final int SET_SIZE_REQUIRED = 4;
final int NUMBER_RANGE = 70;
Random random = new Random();
Set set = new HashSet<Integer>(SET_SIZE_REQUIRED);
while(set.size()< SET_SIZE_REQUIRED) {
while (set.add(random.nextInt(NUMBER_RANGE)) != true) ;
}
assert set.size() == SET_SIZE_REQUIRED;
ArrayList<Integer> Elements = new ArrayList<>(set);
Log.i("Elements","A:" + Elements.get(0));
Log.i("Elements","B:" + Elements.get(1));
Log.i("Elements","C:" + Elements.get(2));
Log.i("Elements","D:" + Elements.get(3));
}
Now I am able to get four unique random numbers by this code but the problem is there sum is greater then 60. Let me explain it little bit.
When I run the code I get:
A:61
B:45
C:31
D:49
This is the screen shot of my log cat
So I want the sum of all the numbers should be in the specified range (which is 1 to 60).
e.g: A = 20 , B = 25 , C = 3 and D = 11 then their sum is 59 which is within the range
Now another e.g: Suppose A = 5 , B = 22 , C = 18 and D = 3 then their sum will be 48
When we Add A,B,C,D then their sum should not exceed the range that is 60
I am new to Android and Java, and I am learning on my own by searching some materials on Google.
Let's say your target sum is T. It's easiest if you try to pick the numbers in descending order (you can shuffle them afterwards, if you want).
The largest number you can pick for the 1st of four numbers is T-6, because you need to pick 3, 2 and 1 for the smaller numbers.
The smallest number you can pick is the one where n+(n-1)+2+1 = T, so T/2+1.
So, pick the first number in the range (T/2+1) to T-6.
Then repeat the process to pick the third-largest and second-largest, applying similar logic to determine the possible range. There should be no choice in the smallest number, it's just whatever else you need to add to make the final sum.
Note that you need to take care with rounding of things like the T/2.
I made the return type an int[]. You know how big you want to make the set, so there is no need to use sets or lists. The input parameter is changed to SET_SIZE_REQUIRED instead of using view. Make sure that a funtion only has one purpose and not do a calculation and change on a view at the same time.
Replace the 60f to something else if you want the sum to be more or less than 60.
public int[] Arandom(int numberOfValues) {
int[] values = new int[numberOfValues];
int sum = 0;
for(int i = 0; i < numberOfValues; i++){
values[i] = (int)(Math.random() * 100);
sum += values[i];
}
float multiplier = 60f / sum;
for(int i = 0; i < numberOfValues; i++){
values[i] = (int)(values[i] * multiplier);
Log.i("Value " + (i + 1), values[i]);
}
return values;
}
Or just do this:
public int[] Arandom(int numberOfValues) {
int[] values = new int[numberOfValues];
for(int i = 0; i < numberOfValues; i++){
values[i] = (int)(Math.random() * (60f / numberOfValues));
Log.i("Value " + (i + 1), values[i]);
}
return values;
}

How to average random numbers in java?

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.

Output amount of primes in array

I'm kind of a newbie at Java, and not very good at it. It's a trial and error process for me.
I'm working on a Java program to output the amount of primes in an array. I can get it to output the primes, but I want to also output the quantity of primes. I tried to add each prime to an array list titled "primes" then return "primes.size()" at the end of my program. It doesn't work as intended. The count is actually off. When I create an array of 5 numbers, it outputs 3 primes, 2, 3, and 5. But then it says I have 4 primes. I think it might be counting 1 as a prime. Because when I create an array of 20, the prime numbers output 2,3,5,7,11,13,17 and 19. Then it says the total prime numbers = 9. It should be 8 though.
Here's my code
public class Prime {
public static void main(String[] args) {
int index = 0;
Scanner scan = new Scanner(System. in );
System.out.println("How big would you like the array? ");
int num = scan.nextInt();
int[] array = new int[num];
ArrayList < Integer > primes = new ArrayList < Integer > ();
//System.out.println("How Many threads? ");
//int nThreads = scan.nextInt(); // Create variable 'n' to handle whatever integer the user specifies. nextInt() is used for the scanner to expect and Int.
//Thread[] thread = new Thread[nThreads];
for (int n = 1; n <= array.length; n++) {
boolean prime = true;
for (int j = 2; j < n; j++) {
if (n % j == 0) {
prime = false;
break;
}
}
if (prime) {
primes.add(n);
}
if (prime && n != 1) {
System.out.println(n + "");
}
}
System.out.println("Total Prime numbers = " + primes.size());
System.out.println("Prime Numbers within " + array.length);
}
}
Forgive the sloppiness of it. I actually plan on adding multithreading to it, but I wanted to get this down first.
Any help would be greatly appreciated. Thanks.
You have included 1 in your array of primes, because you started the n for loop at 1. You don't print it because of the final if statement, but it's there in the ArrayList.
Start your n for loop with n = 2. As a consequence, you won't need the final if statement, because n won't be 1 ever. You could print the prime at the same time as you add it to the ArrayList.

Categories

Resources