Java Largest Prime Factor of Long - java

I'm trying to find the largest prime factor of a large number. For example, if that number were 573849284703, my code would look like this:
public static void main(String[] args) {
long number = 573849284703l;
System.out.println(lgstprmfactor(number));
}
public static long lgstprmfactor(long number) {
for (long i = 286924642352l; i > 0; i--) {
if (number % i == 0 && isPrime(i) == true) {
long answer = i;
return answer;
}
}
return 0;
}
public static boolean isPrime(long i) {
for (long c = 2; c < i; c++) {
if (i % c == 0)
return false;
}
return true;
}
But it's taking forever to run- any suggestions to speed it up or optimize the code in general?

One quick solution to improve runtime could be to implement your algorithm in multiple threads that concurrently check if the number is a prime factor across different ranges. I.e. create a thread that checks if it is a prime factor between 0 and 1000000, then a thread for 1000001+ etc.

public static void main(String[] args)
{
long startTime = System.currentTimeMillis();
System.out.println(largestprimefactor(573849284703l));
long endTime = System.currentTimeMillis();
System.out.println(endTime - startTime+" ms ");
}
public static int largestprimefactor(long l)
{
int i;
long copyofinput = l;
for(i=2;i<copyofinput;i++)
{
if(copyofinput%i==0){
copyofinput/=i;
i--;
}
}
return i;
}
}
output :
66718903
688 ms

The basic ideas here: remove prime factors as you find them, don't search higher than the square root of the remaining number, and skip even numbers (other than 2). I also added some error checking and other decorations.
public static void main(String[] args)
{
try {
System.out.println(largestPrimeFactor(573849284703l));
} catch (ArithmeticException e) {
System.out.println("Error factoring number: " + e.getMessage());
}
}
private static long sqrtint(long n) {
return (long)Math.sqrt(n + 0.5);
}
public static int largestPrimeFactor(long n) throws ArithmeticException
{
if (n < 2) throw new ArithmeticException(n + " < 2");
while (n%2 == 0) n /= 2;
if (n < 2) return 2;
long i, root = sqrtint(n);
for(i=3; i<root; i+=2)
{
if(n%i == 0) {
n /= i;
while (n%i==0) n /= i;
if (n == 1) return i;
root = sqrtint(n);
}
}
return n;
}
}

Related

Checking if an integer is a circular prime number without using String

I have to write a boolean method that checks if a number n is a circular prime, using only integer computations, so no Strings. I wrote two other methods that have to be included.
boolean isPrime(int n) {
if (n < 1) {
return false;
} else if (n == 1 || n == 2) {
return true;
} else if (n % 2 != 0) {
for (int i = 3; i < n; i+=2) {
if (n % i == 0) {
return false;
}
}
return true;
} else {
return false;
}
}
This checks if the number is a prime.
int largestPowerOfTen(int n) {
for (int i = 1; i < n * 10; i*=10) {
if (n / i == 0) {
return i / 10;
}
}
return 1;
}
This returns the largest power of ten of the number. For instance, 23 would return 10, 704 would return 100, etc.
I had the idea to put every digit into an array and move the digits around from there, but I'm stuck at the moving part.
boolean isCircularPrime(int n) {
ArrayList<Integer> k = new ArrayList<Integer>();
int i = 0;
while (n != 0) {
k.add(n % 10);
n /= 10;
i++;
}
//???
}
So how do I move the digits around?
Assuming a "circular prime number" is a number that is a prime number for all rotations of the digits...
You can't just rotate the number, because zeroes won't be conserved.
First break up the number into an array - each digit of the number an element of the array. Use n % 10 to find the last digit, then n /= 10 until n == 0.
Create a method the generates a number from the array with a specified starting index. This is the crux of the problem, and here's some code:
private static int generate(int[] digits, int index) {
int result = 0;
for (int i = 0; i < digits.length; i++) {
result = result * 10 + digits[(index + i) % digits.length];
}
return result;
}
Then loop over every possible starting index for your digits and check if it's prime.
The remaining code I leave to the reader...
import java.util.Scanner;
class CircularPrime
{
public boolean prime(int n)
{
int lim=n,count=0;
for(int i=1;i<=lim;i++)
{
if(n%i==0)count++;
}
if(count==2)
return true;
else
return false;
}
public int circlize(int n)
{
int len,x,y,circle;
len=(""+n).length();
x=n/(int)Math.pow(10,len-1);
y=n%(int)Math.pow(10,len-1);
circle=(y*10)+x;
return circle;
/**
Another way using String
String str = Integer.toString(n);
String arr = str.substring(1)+str.charAt(0);
int a = Integer.parseInt(arr);
return a;
**/
}
public void check(int n)
{
int a=n;
boolean flag=true;
System.out.println("OUTPUT:");
do
{
if(!(prime(a)))
{
flag=false;
break;
}
a=circlize(a);
System.out.println(a);
}while(a!=n);
if(flag)System.out.println(n+" IS A CIRCULAR PRIME");
else System.out.println(n+" IS NOT A CIRCULAR PRIME");
}
public static void main(String ar[])
{
CircularPrime obj = new CircularPrime();
Scanner sc = new Scanner(System.in);
System.out.print("Enter a number: ");
int n=sc.nextInt();
obj.check(n);
}
}

Java - Recursion sum of number and how it work

I am trying to write a recursive function that when I call with number 5 for example then the function will calculate the sum of all digits of five.
1 + 2 + 3 + 4 + 5 = 15
The current code always returns 0, how can the amount each time the n?
public class t {
public static void main(String[] args) {
System.out.println(num(5));
}
public static int num(int n) {
int sum = 0;
sum += n;
if (n == 0)
return sum;
return num(n - 1);
}
}
thank you.
Instead of setting the sum to 0 you can -
Do this:
public int sumUp(int n){
if (n==1)
return 1;
else
return sumUp(n-1)+n;
}
The problem is you set the sum always 0.
public static void main(String[] args) {
System.out.println(num(5, 0));
}
public static int num(int n, int sum) {
if (n == 0) {
return sum;
}
sum += n;
return num(n - 1, sum);
}
public static int withRecursion(List<Integer> list) {
int size = list.size();
int a=0;
if(list.isEmpty() == true) {
return 0;
}else {
a = a + list.get(0) + withRecursion(list.subList(1, size));
return a;
}
}

I need to get all the prime numbers from 1 to a large number?

I need to create a program that can get all the prime numbers from 1 to a large number. I have a getPrime method which returns true if the number is prime or false if it is not prime. When I use this method and a while loop to get a list of prime numbers from 1 to a large number it keeps returning 24 then 4 then 5.the variable end, in code below is asked for in a prime class runner separately. Here is my code:
public class Prime
{
private long userNumber;
private int numRoot;
private int x;
private boolean isPrime;
private int factors;
private long end;
private int i;
public void setUserNumber(long num)
{
userNumber = num;
}
public void setEndNumber(long n)
{
end = n;
}
public boolean getPrime()
{
numRoot = ((int)Math.sqrt(userNumber));
for (x=2; x<=numRoot; x++)
{
if ((userNumber % x) == 0)
{
factors++;
}
}
if (factors >1) {
isPrime = false;
}
else {
isPrime = true;
}
return isPrime;
}
public void getPrimeList()
{
if(end < 2) {
System.out.println("No prime numbers");
System.exit(0);
}
System.out.printf("\nThe prime numbers from 1 to %d are: \n 2", end);
Prime primeNum = new Prime();
i = 3;
while( i <= end )
{
userNumber = i;
getPrime();
if (isPrime == true)
{
System.out.println(userNumber);
}
i++;
}
System.out.println();
}
}
public void getPrimes(int N) {
for (int i = 2; i <= N; i++) {
if (isPrime(i)) System.out.println(i);
}
System.out.println("These are all the prime numbers less than or equal to N.");
}
private boolean isPrime(int N) {
if (N < 2) return false;
for (int i = 2; i <= Math.sqrt(N); i++) {
if (N % i == 0) return false;
}
return true;
}
The code below is written in C#, although it will work in Java with very little modification.
I use a long as the data type as you haven't been specific when you say "a large number".
public static bool isPrime(long Number)
{
if (Number == 1) { return false; }
int i = 2;
while (i < Number)
{
if (Number % i++ == 0) { return false; }
}
return true;
}
It can be applied like so, again this is C#, but will work in Java with little modification.
while (i <= LARGE_NUMBER)
{
Console.Write((isPrime(i) ? i.ToString() + "\n" : ""));
i++;
}
public class PrimeTest{
private static final int MAX_NUM = Integer.MAX_VALUE; // your big number
public static void main(String[] args) {
int count = 0;
for(int i=0; i<MAX_NUM; i++) {
if (isPrime(i)) {
System.out.printf("Prime number %d\n", i);
count++;
}
}
System.out.printf("There is %d prime numbers between %d and %d\n", count, 0, MAX_NUM);
}
public static boolean isPrime(int number) {
if (number < 2) {
return false;
}
for (int i=2; i*i <= number; i++) {
if (number % i == 0) {
return false;
}
}
return true;
}
}
A prime number p should have zero factors between 2 and sqrt(p), but you are allowing one here:
if (factors >1){
isPrime = false;
}
In fact, there's no need to count factors at all, you can directly do
if ((userNumber % x) == 0) {
return false;
}
If you however need to count factors anyways, I would suggest setting factors explicitly to 0 at the start. It's not a good practice to rely on implicit initial values.
The problem is that you're using too many instance variables inside getPrime, causing you to unintentionally inherit state from previous iterations. More precisely, factors should be reset to 0 at the start of getPrime.
A better way to go about this is by making x, numRoot, isPrime and factors local variables of getPrime:
public boolean getPrime()
{
int factors = 0;
boolean isPrime;
int numRoot = ((int) Math.sqrt(userNumber));
for (int x=2; x<=numRoot; x++)
{
if ((userNumber % x) == 0)
{
factors++;
}
}
if (factors >1){
isPrime = false;
} else {
isPrime = true;
}
return isPrime;
}
You can go even further and make userNumber an argument of getPrime:
public boolean getPrime(int userNumber)
{
// ...
and call it with:
while( i <= end )
{
isPrime = getPrime(i);
if (isPrime)
{
System.out.println(userNumber);
}
i++;
}
Two things to note:
I removed the usage of userNumber inside getPrimeList completely, I simply use i instead.
The isPrime could be removed as well if it's not needed elsewhere, simply use if(getPrime(i)) { ... } instead.
Your algorithm is the wrong solution for your task. The task is to find all primes from 2 to N, the appropriate algorithm is the Sieve of Eratosthenes. (See here for an epic rant discussing basics and optimizations of sieve algorithms.)
It is known that all primes are either 2,3,5,7,11,13 or of the form
30*k-13, 30*k-11, 30*k-7, 30*k-1, 30*k+1, 30*k+7, 30*k+11, 30*k+13,
for k=1,2,3,...
So you generate an array boolean isPrime[N+1], set all to true and for any candidate prime p of the form above, until pp>N and if isPrime[p] is true, set all isPrime[kp]=false for k=2,3,4,...N/p.
int N;
Boolean isPrime[] = new Boolean[N+6];
static void cross_out(int p) {
for(int k=5*p, d=2; k<N; k+=d*p, d=6-d) {
isPrime[k]=false;
}
}
static void sieve() {
for(int k=0; k<N; k+=6) {
isPrime[k ]=isPrime[k+2]=false;
isPrime[k+3]=isPrime[k+4]=false;
isPrime[k+1]=isPrime[k+5]=true;
}
for(int k=5, d=2; k*k<N; k+=d; d=6-d) {
if(isPrime[k]) cross_out(k);
}
}

Project Euler 14 - Java StackOverflowError

For those unfamiliar with the problem, here it is.
I am getting a StackOverflowError with the following code:
public class LongestCollatzSequence {
static int count = 1;
public static void main(String[] args) {
final int range = 1000000;
int maxSeq = 0;
List<Integer> chainList = new ArrayList<Integer>();
for(int i = 1; i <= range; i++) {
generateSequence(i);
if(chainList.isEmpty()) {
chainList.add(count);
count = 1;
} else if(!chainList.contains(count) && count > Collections.max(chainList)) {
chainList.clear();
chainList.add(count);
maxSeq = i;
count = 1;
}
}
System.out.println("Sequence starting number: "+maxSeq);
}
private static void generateSequence(int num) {
if(num == 1) {
return;
}
if(num % 2 == 0) {
count++;
generateSequence(num/2);
} else {
count++;
generateSequence(num*3+1);
}
}
}
High level flow:
-For numbers 2 - 100000, generate a collatz sequence for that number.
-Chain list is a list to store the length of the sequence generated for each number i.e. sequence size for number 13 is 10 (see example).
-If the current sequence size is bigger than the max in the chain list, clear chain list and add the new max, also store the value of i in maxReq to remember the starting number that produces the longest chain.
Interesting problem but the int in java is limited to 2^31-1 you could crox this limit use long or BigInteger
private static void generateSequence(long num) {
if (num == 1) {
return;
}
if (num % 2 == 0) {
count++;
generateSequence(num / 2);
} else {
count++;
generateSequence(num * 3 + 1);
}
}

Recursion - digits in reverse order

I need to implement a recursive method printDigits that takes an integer num as a parameter and prints its digits in reverse order, one digit per line.
This is what I have so far:
public class PrintDigits {
public static void main(String[] args) {
System.out.println("Reverse of no. is " + reversDigits(91));
}
/* Recursive function to reverse digits of num */
public static int reversDigits(int number) {
if (number == 0)
return number;
else {
return number % 10;
}
}
}
I feel like there is only one line of code that I am missing, but not sure what I need to do to fix it.
public static void main(String[] args) {
reverseDigits(98198187);
}
/* Recursive function to reverse digits of num */
public static void reverseDigits(long number) {
if (number < 10) {
System.out.println(number);
return;
}
else {
System.out.println(number % 10);
reverseDigits(number/10);
}
}
This doesn't exactly answer the question, but it actually computes the entire reversed number instead of printing the digits as they are calculated. The result is an int with the digits in reversed order. Much more powerful than printing out the string version of the numbers one by one:
public class Reverse {
public static void main(String[] args) {
// input int parameter
int param = Integer.parseInt(args[0]);
System.out.println(reverse(param));
}
public static int reverse(int input) {
return reverse(input, 0);
}
private static int reverse(int original, int reversed) {
// get the rightmost original digit and remove it
int rightmost = original % 10;
original -= rightmost;
original /= 10;
// add rightmost original digit to left of reversed
reversed += rightmost * Math.pow(10, numDigits(original));
return (original == 0)
? reversed
: reverse(original, reversed);
}
public static int numDigits(int number) {
number = Math.abs(number);
if (number >= 10) {
return 1 + numDigits(number /= 10);
} else if (number > 0) {
return 1;
} else {
return 0;
}
}
}
public static void reversDigits(long number) {
System.out.println(number % 10);
if (number >= 10) {
reversDigits(number / 10);
}
}
This is shortest/simplest version so far;)
public static int reversDigits(int num) {
if(num < 1) {
return 0;
}
int temp = num % 10;
num = (num - temp)/10;
System.out.println(temp);
return reversDigits(num);
}
This will print the digits one at a time in reverse order. You don't need to do System.out in your main method.
I found I had to pick off the highest digit (on the left) and work towards the rightmost digit. I couldn't get a recursive one to work going from right to left.
public static int reverseItRecursive(int number)
{
if (number == 0)
return 0;
int n = number;
int pow = 1;
while (n >= 10)
{
n = n / 10;
pow = pow * 10;
}
return (n + reverseItRecursive(number - n*pow)*10);
}
This should work
int rev = 0;
int reverse(int num)
{
if (num < 10) {
rev = rev*10 + num;
}
else {
rev = rev*10 + (num % 10);
num = reverse(num / 10);
}
return rev;
}
//Try out this, recursion with singe variable using Math class.
public static void main(String[] args) {
// Let the number be 139
int n=139;
System.out.println("reverse is "+rev(n));
}
static int rev(int n){
if (n==0)return 0;
else {
return n%10*(int) Math.pow(10,(double) (int)Math.log10(n))+rev(n/10);
}
}
This method reverse the integer and returns the result without using any string functions, Math, or by just printing
public class ReverseNumber {
public static void main (String[] args) {
ReverseNumber rNumber = new ReverseNumber();
System.out.println(rNumber.reverseRecursive(1234,0)); // pass zero to initialize the reverse number
}
public int reverseRecursive(int n, int reverse) {// n - the number to reverse
// System.out.println(n);
if (n != 0){
reverse = reverse * 10;
reverse = reverse + n %10;
n = n/10;
} else {
return reverse;
}
return reverseRecursive(n,reverse);
}}
public void reverse(int num){
System.out.print(num %10);
if(num / 10 == 0){
return;
}
reverse(num /10);
return;
}
This is very shortest/simplest way in two lines code:
public static int reverseNumber(int n)
{
System.out.println(n % 10);
return (n/10 > 0) ? reverseNumber(n/10) : n;
}
I came looking for a more elegant version than mine, but perhaps this just requires a bit of a messy algorithm. Mine also returns the actual integer value which I agree is much more useful than only printing the string:
Mine:
public static int reverse(int n){
if(n<10)return n;
return n%10*(int)Math.pow(10,(int)Math.log10((double)n)) + reverse(n/10);
}
so this returns the last digit, multiplied by 10^current power + (recursive call)
Here you go :
static String reverseDigits(int n)
{
String N = "";
if ( n== 0)
return N;
else
{
N += n%10;
return N + reverseDigits(n/= 10);
}
}
This is of course returned as String.
If you want it as int all you have to do is parse it using Integer.parseInt()
//Reverse a number using recursion by bibhu.rank
public class Rev_num {
public static int revnum(int x){
int temp1=x,temp2=1;
if(x<10){
return x;
}
while(temp1>=10){
temp2*=10;
temp1/=10;
}
if(((x%temp2) < (temp2/10))&& x%temp2!=0){
int c=temp2;
while(c> x%temp2){
c/=10;
}
c=temp2/c;
temp2=x%temp2;
return((temp1)+(c*revnum(temp2)));
}
temp2=x%temp2;
return (temp1+(10*revnum(temp2)));
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("Enter a number");
Scanner y=new Scanner(System.in);
System.out.println(revnum(y.nextInt()));
y.close();
}
}
public class reverseIntRec{
public static void main(String args[]) {
System.out.println(reverse(91));
}
public static int reverse(int x) {
String strX = String.valueOf(x);
if (Math.abs(x) < 10)
return x;
else
return x % 10 * ((int) Math.pow(10, strX.length()-1)) + reverse(x/10);
}
}
Here is my answer return as integer. I converted x into string to see how many 0s you should multiply with.
For example: reverse(91) returns 1 * 10 + reverse (9), and that returns 10 + 9 = 19.
Relatively simple since you need to print one digit per line. You also state that you print its digits, which implies that leading zeros are still going to be displayed. Our test case
123000 prints :
0
0
0
3
2
1
here is the code, no while, no string, and no math library :
private void printIntegerDigitsReversed(int i) {
if (i / 10== 0 ){
System.out.println(i);
}
else{
printIntegerDigitsReversed(i%10);
printIntegerDigitsReversed(i/10);
}
}

Categories

Resources