before I start I want to clarify that I am not looking for code examples to get the answer; that would defeat the object of Project Euler.
The problem can be found here http://projecteuler.net/problem=3
I think I have a way of solving the problem, but the Algorithm is VERY slow; it has been running for nearly two and a half hours now. So I am looking for general advice on optimisation.
Thanks.
#include<iostream>
using namespace std;
bool primality(int);
int main(){
long long lim = 600851475143;
long long div = lim/2;
bool run = true;
while(run){
if(lim%div==0 && primality(div)){
cout << "HPF: " << div;
run = false;
}
else{
div--;
}
if(div<=1){
break;
}
}
return 0;
}
bool primality(int num){
for(int i=2; i<num; i++){
if(num%i==0 && i!=num){
return false;
}
else{
return true;
}
}
}
If you start div at 2 and count up instead of down, and divide it out from the number when the modulo is zero, you gain two big advantages that are useful here:
You don't have to check if div is prime, since it can't be composite because any prime factors smaller than it would already have been divided out.
You reduce the remaining problem size every time you find a factor, and, as it turns out, the input number has fairly small prime factors.
You could then also break once div*div is greater than the remaining number, as you know at that point that it must be a prime. This is because any divisors greater than the square root are "paired" with one less than the square root. However, since this is an "easy" problem, this optimization is not needed here (although it is useful for later problems).
# Possible solution but still its *time consuming* but answer can be guessed by the last option in console output
#include<stdio.h>
#include<string>
#include<iostream>
#include<math.h>
int prime(unsigned long long);
using namespace std;
int main(){
unsigned long long ii, ij; unsigned long long in;
cin>>in; ij = ceil(in/2);
if( (ij % 2) == 0 ) ij -= 1;
for(ii = 3 ;ii < ij;ii+= 2){
if(in % ii == 0){
if(prime(ii) == 1 ){
cout<<" ans "<<ii<<endl;
}
}
}
return 0;
}
int prime(unsigned long long ii){
unsigned long long ij;
for(ij = 3;ij < ii/2 ;ij += 2){
if( (ii % ij) ==0){
return 0;
}
}
return 1;
}
Related
I was trying this question.
The prime factors of 13195 are 5, 7, 13 and 29.What is the largest prime factor of the number 600851475143 ?
And I had written the following code:
#include<iostream>
#define num 600851475143
using namespace std;
int isprime(unsigned long long int n)
{
unsigned long long int c=0;
for(unsigned long long int i=2;i<n;i++)
{
if(n%i==0)
{
c++;
break;
}
}
if(c==0)
{
return 1;
}
else
{
return 0;
}
}
int main()
{
unsigned long long int a,i,n=num;
while(n-- && n>1)
{
if(isprime(n)==1 && num%n==0)
{
cout<<n;
break;
}
}
return 0;
}
The problem occurring with the code is it is working for 13195 and other small values. But not getting any output for 600851475143. Can anyone explain why it is not working for large value and also tell the changes that should be made in these to get the correct output.
The below code snippets are from c (but should run quite nice with c++ as well):
#include <stdio.h>
#define uIntPrime unsigned long long int
#define uIntPrimeFormat "llu"
uIntPrime findSmallestPrimeFactor(uIntPrime num)
{
uIntPrime limit = num / 2 + 1;
for(uIntPrime i=2; i<limit; i++)
{
if((num % i) == 0)
{
return i;
}
}
return num;
}
uIntPrime findLargestPrimeFactor(uIntPrime num)
{
uIntPrime largestPrimeFactor = 1; // start with the smallest possible value
while (num > 1) {
uIntPrime primeFactor = findSmallestPrimeFactor(num);
if (primeFactor > largestPrimeFactor) largestPrimeFactor = primeFactor;
num = num / primeFactor;
}
return largestPrimeFactor;
}
How can this work?
(first function:) Counting the numbers up from 2 means you are starting with prime factors on the lower end. (Numbers that are non-prime when counting are just not working out as fraction-less divisors and at the same time their prime number factor components were already probed because they are lower.)
(second function:) If a valid factor is found then the factor is pulled out from the number in question. Thus the search for the now smallest prime in the pulled-out number can repeat. (The conditional might probably be superfluous due to lower numbers are found first anyway - but it might resemble a search pattern you are familiar with - like in a minimum/maximum/other-criteria search. I am now leaving it up to you to proof it right or wrong with testing with your own main routine.)
The stop condition is about having the last factor extracted means dividing the value by itself and getting a value of 1 for num.
(There is for sure still much space for speeding this up!)
Im trying to solve this problem on programing.
Here is the question.
The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143 ?
Now I've cooked up a c++ program, which tries to check it by brute force, however, while executing its stuck at 5. Here is the Program
#include <iostream>
#include <math.h>
using namespace std;
const long long no = 600851475143;
long long isprime(long long p)
{
long long reply = -1;
long long i = 2;
while (i < pow(p, 0.5)) {
if (i % p == 0)
reply = i;
}
if (reply == -1){
return 0;
cout<<" yup its prime "<<endl;
}
else
return reply;
}
long long factor(long long x)
{
for (long long i = 2; i < no; i++) {
cout<<"Trying "<<i<<endl;
if ((isprime(i) == 0)&& (no % i == 0)) {
return i;
cout<<"found "<<i<<endl;
break;
}
}
}
int main()
{
long long ans = no;
while (ans != 1) {
cout << factor(ans) << endl;
ans = ans / factor(ans);
}
}
and this is the output
~/Desktop/proj$ ./a.out
Trying 2
Trying 3
Trying 4
Trying 5
I really don't understand why its stuck at number 5, can someone help me out?
EDIT : Thanks b13rg , I realised my mistake . I now have a better algorithm , I have pasted it down for anybody needing it.
#include<iostream>
#include<math.h>
using namespace std;
long long fun (long long x)
{
for(long long i=2; i<sqrt(x);i++){
while (x%i==0){
cout<<i<<endl;
x=x/i;
}
}
}
int main(){
fun(600851475143);
return 0;}
You seem to never change the value of i or p in the while loop in the function isprime. It fails because sqrt(5) is larger than 2, and nothing in the while loop ever changes.
For the problem you're trying to solve:
You could first optimize the checking loop by only trying odd numbers, so first do 2, then 3, then 5 etc. To make it even faster you could hard code in the first few primes, but that might be beyond the scope of this project.
To find the largest prime factor, you would want to first find the smallest prime factor. For example, in the number above, the smallest is 5. The next step would be to divide 13195 by 5 to get 2369. Then start again to find the smallest prime factor of this number, and keep going until the dividing result is prime.
Number|Smallest prime
------|--------------
13169 | 5
2369 | 7
377 |13
29 |Largest prime factor of 13169
I tried a code on a coding website to find the largest prime factor of a number and it's exceeding the time limit for the last test case where probably they are using a large prime number. Can you please help me to reduce the complexity of the following code?
int main()
{
long n;
long int lar, fact;
long int sqroot;
int flag;
cin >> n;
lar=2, fact=2;
sqroot = sqrt(n);
flag = 0;
while(n>1)
{
if((fact > sqroot) && (flag == 0)) //Checking only upto Square Root
{
cout << n << endl;
break;
}
if(n%fact == 0)
{
flag = 1;
lar = fact;
while(n%fact == 0)
n = n/fact;
}
fact++;
}
if(flag == 1) //Don't display if loop fact reached squareroot value
cout << lar << endl;
}
Here I've also taken care of the loop checking till Square Root value. Still, how can I reduce its complexity further?
You can speed things up (if not reduce the complexity) by supplying a hard-coded list of the first N primes to use for the initial values of fact, since using composite values of fact are a waste of time. After that, avoid the obviously composite values of fact (like even numbers).
You can reduce the number of tests by skipping even numbers larger than 2, and stopping sooner if you have found smaller factors. Here is a simpler and faster version:
int main() {
unsigned long long n, lar, fact, sqroot;
cin >> n;
lar = 0;
while (n && n % 2 == 0) {
lar = 2;
n /= 2;
}
fact = 3;
sqroot = sqrt(n);
while (fact <= sqroot) {
if (n % fact == 0) {
lar = fact;
do { n /= fact; } while (n % fact == 0);
sqroot = sqrt(n);
}
fact += 2;
}
if (lar < n)
lar = n;
cout << lar << endl;
return 0;
}
I am not sure how large the input numbers may become, using the larger type unsigned long long for these computations will get you farther than long. Using a precomputed array of primes would help further, but not by a large factor.
The better result I've obtained is using the function below (lpf5()). It's based on the primality() function (below) that uses the formulas 6k+1, 6k-1 to individuate prime numbers. All prime numbers >= 5 may be expressed in one of the forms p=k*6+1 or p=k*6-1 with k>0 (but not all the numbers having such a forms are primes). Developing these formulas we can see a sequence like the following:
k=1 5,7
k=2 11,13
k=3 17,19
k=4 23,25*
k=5 29,31
.
.
.
k=10 59,61
k=11 65*,67
k=12 71,73
...
5,7,11,13,17,19,23,25,29,31,...,59,61,65,67,71,73,...
We observe that the difference between the terms is alternatively 2 and 4. Such a results may be obtained also using simple math. Is obvious that the difference between k*6+1 and k*6-1 is 2. It's simple to note that the difference between k*6+1 and (k+1)*6-1 is 4.
The function primality(x) returns x when x is prime (or 0 - take care) and the first divisor occurs when x is not prime.
I think you may obtain a better result inlining the primality() function inside the lpf5() function.
I've also tried to insert a table with some primes (from 1 to 383 - the primes in the first 128 results of the indicated formulas) inside the primality function, but the speed difference is unappreciable.
Here the code:
#include <stdio.h>
#include <math.h>
typedef long long unsigned int uint64;
uint64 lpf5(uint64 x);
uint64 primality(uint64 x);
uint64 lpf5(uint64 x)
{
uint64 x_=x;
while ( (x_=primality(x))!=x)
x=x/x_;
return x;
}
uint64 primality(uint64 x)
{
uint64 div=7,f=2,q;
if (x<4 || x==5)
return x;
if (!(x&1))
return 2;
if (!(x%3))
return 3;
if (!(x%5))
return 5;
q=sqrt(x);
while(div<=q) {
if (!(x%div)) {
return div;
}
f=6-f;
div+=f;
}
return x;
}
int main(void) {
uint64 x,k;
do {
printf("Input long int: ");
if (scanf("%llu",&x)<1)
break;
printf("Largest Prime Factor: %llu\n",lpf5(x));
} while(x!=0);
return 0;
}
I keep getting the wrong answer of 1179908154. At first I blamed it on my summation variable being type int, rather than long. I gave it long type but I get the same answer. Thoughts?
// Project Euler
// Problem 10
#include <iostream>
#include <cmath>
using namespace std;
void main()
{
int p = 3;
long sum = 2;
bool isPrime;
for (p; p < 2000000; p++)
{
isPrime = true;
for (int i = 2; i <= sqrt(static_cast<double>(p)); i++) // cast into double for sqrt function
{
if (p % i == 0)
{
isPrime = false;
break;
}
}
if (isPrime == true)
{
cout << p << endl; // show each prime
sum += p; // add prime to sum
}
}
cout << sum << endl; // show sum
system("pause");
}
Maybe on your platform the long is not enough to hold the value too. Try a long long instead.
Do not write prime numbers generator by yourself, it's really not easy.
Just use this http://cr.yp.to/primegen.html , it's really good enough for project euler.
When putting the bounds on your for loop, you should check numbers up until sqrt(p) + 1. You can get floating point errors when calculating the square root (it might underestimate it slightly), so it's possible that some potential factors are not checked in the loop.
I'm pretty new to programming and so I"m making this program in C++ that will take a number and find it's prime factors, which works great! Unless it's too big for an int variable. Now then I tried to change all of the int variables to long long variables so it wouldn't matter, but this doesn't seem to fix the problem. The program is as follows:
#include <iostream>
using namespace std;
bool prime (long long recievedvalue) { //starts a function that returns a boolean with parameters being a factor from a number
long long j =1;
long long remainderprime = 0;
bool ended = false;
while (ended == false){ //runs loop while primality is undetermined
if (recievedvalue == 1){ //if the recieved value is a 1 it isn't prime
//not prime
return false;
break; // breaks loop
}
remainderprime=recievedvalue%j; //gives a remainder for testing
if ((remainderprime==0 && j>2) && (j!=recievedvalue || j == 4)){ //shows under which conditions it isn't prime
ended=true;
//not prime
return false;
}
else if (j==1){
j++;
}
else if ( recievedvalue==2 || j==recievedvalue ){ // shows what conditions it is prime
ended = true;
//prime
return true;
}
else {
j++;
}
}
}
long long multiple(long long tbfactor){ //factors and then checks to see if factors are prime, then adds all prime factors together
//parameter is number to be factored
long long sum = 0;
bool primetest = false;
long long remainderfact;
long long i=1;
while (i<=tbfactor){ //checks if a i is a factor of tbfactor
remainderfact=tbfactor%i;
if (remainderfact==0){ //if it is a factor it checks if it is a prime
primetest = prime(i);
}
if (primetest ==true){ //if it is prime it add that to the sum
sum += i;
primetest=false;
}
i++;
}
return sum;
}
int main()
{
long long input;
long long output;
cout << "Enter a number > 0 to find the sum of all it's prime factors: ";
cin >> input;
if (input == 0 || input <= 0){
cout << "The number you entered was too small."<< endl << "Enter number a number to find the sum of all it's prime factors: ";
cin >> input;
}
output = multiple(input);
cout << output << endl << "finished";
return 0;
}
Now then to be sure, the problem does the same thing whether or not it's a int or not. Also like I said I"m new to programming, and C for that matter so I look forward to your easily understandable replies. :)
I'm willing to be that your program IS running. I'm sure that someone is going to pop on and give you the answer in a heartbeat, but I'm hoping that it doesn't happen so that you get to experience the same thing that I did when I ran into the problem YEARS ago.
Do this: start with 1, and work up from there using powers of 2 (1, 2, 4, 8, 16, etc.) and just keep going, doubling the input number each time. When does it "stop running?" Does it get progressively slower?
Please comment back on my post or on your own, or edit your own, or post an answer, whatever it is you're allowed to do with only 56 rep. If the community will allow it (and of course I would like the community to further the lesson), I'd like to gently push you to the answer through a series of back-and-forth steps feedback rather than the typical fashion, since this is an obvious unique learning opportunity.
If you are trying to find if a number is a prime or not, here is a fast solution,
#include <iostream>
using namespace std;
#define ullong unsigned long long
bool prime (ullong x)
{
if(x <= 1)
return false;
ullong s = (ullong)sqrt(x);
for(ullong i=2;i<=s;i++)
if(x%i == 0)
return false;
return true;
}