Prime Factorization With Exponents In Java - java

I'm trying to write a java code that displays the prime factorization of a number in two forms: multiplied out and multiplied out with exponents. For example, the proper output would look like this:
Enter a number
100
The prime factorization of 100 is:
100 = 2 * 2 * 5 * 5
100 = 2^2 * 5^5
Except my current code only outputs this:
Enter a number
100
The prime factorization of 100 is:
100 = 2 2 5 5
Here's what my code looks like:
import java.util.Scanner;
public class Factorization {
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
// user inputs variables here
System.out.println("Enter a number");
long n = keyboard.nextLong();
System.out.println("The prime factorization of " + n + " is: ");
System.out.print(n+" = ");
// solution for 1 as an input
if(n==1){
System.out.println("1");
}
// for each potential factor
for (long factor = 2; factor*factor <= n; factor++) {
// if factor is a factor of n, repeatedly divide it out
while (n % factor == 0) {
System.out.print(factor + " ");
n = n / factor;
}
}
// if biggest factor occurs only once, n > 1
if (n > 1){
System.out.println(n);
} else {
System.out.println();
}
}
}
How can I make it give the proper output?
Thank you so much!

Printing out the first form is easy, and would just require a slight modification to your code so that it would print out the *. The second form, however, is a bit more tricky as you can't just directly print out the factors as you obtain them, since you need to count how many times each one occurs to know their exponent. There are a few different ways you could do this, but I thought the simplest would be to use 2 ArrayLists. One of these ArrayLists would contain the bases, while the other would contain the exponents for each base. This is my implementation, and I added some comments for clarification.
import java.util.Scanner;
import java.util.ArrayList;
public class Factorization{
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
// user inputs variables here
System.out.println("Enter a number");
long n = keyboard.nextLong();
long m = n;
System.out.println("The prime factorization of " + n + " is: ");
System.out.print(n+" = ");
ArrayList<Long> bases = new ArrayList<Long>(); //ArrayList containing each unique factor
ArrayList<Long> exponents = new ArrayList<Long>(); //ArrayList containing exponents, or the amount of times that factor is multiplied
// solution for 1 as an input
if(n==1){
System.out.println("1");
}
// for each potential factor
for (long factor = 2; factor*factor <= n; factor++) {
// if factor is a factor of n, repeatedly divide it out
while (n % factor == 0) {
n = n / factor;
if (!bases.contains(factor)){ //if the factor is not already in the bases list, it's unique and should be added
bases.add(factor);
exponents.add(1L);
}
else{ //if the factor is already in the bases list, increment its exponent by 1
exponents.set(bases.indexOf(factor), exponents.get(bases.indexOf(factor)) + 1);
}
}
}
// if biggest factor occurs only once, n > 1
if (n > 1){
if (!bases.contains(n)){
bases.add(n);
exponents.add(1L);
}
else{
exponents.set(bases.indexOf(n), exponents.get(bases.indexOf(n)) + 1);
}
}
//printing out the first form
for (int i = 0; i < bases.size(); i++)
{
for (int j = 0; j < exponents.get(i); j++) //each base is printed out an amount of times equal to its exponent
{
if (i != 0 || j != 0) //making sure we don't print * before the first base
{
System.out.print(" * ");
}
System.out.print(bases.get(i));
}
}
System.out.println();
System.out.print(m+" = ");
//printing out the second form
for (int i = 0; i < bases.size(); i++)
{
if (i >= 1) //making sure we don't print * before the first base
{
System.out.print(" * ");
}
System.out.print(bases.get(i) + "^" + exponents.get(i));
}
}
}
If you want to learn more about ArrayLists, I recommend you check out the official Java documentation on it here: https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html.
I hope this helps.

Related

Significant numbers - arithmetic average of proper divisors is not bigger than root of that number

The task seems pretty easy - on input I get number of tests (numOfTests), then two numbers (downBorder, upBorder) and I have to find how many numbers between those numbers (downBorder, upBorder) are significant numbers where significant number is a number which arithmetic average of proper divisors(all divisors except one and the same number) are smaller or equal than square root of that number.
I wrote the code and probably it works however it's too slow.
My code:
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws java.lang.Exception
{
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); //faster than Scanner
int numOfTests = Integer.parseInt(bf.readLine());
for(int i = 0; i < numOfTests; i++)
{
String[] borders = bf.readLine().split(" ");
long downBorder = Long.parseLong(borders[0]);
long upBorder = Long.parseLong(borders[1]);
//System.out.println(String.format("down: %s, up: %s", downBorder, upBorder));
System.out.println(countNumberOfSignificantNumbers(downBorder, upBorder));
}
}
/**
* print numbers of significant numbers - (arithmetic average of all divisors that is not bigger than root of that number)
* e.g 4 is significant but 6 is not
* #param downBorder
* #param upBorder
*/
private static int countNumberOfSignificantNumbers(Long downBorder, Long upBorder) {
int numberOfSignificantNumbers = 0;
for(Long i = downBorder; i <= upBorder; i++)
{
if(i%2 != 0)
continue;
else
{
double avgOfProperDivisors = getAvgArithOfSumOfNumberDividers(i);
if(avgOfProperDivisors != 0 && avgOfProperDivisors <= Math.sqrt(i))
numberOfSignificantNumbers++;
}
}
return numberOfSignificantNumbers;
}
/**
* method returns the arithemtic average of all proper divisors (all divisors except one and number itself)
* #param number
* #return
*/
public static double getAvgArithOfSumOfNumberDividers(Long number)
{
long maxD = number/2;
long sum=0;
long numOfDivs = 0;
for(long i = 2; i <= maxD; i++)
{
if(number % i == 0)
{
numOfDivs++;
sum += i;
}
}
return (numOfDivs > 0) ? (double)sum/numOfDivs : 0;
}
}
The bottleneck in this task is counting average of divisors. How can I make it better and faster?
Example input:
2
4 6
1 3
Example output:
1
0
Significant Number will always be a perfect square of a prime number like 4, 9, 25, 49, 121 etc. All you need to check is how many perfect square of a prime numbers lie between upBorder and downBorder.
You can reduce the complexity of the loop from O(number) to O(sqrt(number)).
This is based on the observation that if number is divisible by i, then it is also divisible by number/i. Given this, you can count the two divisors at once; given that the sparsity of the divisors increases as the number increases (i.e. the number of numbers you have to check before finding a divisor), you can save a lot of work in this way.
For example:
for (long i = 2; i*i <= n; ++i) {
if (n % i == 0) {
// i is a divisor, so increment the counters.
numOfDivs++; sum += i;
long c = n / i;
if (c != i) {
// c is a distinct divisor from i, so also increment the counters.
numOfDivs++; sum += c;
}
}
}
For example, 10 = 5*2. This approach finds a divisor when i=2, meaning that c=5. It can stop checking after i=3. In contrast, checking while i<=10/2 will stop checking after i=5.
As the number increases, the difference becomes far greater. For example, with number==1000, you check 499 numbers with i<=1000/2, but just 30 with i*i <= 1000.

Represent an Integer as a sum of Consecutive positive integers

I am writing code for counting the number of ways an integer can be represented as a sum of the consecutive integers. For Example
15=(7+8),(1+2+3+4+5),(4+5+6). So the number of ways equals 3 for 15.
Now the input size can be <=10^12. My program is working fine till 10^7(i think so, but not sure as i didnt check it on any online judge. Feel free to check the code for that)
but as soon as the i give it 10^8 or higher integer as input. it throws many runtime exceptions(it doesnt show what runtime error). Thanks in advance.
import java.io.*;
//sum needs to contain atleast 2 elements
public class IntegerRepresentedAsSumOfConsecutivePositiveIntegers
{
public static long count = 0;
public static void main(String[] args) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
long num = Long.parseLong(br.readLine()); //Enter a number( <=10^12)
driver(num);
System.out.println("count = " + count);
}
public static void driver(long num)
{
long limit = num / 2;
for(long i = 1 ; i <= limit ; i++)
{
func(i,num);
}
}
public static void func(long i,long num)
{
if(i < num)
{
func(i + 1,num - i);
}
else if(i > num)
{
return;
}
else
{
count++;
}
}
}
Use some math: if arithmetic progression with difference 1 starts with a0 and contains n items, then its sum is
S = (2 * a0 + (n-1))/2 * n = a0 * n + n * (n-1) / 2
note that the second summand rises as quadratic function. So instead of checking all a0 in range S/2, we can check all n is smaller range
nmax = Ceil((-1 + Sqrt(1 + 8 * S)) / 2)
(I used some higher approximation).
Just test whether next expression gives integer positive result
a0 = (S - n * (n - 1) / 2) / n
Recursive function isn't suitable when you have big input size like your case.
The maximum depth of the java call stack is about 8900 calls and sometimes only after 7700 calls stack overflow occurs so it really depends on your program input size.
Try this algorithm I think it worked for your problem:
it will work fine until 10^9 after that it will take much more time to finish running the program.
long sum = 0;
int count = 0;
long size;
Scanner in = new Scanner(System.in);
System.out.print("Enter a number <=10^12: ");
long n = in.nextLong();
if(n % 2 != 0){
size = n / 2 + 1;
}
else{
size = n / 2;
}
for(int i = 1; i <= size; i++){
for(int j = i; j <= size; j++){
sum = sum + j;
if(sum == n){
sum = 0;
count++;
break;
}
else if(sum > n){
sum = 0;
break;
}
}
}
System.out.println(count);
Output:
Enter a number <=10^12: 15
3
Enter a number <=10^12: 1000000000
9
BUILD SUCCESSFUL (total time: 10 seconds)
There's a really excellent proof that the answer can be determined by solving for the unique odd factors (Reference). Essentially, for every odd factor of a target value, there exists either an odd series of numbers of that factor multiplied by its average to produce the target value, or an odd average equal to that factor that can be multiplied by double an even-sized series to reach the target value.
public static int countUniqueOddFactors(long n) {
if (n==1) return 1;
Map<Long, Integer> countFactors=new HashMap<>();
while ((n&1)==0) n>>>=1; // Eliminate even factors
long divisor=3;
long max=(long) Math.sqrt(n);
while (divisor <= max) {
if (n % divisor==0) {
if (countFactors.containsKey(divisor)) {
countFactors.put(divisor, countFactors.get(divisor)+1);
} else {
countFactors.put(divisor, 1);
}
n /= divisor;
} else {
divisor+=2;
}
}
int factors=1;
for (Integer factorCt : countFactors.values()) {
factors*=(factorCt+1);
}
return factors;
}
As #MBo noted, if a number S can be partitioned into n consecutive parts, then S - T(n) must be divisible by n, where T(n) is the n'th triangular number, and so you can count the number of partitions in O(sqrt(S)) time.
// number of integer partitions into (at least 2) consecutive parts
static int numberOfTrapezoidalPartitions(final long sum) {
assert sum > 0: sum;
int n = 2;
int numberOfPartitions = 0;
long triangularNumber = n * (n + 1) / 2;
while (sum - triangularNumber >= 0) {
long difference = sum - triangularNumber;
if (difference == 0 || difference % n == 0)
numberOfPartitions++;
n++;
triangularNumber += n;
}
return numberOfPartitions;
}
A bit more math yields an even simpler way. Wikipedia says:
The politeness of a positive number is defined as the number of ways it can be expressed as the sum of consecutive integers. For every x, the politeness of x equals the number of odd divisors of x that are greater than one.
Also see: OEIS A069283
So a simple solution with lots of room for optimization is:
// number of odd divisors greater than one
static int politeness(long x) {
assert x > 0: x;
int p = 0;
for (int d = 3; d <= x; d += 2)
if (x % d == 0)
p++;
return p;
}

Calculating the number of prime factors

The following was the problem on codeforce
Two soldiers are playing a game. At the beginning first of them chooses a positive integer n and gives it to the second soldier. Then the second one tries to make maximum possible number of rounds. Each round consists of choosing a positive integer x > 1, such that n is divisible by x and replacing n with n / x. When n becomes equal to 1 and there is no more possible valid moves the game is over and the score of the second soldier is equal to the number of rounds he performed.
To make the game more interesting, first soldier chooses n of form a! / b! for some positive integer a and b (a ≥ b). Here by k! we denote the factorial of k that is defined as a product of all positive integers not large than k.
What is the maximum possible score of the second soldier?
Input
First line of input consists of single integer t (1 ≤ t ≤ 1 000 000) denoting number of games soldiers play.
Then follow t lines, each contains pair of integers a and b (1 ≤ b ≤ a ≤ 5 000 000) defining the value of n for a game.
Output
For each game output a maximum score that the second soldier can get.
So i tried to calculate the number of prime factors of n(as in the prime factorization of n).
Following is my my code but it fails for the test case
a=5000000 and b= 4999995
import java.util.Scanner;
import java.lang.*;
public class Main {
public static void main (String[] args) throws java.lang.Exception
{
// your code goes here
int count=0;
Scanner input=new Scanner(System.in);
int testcases=input.nextInt();
for(int m=1;m<=testcases;m++){
count=0;
long a=input.nextLong();
long b=input.nextLong();
double n=1;
for(double i=b+1;i<a+1;i++)
n=n*i;
//System.out.println(Math.sqrt(n));
for(int i=2;i<Math.sqrt(n);i++){
if(n%i==0){
while(n%i==0){
n=n/i;
count++;
}
}
}
if(n!=1) count++;
System.out.println(count);
}
}
}
In your case, a! / b! is
3,124,993,750,004,374,998,750,000,120,000,000
which is somewhat larger than 2^111. Only numbers up to 2^53 can be safely represented as an integer with a double value. If you use long, you can crank that up to 2^63, which still isn't enough.
You must either use BigInteger or you must change your approach: Instead of dividing the result of a! / b! into prime factors, divide the factors that contribute to the factorial and then merge the prime factor sets.
To illustrate with your example:
5000000 == 2^6 * 5^7
4999999 == 4999999
4999998 == 2 * 3 * 191 * 4363
4999997 == 43 * 116279
4999996 == 2^2 * 1249999
a! / b! == 2^9 * 3 * 5^7 * 43 * 191 * 4363 * 116279 * 1249999 * 4999999
As the input for a and b is small, we can create an array numOfPrime, which at index ith,
numOfPrime[i] = number of prime factor of i
So, we notice that numOfPrime[i] = 1 + numOfPrime[i/x] with x is any prime factor of i.
For simplicity, let x be the smallest prime factor of i, we can use Sieve of Eratosthenes to precalculate x for each i
int[]x = new int[5000001];
for(int i = 2; i < x.length; i++)
if(x[i] == 0)
for(int j = i + i; j < x.length; j+= i)
if(x[j] == 0)
x[j] = i;
int[]numOfPrime = new int[5000001];
for(int i = 2; i < x.length; i++)
if(x[i] == 0)
numOfPrime[i] = 1;
else
numOfPrime[i] = 1 + numOfPrime[i/x[i]];
You can take a look at my submission for this problem
Based on #m-oehm's answer:
int[] factors = new int[a-b];
for(int i=0;i<a-b;i++)
factors[i] = b+1+i;
boolean done = false;
int i = 2;
while(!done){
done = true;
for(int j=0; j<a-b; j++){
if(i>Math.sqrt(factors[j]) && factors[j]!=1){ // factors[j] is prime
factors[j] = 1;
count++;
}else{
while(factors[j]%i==0){ // divide factors[j] by i as many times as you can
factors[j]/=i;
count++;
}
}
if(factors[j]!=1) // if all factors have reach 1, you're done
done = false;
}
i++;
}

Prime Number Finder has a mind of its own?

I am making a prime number finder, that would find the prime numbers for a given number that the user inputs. What I have now seems to either miss primes, or add non-primes to the ArrayList. My code seems logical to me, and I'm confused as to why this is happening. Can anyone tell me what I am doing wrong? Or maybe a simpler way to do this (I feel like I am over-complicating)? Some examples of errors would be: Enter 21, only 3 shows as a prime. Enter 11000, 25 and 55 show up (not prime obviously). Thanks in advance!
import java.util.*;
public class PrimeFactors {
public static void main(String args[]) {
long num;
Scanner in = new Scanner(System.in);
System.out.println("\n\n\nThis program finds the prime factors of a given number.\n");
System.out.print("Please enter the number: ");
num = in.nextLong();
System.out.println("\nThe prime factors are: " + primeFactor(num) + "\n");
}
public static ArrayList<Long> primeFactor(long n) {
long output = 0;
long guess = 2;
ArrayList<Long> primeFactors = new ArrayList<Long>();
while (guess <= n) {
long primes = 0;
long i = 2;
long x = 0;
long rt = 1;
long duplicate = 0;
output = n % guess;
// Finds the sqrt.
while (x <= n) {
x = rt * rt;
rt++;
}
// Finds odd factors.
if ((output == 0) && (guess % 2 != 0)) {
// This divides the odd factor by an incrementing number that is not 1 or the number itself.
while (i < rt) {
primes = primes + (guess % i);
// If the sum of the remainders to the division is not 0, then the number is prime.
// I used duplicate to make sure it didn't just go through once and count as prime.
if (primes != 0){
// There were duplicates, so I added them for the division later.
duplicate = duplicate + guess;
// This was used to wait for the while loop to finish, then find if the amount of times the guess went through was equal to its value - 1 and another 1 for the final number (primes are only divisible by one and itself).
if (i == (factors - 1)) {
if ((duplicate / guess) == (guess- 2)) {
primeFactors.add(guess);
}
}
}
i++;
}
}
guess++;
}
return primeFactors;
}
}
The math and logic you're doing here is very strange and I don't quite follow what's happening.
To that end, I would vote +1 for making the code simpler. This can be done with two simple methods. The first method will find factors for a number and run them through a prime checker. If they are a factor and pass the prime check, they get added to the array.
Bonus points: increase the speed of the algorithm by only searching through the bottom half of each of the factor checker and prime checker. Logic being that any value beyond half a number cannot be a factor of that number.
More bonus points for speed, increment by 2 skipping all multiples of 2, since they are automatically not prime. Good luck!
import java.util.ArrayList;
import java.util.Scanner;
/***************************************************
*
* #file: PrimeFactors.java
* #date: Mar 17, 2013
* #author: AaronW
*/
/**
*
* #author AaronW
*/
public class PrimeFactors {
public PrimeFactors() {
}
/**
*
* #param args
*/
public static void main(String[] args) {
long num;
Scanner in = new Scanner(System.in);
System.out.println("\n\n\nThis program finds the prime factors of a given number.\n");
System.out.print("Please enter the number: ");
num = in.nextInt();
System.out.println("\nThe factors are: " + findFactors((double)num) + "\n");
}
public static ArrayList<Integer> findFactors(Double num) {
ArrayList<Integer> factors = new ArrayList<Integer>();
for (int x = 1; x <= num; x++) {
System.out.println("Testing " + num + " % " + x + " = " + num % x);
// First, let's see if a number is factor of your target number
if (num % x == 0) {
System.out.println(x + " is a factor");
// Now that we know it's a factor, let's test to see if it's prime
if (isPrime(x)) {
// If it's prime, add it to the ArrayList
System.out.println("And " + x + " is prime.");
factors.add(x);
} else {
System.out.println("But " + x + " is not prime.");
}
} else {
System.out.println(x + " is not a factor");
}
}
return factors;
}
public static boolean isPrime(double num) {
// Let's start by assuming everything is prime and try to prove that false
// If we fall through the loop without proving it false, we have a prime
boolean prime = true;
for (int x = 2; x < num; x++) {
// if our target number can be divided by any number between 1 and itself, it is not prime
if (num % x == 0) {
prime = false;
}
}
return prime;
}
}
For a start, instead of
long x = 0;
long z = 1;
while (x <= n) {
x = z * z;
z++;
}
while (j < z) {
You can just do this
z = (int) Math.Sqrt(n)
while (j <= z) {
Then for each j I would check if it divides n with no remainder.
If it divides n with no remainder, divide n by j and add j to the prime factors. Then instead of incrementing j, try the same j again, for instance for 9 you do 3 twice for its factors.
Anything more complex than that is unnecessary - you will try each j until it can divide into n no more, and you will always try primes before composites formed of those primes, so you know off the bat you'll end up with only prime factors.
OK, there are a few problems with your code:
j, x, j & n, poorly named variables make for hard work debugging.
Where are your System.out.println() calls so you can see what is going on in your code?
The square root of n would be a more optimal point to stop looking for prime up to n.
Can I suggest you look at this: http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes for a rapid way of finding primes.
One suggestion to make the code simpler. In you primeFactors method, first findout is it a factor, which I believe you are already doing, then call another method to determine if this is a prime. If that is prime add to the list.
I'll give you some pseudo-code for a simple to implement (not efficient) algorithm:
the value to factorize is N
keep going until N is equal to one
start at 2 and find lowest number X that divides N evenly
X is one factor
N/X is your new N to factor
Your variable names are inconsistent. factors is particularly bad, as it is only a guess of a single factor. Call it guess instead.
The arithmetic you do with factors, primes, and dup are also strange. Why are you adding to dup or primes? Try being your own computer, and executing your algorithm for the number 12; you'll see that you don't have a correct algorithm at all.
You've foreclosed the possibility of repeated factors by incrementing factors at the end.

Counting the occurrence of each number in prime factors of an integer

I want to count the number of each prime factor of an integer. For an example 18=2^1*3^2. I want to get all exponent part of each prime number. For number 18, it is 1+2=3.Below is the program which generates all the prime factors of an integer.
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
for (int i = 2; i <= n / i; i++) {
while (n % i == 0) {
System.out.print(i + ", ");
n /= i;
}
}
if (n > 1)
System.out.print(n + ", ");
For input 18, this program prints 2, 3, 3, . As for completing my requirement, to count the occurrence of each prime factor, i can first add them all to a list, then a for loop from starting to ending of the list can count the occurrence of each number. But this idea doesn't seem good to me. Unnecessary i am adding one for loop, for all prime factors, which just tells me that this prime factor comes n times in the list.Any better approach to get the number of individual number of prime factors of an integer.
yy, just as #attila and #robert said:
import java.util.Scanner;
import java.util.TreeMap;
public class Test{
public static void main( String args[] ){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
TreeMap<Integer, Integer> factors = new TreeMap<Integer, Integer>();
for (int i = 2; i <= n / i; i++) {
int count = 0;
while (n % i == 0) {
System.out.print(i + ", ");
n /= i;
count ++;
}
if( count > 0 )
factors.put( i, count );
}
if (n > 1){
System.out.print(n + ", ");
factors.put( n, 1 );
}
System.out.println();
System.out.println( "-------------" );
for( Integer factor : factors.keySet() ){
System.out.println( factor + "^" + factors.get( factor ) );
}
}
}
i'm using a treemap because it keeps the factors in their natural order, which is neat :)
you could also use a hashmap which should be a bit faster. but the implementation of the prime decomposition should be so slow that i don't think it matters much :)
Every time you are executing n/=i;, you are encountering a factor. So by incrementing a counter (Starting from 0) at that point, you get the total number of factors at the end of the factorization process.
Note that you need an extra if for properly handling prime numbers. For primes you do not find any factors, so the counter will be 0 -- you need to set it to 1 after the loop in this case (one factor: itself)

Categories

Resources