Factors In Java - 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;
}

Related

I got some problems in adding the prime numbers to an array list

In this problem, I have a variable N.User will input the value of N.So, I have to find the prime number between 2 to N and store them in an array
import java.util.ArrayList;
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
ArrayList<Integer> array = new ArrayList<>(10);
int num,i,j,count;
num = sc.nextInt();
for(i=2;i<=num;i++){
count = 0;
for(j=2;j<= num/2;j++) {
if (i % j == 0) {
count++;
}
}
if(count==0){
array.add(i);
}
}
for(int val: array){
System.out.print(val + " ");
}
}
}
So, if N=15.The output should be 2 3 5 7 11 13
But I'm getting 11 13
where is the problem?
If you want to optimize your search for primes you should use a sieve or at least add some simple limitations to your algorithm. I have included a version with comments. The main point of this is to only divide by primes that you have already found.
After 2, only check odd numbers since even numbers are guaranteed to be composite (i.e. non-prime).
Only divide by primes already computed.
Only divide by primes <= to the square root of the candidate. If n is divisible by m to yield q. Then n is also divisible by q to yield m. No need to repeat the test with higher numbers. The threshold is the square root of the candidate.
List<Integer> primes = new ArrayList<>();
primes.add(2); // seed list with first prime
int max = 50;
// only check odd numbers after 2.
for (int candidate = 3; candidate < max; candidate += 2) {
// loop thru existing primes
for (int p : primes) {
// if candidate is divisible by any prime, then discontinue
// testing and move on to next candidate via outer loop
if (candidate % p == 0) {
break;
}
// if the limit has been reached, then a prime has been
// found, so add to list of primes and continue with
// next candidate.
if (p * p > candidate) {
// add new found prime to list
primes.add(candidate);
break;
}
}
}
System.out.println(primes);
Your logic is mixed up, think about what defines a prime number. A prime number is a number that is only divisible by itself and one. So when you check that the remainder equals zero and then increase the count a prime number then wouldn't be added to the array as the count != 0. I do realise you set the limit to j for num / 2 but not sure what your thought process there was. I've added an alternative solution (I've tried to stick to yours and just alter it slightly).
My thought process is that by the time a prime number is divided by itself it should only have produced a remainder of zero that one time.
ArrayList<Integer> array = new ArrayList<>();
int limit = 100;
int i, j;
for (i = 1; i <= limit; i++) {
count = 0;
j = 2;
for (j = 2; j <= i; j++) {
if(i%j == 0){
count += 1;
}
if (j == i && count == 1) {
array.add(i);
}
}
}

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.

Array of random integers with fixed average in 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);
}
}

Mathematical riddle - how to solve numerically in Java?

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

Sum of all prime numbers below 2 million

Problem 10 from Project Euler:
The program runs for smaller numbers and slows to a crawl in the hundred thousands.
At 2 million, an answer fails to show up even though the program seems like it is still running.
I'm trying to implement the Sieve of Eratosthenes. It is supposed to be very fast. What's wrong with my approach?
import java.util.ArrayList;
public class p010
{
/**
* The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17
* Find the sum of all the primes below two million.
* #param args
*/
public static void main(String[] args)
{
ArrayList<Integer> primes = new ArrayList<Integer>();
int upper = 2000000;
for (int i = 2; i < upper; i++)
{
primes.add(i);
}
int sum = 0;
for (int i = 0; i < primes.size(); i++)
{
if (isPrime(primes.get(i)))
{
for (int k = 2; k*primes.get(i) < upper; k++)
{
if (primes.contains(k*primes.get(i)))
{
primes.remove(primes.indexOf(k*primes.get(i)));
}
}
}
}
for (int i = 0; i < primes.size(); i++)
{
sum += primes.get(i);
}
System.out.println(sum);
}
public static boolean isPrime(int number)
{
boolean returnVal = true;
for (int i = 2; i <= Math.sqrt(number); i ++)
{
if (number % i == 0)
{
returnVal = false;
}
}
return returnVal;
}
}
You appear to be trying to implement the Sieve of Eratosthenes which should perform better that O(N^2) (In fact, Wikipedia says it is O(N log(log N)) ...).
The fundamental problem is your choice of data structure. You've chosen to represent the set of remaining prime candidates as an ArrayList of primes. This means that your test to see if a number is still in the set takes O(N) comparisons ... where N is the number of remaining primes. Then you are using ArrayList.remove(int) to remove the non-primes ... which is O(N) also.
That all adds up to making your Sieve implementation worse than O(N^2).
The solution is to replace the ArrayList<Integer> with an boolean[] where the positions (indexes) in the boolean array represent the numbers, and the value of the boolean says whether the number is prime / possibly prime, or not prime.
(There were other problems too that I didn't notice ... see the other answers.)
There are a few issues here. First, lets talk about the algorithm. Your isPrime method is actually the very thing that the sieve is designed to avoid. When you get to a number in the sieve, you already know it's prime, you don't need to test it. If it weren't prime, it would already have been eliminated as a factor of a lower number.
So, point 1:
You can eliminate the isPrime method altogether. It should never return false.
Then, there are implementation issues. primes.contains and primes.remove are problems. They run in linear time on an ArrayList, because they require checking each element or rewriting a large portion of the backing array.
Point 2:
Either mark values in place (use boolean[], or use some other more appropriate data structure.)
I typically use something like boolean primes = new boolean[upper+1], and define n to be included if !(primes[n]). (I just ignore elements 0 and 1 so I don't have to subtract indices.) To "remove" an element, I set it to true. You could also use something like TreeSet<Integer>, I suppose. Using boolean[], the method is near-instantaneous.
Point 3:
sum needs to be a long. The answer (roughly 1.429e11) is larger than the maximum value of an integer (2^31-1)
I can post working code if you like, but here's a test output, without spoilers:
public static void main(String[] args) {
long value;
long start;
long finish;
start = System.nanoTime();
value = arrayMethod(2000000);
finish = System.nanoTime();
System.out.printf("Value: %.3e, time: %4d ms\n", (double)value, (finish-start)/1000000);
start = System.nanoTime();
value = treeMethod(2000000);
finish = System.nanoTime();
System.out.printf("Value: %.3e, time: %4d ms\n", (double)value, (finish-start)/1000000);
}
output:
Using boolean[]
Value: 1.429e+11, time: 17 ms
Using TreeSet<Integer>
Value: 1.429e+11, time: 4869 ms
Edit:
Since spoilers are posted, here's my code:
public static long arrayMethod(int upper) {
boolean[] primes = new boolean[upper+1];
long sum = 0;
for (int i = 2; i <=upper; i++) {
if (!primes[i]) {
sum += i;
for (int k = 2*i; k <= upper; k+=i) {
primes[k] = true;
}
}
}
return sum;
}
public static long treeMethod(int upper) {
TreeSet<Integer> primes = new TreeSet<Integer>();
for (int i = 2; i <= upper; i++) {
primes.add(i);
}
long sum = 0;
for (Integer i = 2; i != null; i=primes.higher(i)) {
sum += i;
for (int k = 2*i; k <= upper; k+=i) {
primes.remove(k);
}
}
return sum;
}
Two things:
Your code is hard to follow. You have a list called "primes", that contains non prime numbers!
Also, you should strongly consider whether or not an array list is appropriate. In this case, a LinkedList would be much more efficient.
Why is this? An array list must constantly resize an array by: asking for new memory to create an array, then copying the old memory over in the newly created array. A Linked list would just resize the memory by changing a pointer. This is a lot quicker! However, I do not think that by making this change you can salvage your algorithm.
You should use an array list if you need to access the items non-sequentially, here, (with a suitable algorithm) you need to access the items sequentially.
Also, your algorithm is slow.Take the advice of SJuan76 (or gyrogearless), thanks sjuan76
The key to the efficiency of classic implementation of the sieve of Eratosthenes on modern CPUs is the direct (i.e. non-sequential) memory access. Fortunately, ArrayList<E> does implement RandomAccess.
Another key to the sieve's efficiency is its conflation of index and value, just like in integer sorting. Actually removing any number from the sequence destroys this ability to directly address without any computations. We must mark, not remove, any composite as we find them, so any numbers greater than it will remain in their places in the sequence.
ArrayList<Integer> can be used for that (except taking more memory than is strictly necessary, but for 2 million this is inconsequential).
So your code with a minimal edit fix (also changing sum to be long as others point out too), becomes
import java.util.ArrayList;
public class Main
{
/**
* The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17
* Find the sum of all the primes below two million.
* #param args
*/
public static void main(String[] args)
{
ArrayList<Integer> primes = new ArrayList<Integer>();
int upper = 5000;
primes.ensureCapacity(upper);
for (int i = 0; i < upper; i++) {
primes.add(i);
}
long sum = 0;
for (int i = 2; i <= upper / i; i++) {
if ( primes.get(i) > 0 ) {
for (int k = i*i; k < upper ; k+=i) {
primes.set(k, 0);
}
}
}
for (int i = 2; i < upper; i++) {
sum += primes.get(i);
}
System.out.println(sum);
}
}
Finds the result for 2000000 in half a second on Ideone. The projected run time for your original code there: between 10 and 400 hours (!).
To find rough estimates for the run time when faced with a slow code, you should always try to find out its empirical orders of growth: run it for some small size n1, then a bigger size n2, record the run times t1 and t2. If t ~ n^a, then a = log(t2/t1) / log(n2/n1).
For your original code the empirical orders of growth measured on 10k .. 20k .. 40k range of upper limit value N, are ~ N^1.7 .. N^1.9 .. N^2.1. For the fixed code it's faster than ~ N (in fact, it's ~ N^0.9 in the tested range 0.5 mln .. 1 mln .. 2 mln). The theoretical complexity is O(N log (log N)).
Your program is not the Sieve of Eratosthenes; the modulo operator gives it away. Your program will be O(n^2), where a proper Sieve of Eratosthenes is O(n log log n), which is essentially n. Here's my version; I'll leave it to you to translate to Java with appropriate numeric datatypes:
function sumPrimes(n)
sum := 0
sieve := makeArray(2..n, True)
for p from 2 to n step 1
if sieve[p]
sum := sum + p
for i from p * p to n step p
sieve[i] := False
return sum
If you're interested in programming with prime numbers, I modestly recommend this essay at my blog.

Categories

Resources