Today I practiced for my coding test using projecteulers problems. While doing the prime factor division I stumbled across something I found weird. Here is the relevant code (res is an ArrayList):
for (int x = 2; x <= n; x++){
if (n % x == 0){
System.out.println("Prime found: " + x);
res.add(x);
n = n / x;
}
}
Which divided 1000 into [2, 4, 5, 25].
After a while I tried replacing the if-statement with a while-loop and it printed me the correct answer [2, 2, 2, 5, 5, 5].
Obviously there is somthing I didn't understand, could someone explain this to me, please?
Edit:
The newer code:
for (int x = 2; x <= n; x++){
while (n % x == 0){
System.out.println("Prime found: " + x);
res.add(x);
n = n / x;
}
}
The difference is:
If you use if, every number is tested only once. So if you are able to pull out the 2, you try so only once. The next number you can pull out is the 4, although it is not a prime.
The same holds for the 5 resp. 25.
If you use while, you test each number until you know it's no longer in the number to test.
You could also change it into
for (int x = 2 ; x <= n/x ; ) {
if (n % x == 0) {
System.out.println("Prime factor: " + x);
res.add(x);
n = n / x;
}
else {
x++; // increment moved here
}
}
if (n > 1) {
System.out.println("Prime factor: " + n);
res.add(n);
}
I've also changed the termination condition, to make it much more efficient in cases where n's largest prime factor is itself large, because if n = a*b and a <= b, then a*a <= a*b = n, i.e. a <= n/a.
This repeats the test for a prime factor, because as you've found out, some numbers have multiple prime factors of same magnitude (like 1000 = 2*2*2*5*5*5). It is equivalent to your while loop, because the increment is now conditional, performed only when the tested candidate was not n's factor.
Related
public class Solution {
public String nearestPalindromic(String n) {
long num = Long.parseLong(n);
for (long i = 1;; i++) {
if (isPalindrome(num - i))
return "" + (num - i);
if (isPalindrome(num + i))
return "" + (num + i);
}
}
boolean isPalindrome(long x) {
long t = x, rev = 0;
while (t > 0) {
rev = 10 * rev + t % 10;
t /= 10;
}
return rev == x;
}
}
Found here
In the explanation of the brute force solution seen above, Leetcode claims "Up to 2 x sqrt{n} numbers could be generated in the worst case."
how do we know that the closest palindrome is within sqrt{n} distance of the input?
My second question is if there are 2sqrt{n} numbers generated in the worst case then shouldn't the overall time complexity be 2sqrt{n} * n since isPalindrome is log(n) with base 10?
Edit: 2nd question has been answered in comments.
Just figure out how many numbers say from 1 to 1,000,000 are palindromic. Say that number is n. If you examine a million consecutive numbers starting at 1, n of them are palindromic. So if you examine numbers until you find a palindromic one, you examine on average 1,000,000 / n numbers.
I am trying to find the Largest prime factor of a number while solving this problem here. I think that I am doing everything right, however one of the test case (#2) is failing and I can't think of any corner case where it might fail. Here's my code, please have a look and try to spot something.
public class ProblemThree
{
public static void main(String[] args)
{
Scanner scanner = new Scanner(System.in);
int T = scanner.nextInt();
for (int i = 0; i < T; i++)
{
System.out.println(largestPrime(scanner.nextLong()));
}
}
private static long largestPrime(long n)
{
while (n % 2 == 0)
{
n = n / 2; // remove all the multiples of 2
}
while (n % 3 == 0)
{
n = n / 3; // remove all the multiples of 2
}
// remove multiples of prime numbers other than 2 and 3
while (n >= 5)
{
boolean isDivisionComplete = true;
for (long i = 5; i < Math.ceil(Math.sqrt(n)); i++)
{
if (n % i == 0)
{
n = n / i;
isDivisionComplete = false;
break;
}
}
if (isDivisionComplete)
{
break;
}
}
return n;
}
}
Basically, what I am doing is:
Largest_Prime(n):
1. Repeatedly divide the no by any small number, say x where 0 < x < sqrt(n).
2. Then set n = n/x and repeat steps 1 and 2 until there is no such x that divides n.
3 Return n.
It seems you have some bug in your code as as when you input 16 largestPrime function return 1. and this is true for when input is the power of 3.
Detailed Algorithm description:
You can do this by keeping three variables:
The number you are trying to factor (A)
A current divisor store (B)
A largest divisor store (C)
Initially, let (A) be the number you are interested in - in this case, it is 600851475143. Then let (B) be 2. Have a conditional that checks if (A) is divisible by (B). If it is divisible, divide (A) by (B), reset (B) to 2, and go back to checking if (A) is divisible by (B). Else, if (A) is not divisible by (B), increment (B) by +1 and then check if (A) is divisible by (B). Run the loop until (A) is 1. The (3) you return will be the largest prime divisor of 600851475143.
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t = in.nextInt();
for(int a0 = 0; a0 < t; a0++){
long n = in.nextLong();
long A=n;
long B=2;
long C=0;
while(Math.pow(B,2)<=A)
{
if(A%B==0)
{
C=B;
A=A/B;
B=2;
}
else
B++;
}
if(A>=C)
C=A;
if(A==1)
{ C=2;
break;
}
System.out.println(C);
}
}
Why are you removing multiples of 2 and multiples of 3? This way if you have a number that is any combination of powers of 2 and 3 you will get your answer as 1 which is clearly wrong.
For this problem you can do the naive way of looping from 2 to sqrt(n) and store the largest number which divides n, when you finish your loop just return the highest divisor you found.
1 drop your loop for 2 and 3. If not, you dont get 2, 2x2, 3, 2x3, ... all multiples of 2 and 3
2 change your loop to stop at 2 (and not 5):
while (n >= 2)
{
3 stop if 2
if (n==2) return 2;
4 loop from 2
and
5 loop until sqrt(n), with <= and not only < (if not, you dont get prime X Prime)
for (long i = 2; i <= Math.ceil(Math.sqrt(n)); i++)
One easy way of extracting prime factors is like this:
/**
* Prime factors of the number - not the most efficient but it works.
*
* #param n - The number to factorise.
* #param unique - Want only unique factors.
* #return - List of all prime factors of n.
*/
public static List<Long> primeFactors(long n, boolean unique) {
Collection<Long> factors;
if (unique) {
factors = new HashSet<>();
} else {
factors = new ArrayList<>();
}
for (long i = 2; i <= n / i; i++) {
while (n % i == 0) {
factors.add(i);
n /= i;
}
}
if (n > 1) {
factors.add(n);
}
return new ArrayList<>(factors);
}
Those first loops are a problem. They will reduce all even numbers to 1 - thus missing 2 as the factor. Changing your code to use:
while (n > 2 && n % 2 == 0) {
n = n / 2; // remove all the multiples of 2
}
while (n > 3 && n % 3 == 0) {
n = n / 3; // remove all the multiples of 2
}
You still have further issues - e.g. you report the largest prime factor of 25 to be 25 and the largest prime factor of 49 to be 49.
Just run this code using yours and mine to see where yours fails:
for (long i = 1; i < 1000; i++) {
long largestPrime = largestPrime(i);
List<Long> primeFactors = primeFactors(i, true);
if (primeFactors.size() > 0) {
Collections.sort(primeFactors, Collections.reverseOrder());
long highestFactor = primeFactors.get(0);
if (largestPrime != highestFactor) {
System.out.println("Wrong! " + i + " " + largestPrime + " != " + primeFactors);
}
} else {
System.out.println("No factors for " + i);
}
}
I need to write a code which should calculate the first 200 prime numbers, but I can't hand it in as long as I can't explain everything. I used a piece of code from the internet as reference (http://crab.rutgers.edu/~dhong/cs325/chapter3/PrimeNumber.java).
Whole code:
public class Opdracht3 {
public static void main(String[] args) {
int limiet = 200;
int counter = 1;
int testpriem = 3;
boolean isPriem;
while (counter <= limiet) {
isPriem = true;
for (int i = 2; i <= testpriem / 2; i++) {
if (testpriem % i == 0) {
isPriem = false;
break;
}
}
if (isPriem) {
System.out.println(counter + ": " + testpriem);
counter++;
}
testpriem++;
}
}
}
Below part of code verifies if the number is a composite. If testpriem is composite, then comes out of the loop and starts over. Otherwise, it continues and prints the prime number testpriem.
The problem is here:
for (int i = 2; i <= testpriem / 2; i++) {
if (testpriem % i == 0) {
isPriem = false;
break;
}
}
I tested what happens to i, and one way or another it recognizes the divisor needed to calculate the composite. (With 4 divisor is 2, with 9 divisor is 3, with 221 divisor is 13) But I am flabbergasted as of why.
Any ideas?.
the % or ("remainder") operator in Java divides one operand by another and returns the remainder as its result. And of course if integer x is evenly divisible by another integer y (meaning x/y = some integer z with a remainder of zero), then x can not be prime.
First remember every number able to divide by its half or less. Consider number 7 it is possible divided by 1,2,3 because after 3, if try to divide number by 4 means 4x2 = 8 that is greater than 7. so it is optimum way to find divisor in this way. One more thing every number divided by 1 and number itself. so if number number is divided by 1 or itself then it is called prime so i starts from 2.
now consider testpriem =7 so you will get loop like
for (int i = 2; i <= 7 / 2(i.e 3); i++)
{
if(7 % i == 0)
{
isPriem = false;
break;
}
so first time it checks 7%2=1 so condition false. again check for 7%3 = 1 again condition false. and now this condition full fills here i <= 7 / 2(i.e 3) so loop stopped and it result 7 number is prime
Well, if testpriem % i == 0, it means that i divides testpriem, which means that testpriem is not a prime a number and i, is its first divider. % is the modulo operation, which is the rest of the division.
https://en.wikipedia.org/wiki/Modulo_operation
The break stops the for loop and moves to the next position in the while loop. So it does not restart the for loop for the current tested number.
The break is used for efficiency reasons. You could remove it and the algorithm would still work correctly but slower.
So I need to output a sum of factorials like 1!+2!...+n!=sum I found a way to get a single factorial but I don't know how to sum them together. This is my attempt at doing so:
System.out.println("Ievadiet ciparu");
Scanner in = new Scanner(System.in);
n = in.nextInt();
if ( n < 0 )
System.out.println("Ciparam jabut pozitivam.");
else
{
while (x>2){
for ( c = 1 ; c <= n ; c++ )
fact = fact*c;
sum=sum+fact;
n=n-1;
if (n==0) break;
}
System.out.println("Faktorialu summa "+sum);
Rather than have a loop 1-n and calculate each factorial elsewhere, I would accumulate the sum as you calculate the factorials - ie have two local variables; one for factorial and one for the sum:
long factorial = 1, sum = 0;
for (int i = 1; i <= n; i++) {
factorial *= i;
sum += factorial;
}
When tested with n = 5, sum is 153, which is correct: 1 + 2 + 6 + 24 + 120
Your problem was that the sum was outside the loop - you just needed braces like here.
Also, your while loop condition x < 2 will never change, so either the loop will never execute (if x > 1) or the loop will never terminate, because x is not changed within the loop.
hmmm my search for finding a recursive(via recursive method calling) version of these code still getting nowhere
`public static long factorialSum(long n){
long x = n;
for(int i = 1; i < n; i++){
x = (n-i)*(1+x);
}
return x;
}`
if you just look at the problem more closely you'll see you can do it in linear time, the trick is in (n-1)! + n! = (n-1)!*(1 + n), to understand this more deeply i recommend add (n-2)! just to see how it grows.
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.