Project Euler #27 [closed] - c++

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I'm challenging myself in Project Euler but currently stuck on problem 27, in which the problem states:
Euler published the remarkable quadratic formula:
n² + n + 41
It turns out that the formula will produce 40 primes for the consecutive values n = 0 to 39. However, when n = 40, 402 + 40 + 41 = 40(40 + 1) + 41 is divisible by 41, and certainly when n = 41, 41² + 41 + 41 is clearly divisible by 41.
Using computers, the incredible formula n² 79n + 1601 was discovered, which produces 80 primes for the consecutive values n = 0 to 79. The product of the coefficients, 79 and 1601, is 126479.
Considering quadratics of the form:
n² + an + b, where |a| 1000 and |b| 1000
where |n| is the modulus/absolute value of n
e.g. |11| = 11 and |4| = 4
Find the product of the coefficients, a and b, for the quadratic expression that produces > the maximum number of primes for consecutive values of n, starting with n = 0.
I wrote the following code, which gives me the answers pretty quick but it is wrong (it spits me (-951) * (-705) = 670455). Can somebody check my code to see where is/are my mistake(s)?
#include <iostream>
#include <vector>
#include <cmath>
#include <time.h>
using namespace std;
bool isprime(unsigned int n, int d[339]);
int main()
{
clock_t t = clock();
int c[] = {13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,1063,1069,1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,1163,1171,1181,1187,1193,1201,1213,1217,1223,1229,1231,1237,1249,1259,1277,1279,1283,1289,1291,1297,1301,1303,1307,1319,1321,1327,1361,1367,1373,1381,1399,1409,1423,1427,1429,1433,1439,1447,1451,1453,1459,1471,1481,1483,1487,1489,1493,1499,1511,1523,1531,1543,1549,1553,1559,1567,1571,1579,1583,1597,1601,1607,1609,1613,1619,1621,1627,1637,1657,1663,1667,1669,1693,1697,1699,1709,1721,1723,1733,1741,1747,1753,1759,1777,1783,1787,1789,1801,1811,1823,1831,1847,1861,1867,1871,1873,1877,1879,1889,1901,1907,1913,1931,1933,1949,1951,1973,1979,1987,1993,1997,1999,2003,2011,2017,2027,2029,2039,2053,2063,2069,2081,2083,2087,2089,2099,2111,2113,2129,2131,2137,2141,2143,2153,2161,2179,2203,2207,2213,2221,2237,2239,2243,2251,2267,2269,2273,2281,2287,2293,2297,2309,2311};
int result[4];
result[3] = 0;
for (int a = -999; a < 1000; a+=2)
{
for (int b = -999; b < 1000; b+=2)
{
bool prime;
int n = 0, count = 0;
do
{
prime = isprime(n*n + a*n + b, c);
n++;
count++;
} while (prime);
count--;
n--;
if (count > result[3])
{
result[0] = a;
result[1] = b;
result[2] = n;
result[3] = count;
}
}
if ((a+1) % 100 == 0)
cout << a+1 << endl;
}
cout << result[0] << endl << result[1] << endl << result[2] << endl << result[3] << endl << clock()-t;
cin >> result[0];
return 0;
}
bool isprime(unsigned int n, int d[339])
{
int j = 0, l;
if ((n == 2) || (n == 3) || (n == 5) || (n == 7) || (n == 11))
return 1;
if ((n % 2 == 0) || (n % 3 == 0) || (n % 5 == 0) || (n % 7 == 0) || (n % 11 == 0))
return 0;
while (j <= int (sqrt(n) / 2310))
{
for (int k = 0; k < 339; k++)
{
l = 2310 * j + d[k];
if (n % l == 0)
return 0;
}
j++;
}
return 1;
}

There's a bug in isprime function.
In your function, you check all 2310 * j + d[k] where j < int (sqrt(n) / 2310)) to ensure the target n is a prime number. However, an additional condition that l < sqrt(n) is also required, or you will over-exclude some prime numbers.
For example, when a = 1, b = 41 and n = 0, your function will check whether 41 is a prime number starting from j = 0. So whether 41 can be divisible by 2310 * 0 + d[7] = 41 is also verified, which leads to a false return.
This version should be correct:
bool isprime(unsigned int n, int d[])
{
int j = 0, l;
if ((n == 2) || (n == 3) || (n == 5) || (n == 7) || (n == 11))
return 1;
if ((n % 2 == 0) || (n % 3 == 0) || (n % 5 == 0) || (n % 7 == 0) || (n % 11 == 0))
return 0;
double root = sqrt(n);
while (j <= int (root / 2310))
{
for (int k = 0; k < 339; k++)
{
l = 2310 * j + d[k];
if (l < root && n % l == 0)
return 0;
}
j++;
}
return 1;
}

Related

Largest Prime Number with big numbers

I did a Project Euler question - here
I am at the end of my wits. I am getting wrong solution.
I am perplexed as to "why" particularly this code is not working.
Relevant - this
This was my generated answer.
long long x; // The max prime factor
long long n; // The number to be factored
while (n % 2 == 0)
{
n /= 2;
}
x = 2;
while (n % 3 == 0)
{
n /= 3;
}
x = 3;
for (int i = 5; i <= sqrt(n); i += 2)
{
while (n % i == 0)
{
n /= i;
}
x = i;
}
std::cout << x;
n = 600851475143 answer = 6857>! I am getting x = 1471
At least this for loop
for (int i = 5; i <= sqrt(n); i += 2)
{
while (n % i == 0)
{
n /= i;
}
x = i;
}
is wrong, The variable x gets the value of the last i that is less than or equal to sqrt( n ).
Consider for example n equal to 22. After dividing it by 2 you will get n equal to 11.
After this code snippet
while (n % 3 == 0)
{
n /= 3;
}
x = 3;
x will be equal to 3 and the for loop will be skipped due to its condition that evaluates to false.
The code can look for example the following way
long long int n = 600851475143;
long long int prime_factor = 0;
if (n % 2 == 0)
{
prime_factor = 2;
while (n % 2 == 0 ) n /= 2;
}
for (long long int i = 3; i <= n / i; i += 2)
{
if (n % i == 0)
{
prime_factor = i;
while (n % i == 0) n /= i;
}
}
if (n != 1) prime_factor = n;
std::cout << "prime factor = " << prime_factor << '\n';
Also you should use the unsigned type unsigned long long int instead of the signed type long long int. Otherwise you will need to write code that will take into account the sign of the source number.
You could write a separate function as shown in the demonstration program below
#include <iostream>
unsigned long long max_prime_factor( unsigned long long int n )
{
unsigned long long int prime_factor = 0;
if (not ( n < 2 ))
{
if (n % 2 == 0)
{
prime_factor = 2;
while (n % 2 == 0) n /= 2;
}
for (unsigned long long int i = 3; i <= n / i; i += 2)
{
if (n % i == 0)
{
prime_factor = i;
while (n % i == 0) n /= i;
}
}
}
return n < 2 ? prime_factor : n;
}
int main()
{
for (unsigned int i = 0; i < 20; i++)
{
std::cout << i << " -> " << max_prime_factor( i ) << '\n';
}
}
The program output is
0 -> 0
1 -> 0
2 -> 2
3 -> 3
4 -> 2
5 -> 5
6 -> 3
7 -> 7
8 -> 2
9 -> 3
10 -> 5
11 -> 11
12 -> 3
13 -> 13
14 -> 7
15 -> 5
16 -> 2
17 -> 17
18 -> 3
19 -> 19
int main() {
long long x = 0; // The max prime factor
long long n = 600851475143; // The number to be factored
long long a = sqrt(n);
while (n % 2 == 0) {
n /= 2;
}
x = 2;
while (n % 3 == 0) {
n /= 3;
}
x = 3;
for (int i = 5; i <= a; i += 2) {
while (n % i == 0) {
n /= i;
x = i;
}
}
std::cout << x << std::endl;
}
Here it works, the sqrt(n) stoped the for loop too soon so i put it in a long long,
and the x = i; was in the wrong place

Is there an efficient way to generate number of factors of N less than X?

I am a beginner in the field of programming. I just want to find the number of factors / divisors of a positive integer N less than X. (X itself is a factor of N). I have a naive approach which doesn't work good for queries on N,X.
Here is my approach
int Divisors(int n, int x) {
int ans = 0;
if (x < sqrt(n)) {
for (int i = 1; i < x; i++) {
if (n % i == 0) {
ans++;
}
}
} else
for (int i = 1; i <= sqrt(n); i++) {
if (n % i == 0) {
if (n / i == i && i < x)
ans++;
else {
if (i < x)
ans++;
if (n / i < x)
ans++;
}
}
}
return ans;
}
Is there some efficient way to do this? Kindly help me out!
The actual problem I'm trying to solve :
Given some M and N I need to iterate through all positive integers less than or equal to N(1 <= i <= N) and I need to count how many numbers less than the current number (i) exists such that they divide the last multiple of i that is less than or equal to M (i.e., M - M % i) and finally find the sum of all counts.
Example
Given N = 5 and M = 10
Ans : 6
Explanation :
i = 1 count = 0
i = 2 count = 1 (10 % 1 = 0)
i = 3 count = 1 (9 % 1 = 0)
i = 4 count = 2 (8 % 1 = 0, 8 % 2 = 0)
i = 5 count = 2 (10 % 1 = 0, 10 % 2 = 0)
Therefore sum of all counts = 6
The wording of the question is a bit confusing.
I'm assuming you are finding the size of the set of all factors/divisors, D, of a number n that are less than a number x, where x is a factor of n.
An easier way of doing this is to iterate from all numbers 1 through x, exclusive of x, and use the modulo operator %.
Code:
int NumOfDiv(int x, int n){
int count = 0;
for(int i=1; i<x; i++){
if(n % i == 0) //This indicates that i divides n, having a remainder of 0,
look up % as it is very useful with number theory
count++;
}
return count;
}
Example:
int TestNum = NumOfDiv(4,12)
TestNum would have the value of 3

Miller-Rabin primality test issue in C++

I've been trying to implement the algorithm from wikipedia and while it's never outputting composite numbers as primes, it's outputting like 75% of primes as composites.
Up to 1000 it gives me this output for primes:
3, 5, 7, 11, 13, 17, 41, 97, 193, 257, 641, 769
As far as I know, my implementation is EXACTLY the same as the pseudo-code algorithm. I've debugged it line by line and it produced all of the expected variable values (I was following along with my calculator). Here's my function:
bool primeTest(int n)
{
int s = 0;
int d = n - 1;
while (d % 2 == 0)
{
d /= 2;
s++;
}
// this is the LOOP from the pseudo-algorithm
for (int i = 0; i < 10; i++)
{
int range = n - 4;
int a = rand() % range + 2;
//int a = rand() % (n/2 - 2) + 2;
bool skip = false;
long x = long(pow(a, d)) % n;
if (x == 1 || x == n - 1)
continue;
for (int r = 1; r < s; r++)
{
x = long(pow(x, 2)) % n;
if (x == 1)
{
// is not prime
return false;
}
else if (x == n - 1)
{
skip = true;
break;
}
}
if (!skip)
{
// is not prime
return false;
}
}
// is prime
return true;
}
Any help would be appreciated D:
EDIT: Here's the entire program, edited as you guys suggested - and now the output is even more broken:
bool primeTest(int n);
int main()
{
int count = 1; // number of found primes, 2 being the first of course
int maxCount = 10001;
long n = 3;
long maxN = 1000;
long prime = 0;
while (count < maxCount && n <= maxN)
{
if (primeTest(n))
{
prime = n;
cout << prime << endl;
count++;
}
n += 2;
}
//cout << prime;
return 0;
}
bool primeTest(int n)
{
int s = 0;
int d = n - 1;
while (d % 2 == 0)
{
d /= 2;
s++;
}
for (int i = 0; i < 10; i++)
{
int range = n - 4;
int a = rand() % range + 2;
//int a = rand() % (n/2 - 2) + 2;
bool skip = false;
//long x = long(pow(a, d)) % n;
long x = a;
for (int z = 1; z < d; z++)
{
x *= x;
}
x = x % n;
if (x == 1 || x == n - 1)
continue;
for (int r = 1; r < s; r++)
{
//x = long(pow(x, 2)) % n;
x = (x * x) % n;
if (x == 1)
{
return false;
}
else if (x == n - 1)
{
skip = true;
break;
}
}
if (!skip)
{
return false;
}
}
return true;
}
Now the output of primes, from 3 to 1000 (as before), is:
3, 5, 17, 257
I see now that x gets too big and it just turns into a garbage value, but I wasn't seeing that until I removed the "% n" part.
The likely source of error is the two calls to the pow function. The intermediate results will be huge (especially for the first call) and will probably overflow, causing the error. You should look at the modular exponentiation topic at Wikipedia.
Source of problem is probably here:
x = long(pow(x, 2)) % n;
pow from C standard library works on floating point numbers, so using it is a very bad idea if you just want to compute powers modulo n. Solution is really simple, just square the number by hand:
x = (x * x) % n

Smallest number that is evenly divisible by all of the numbers from 1 to 20?

I did this problem [Project Euler problem 5], but very bad manner of programming, see the code in c++,
#include<iostream>
using namespace std;
// to find lowest divisble number till 20
int main()
{
int num = 20, flag = 0;
while(flag == 0)
{
if ((num%2) == 0 && (num%3) == 0 && (num%4) == 0 && (num%5) == 0 && (num%6) == 0
&& (num%7) == 0 && (num%8) == 0 && (num%9) == 0 && (num%10) == 0 && (num%11) == 0 && (num%12) ==0
&& (num%13) == 0 && (num%14) == 0 && (num%15) == 0 && (num%16) == 0 && (num%17) == 0 && (num%18)==0
&& (num%19) == 0 && (num%20) == 0)
{
flag = 1;
cout<< " lowest divisible number upto 20 is "<< num<<endl;
}
num++;
}
}
i was solving this in c++ and stuck in a loop, how would one solve this step......
consider num = 20 and divide it by numbers from 1 to 20
check whether all remainders are zero,
if yes, quit and show output num
or else num++
i din't know how to use control structures, so did this step
if ((num%2) == 0 && (num%3) == 0 && (num%4) == 0 && (num%5) == 0 && (num%6) == 0
&& (num%7) == 0 && (num%8) == 0 && (num%9) == 0 && (num%10) == 0 && (num%11) == 0 && (num%12) ==0
&& (num%13) == 0 && (num%14) == 0 && (num%15) == 0 && (num%16) == 0 && (num%17) == 0 && (num%18)==0
&& (num%19) == 0 && (num%20) == 0) `
how to code this in proper manner?
answer for this problem is:
abhilash#abhilash:~$ ./a.out
lowest divisible number upto 20 is 232792560
The smallest number that is divisible by two numbers is the LCM of those two numbers. Actually, the smallest number divisible by a set of N numbers x1..xN is the LCM of those numbers. It is easy to compute the LCM of two numbers (see the wikipedia article), and you can extend to N numbers by exploiting the fact that
LCM(x0,x1,x2) = LCM(x0,LCM(x1,x2))
Note: Beware of overflows.
Code (in Python):
def gcd(a,b):
return gcd(b,a%b) if b else a
def lcm(a,b):
return a/gcd(a,b)*b
print reduce(lcm,range(2,21))
Factor all the integers from 1 to 20 into their prime factorizations. For example, factor 18 as 18 = 3^2 * 2. Now, for each prime number p that appears in the prime factorization of some integer in the range 1 to 20, find the maximum exponent that it has among all those prime factorizations. For example, the prime 3 will have exponent 2 because it appears in the factorization of 18 as 3^2 and if it appeared in any prime factorization with an exponent of 3 (i.e., 3^3), that number would have to be at least as large as 3^3 = 27 which it outside of the range 1 to 20. Now collect all of these primes with their corresponding exponent and you have the answer.
So, as example, let's find the smallest number evenly divisible by all the numbers from 1 to 4.
2 = 2^1
3 = 3^1
4 = 2^2
The primes that appear are 2 and 3. We note that the maximum exponent of 2 is 2 and the maximum exponent of 3 is 1. Thus, the smallest number that is evenly divisible by all the numbers from 1 to 4 is 2^2 * 3 = 12.
Here's a relatively straightforward implementation.
#include <iostream>
#include <vector>
std::vector<int> GetPrimes(int);
std::vector<int> Factor(int, const std::vector<int> &);
int main() {
int n;
std::cout << "Enter an integer: ";
std::cin >> n;
std::vector<int> primes = GetPrimes(n);
std::vector<int> exponents(primes.size(), 0);
for(int i = 2; i <= n; i++) {
std::vector<int> factors = Factor(i, primes);
for(int i = 0; i < exponents.size(); i++) {
if(factors[i] > exponents[i]) exponents[i] = factors[i];
}
}
int p = 1;
for(int i = 0; i < primes.size(); i++) {
for(int j = 0; j < exponents[i]; j++) {
p *= primes[i];
}
}
std::cout << "Answer: " << p << std::endl;
}
std::vector<int> GetPrimes(int max) {
bool *isPrime = new bool[max + 1];
for(int i = 0; i <= max; i++) {
isPrime[i] = true;
}
isPrime[0] = isPrime[1] = false;
int p = 2;
while(p <= max) {
if(isPrime[p]) {
for(int j = 2; p * j <= max; j++) {
isPrime[p * j] = false;
}
}
p++;
}
std::vector<int> primes;
for(int i = 0; i <= max; i++) {
if(isPrime[i]) primes.push_back(i);
}
delete []isPrime;
return primes;
}
std::vector<int> Factor(int n, const std::vector<int> &primes) {
std::vector<int> exponents(primes.size(), 0);
while(n > 1) {
for(int i = 0; i < primes.size(); i++) {
if(n % primes[i] == 0) {
exponents[i]++;
n /= primes[i];
break;
}
}
}
return exponents;
}
Sample output:
Enter an integer: 20
Answer: 232792560
There is a faster way to answer the problem, using number theory. Other answers contain indications how to do this. This answer is only about a better way to write the if condition in your original code.
If you only want to replace the long condition, you can express it more nicely in a for loop:
if ((num%2) == 0 && (num%3) == 0 && (num%4) == 0 && (num%5) == 0 && (num%6) == 0
&& (num%7) == 0 && (num%8) == 0 && (num%9) == 0 && (num%10) == 0 && (num%11) == 0 && (num%12) ==0
&& (num%13) == 0 && (num%14) == 0 && (num%15) == 0 && (num%16) == 0 && (num%17) == 0 && (num%18)==0
&& (num%19) == 0 && (num%20) == 0)
{ ... }
becomes:
{
int divisor;
for (divisor=2; divisor<=20; divisor++)
if (num%divisor != 0)
break;
if (divisor != 21)
{ ...}
}
The style is not great but I think this is what you were looking for.
See http://en.wikipedia.org/wiki/Greatest_common_divisor
Given two numbers a and b you can compute gcd(a, b) and the smallest number divisible by both is a * b / gcd(a, b). The obvious thing then to do is to keep a sort of running total of this and add in the numbers you care about one by one: you have an answer so far A and you add in the next number X_i to consider by putting
A' = A * X_i / (gcd(A, X_i))
You can see that this actually works by considering what you get if you factorise everything and write them out as products of primes. This should pretty much allow you to work out the answer by hand.
Hint:
instead of incrementing num by 1 at each step you could increment it by 20 (will work alot faster). Of course there may be other improvements too, ill think about it later if i have time. Hope i helped you a little bit.
The number in question is the least common multiple of the numbers 1 through 20.
Because I'm lazy, let ** represent exponentiation. Let kapow(x,y) represent the integer part of the log to the base x of y. (For example, kapow(2,8) = 3, kapow(2,9) = 3, kapow(3,9) = 2.
The primes less than or equal to 20 are 2, 3, 5, 7, 11, 13, and 17. The LCM is,
Because sqrt(20) < 5, we know that kapow(i,20) for i >= 5 is 1. By inspection, the LCM is
LCM = 2kapow(2,20) * 3kapow(3,20)
* 5 * 7 * 11 * 13 * 17 * 19
which is
LCM = 24 * 32 * 5 * 7 * 11 * 13 *
17 * 19
or
LCM = 16 * 9 * 5 * 7 * 11 * 13 * 17 *
19
Here is a C# version of #MAK's answer, there might be List reduce method in C#, I found something online but no quick examples so I just used a for loop in place of Python's reduce:
static void Main(string[] args)
{
const int min = 2;
const int max = 20;
var accum = min;
for (var i = min; i <= max; i++)
{
accum = lcm(accum, i);
}
Console.WriteLine(accum);
Console.ReadLine();
}
private static int gcd(int a, int b)
{
return b == 0 ? a : gcd(b, a % b);
}
private static int lcm(int a, int b)
{
return a/gcd(a, b)*b;
}
Code in JavaScript:
var i=1,j=1;
for (i = 1; ; i++) {
for (j = 1; j <= 20; j++) {
if (i % j != 0) {
break;
}
if (i % j == 0 && j == 20) {
console.log('printval' + i)
break;
}
}
}
This can help you
http://www.mathwarehouse.com/arithmetic/numbers/prime-number/prime-factorization.php?number=232792560
The prime factorization of 232,792,560
2^4 • 3^2 • 5 • 7 • 11 • 13 • 17 • 19
Ruby Cheat:
require 'rational'
def lcmFinder(a = 1, b=2)
if b <=20
lcm = a.lcm b
lcmFinder(lcm, b+1)
end
puts a
end
lcmFinder()
this is written in c
#include<stdio.h>
#include<conio.h>
void main()
{
int a,b,flag=0;
for(a=1; ; a++)
{
for(b=1; b<=20; b++)
{
if (a%b==0)
{
flag++;
}
}
if (flag==20)
{
printf("The least num divisible by 1 to 20 is = %d",a);
break;
}
flag=0;
}
getch();
}
#include<vector>
using std::vector;
unsigned int Pow(unsigned int base, unsigned int index);
unsigned int minDiv(unsigned int n)
{
vector<unsigned int> index(n,0);
for(unsigned int i = 2; i <= n; ++i)
{
unsigned int test = i;
for(unsigned int j = 2; j <= i; ++j)
{
unsigned int tempNum = 0;
while( test%j == 0)
{
test /= j;
tempNum++;
}
if(index[j-1] < tempNum)
index[j-1] = tempNum;
}
}
unsigned int res =1;
for(unsigned int i = 2; i <= n; ++i)
{
res *= Pow( i, index[i-1]);
}
return res;
}
unsigned int Pow(unsigned int base, unsigned int index)
{
if(base == 0)
return 0;
if(index == 0)
return 1;
unsigned int res = 1;
while(index)
{
res *= base;
index--;
}
return res;
}
The vector is used for storing the factors of the smallest number.
This is why you would benefit from writing a function like this:
long long getSmallestDivNum(long long n)
{
long long ans = 1;
if( n == 0)
{
return 0;
}
for (long long i = 1; i <= n; i++)
ans = (ans * i)/(__gcd(ans, i));
return ans;
}
Given the maximum n, you want to return the smallest number that is dividable by 1 through 20.
Let's look at the set of 1 to 20. First off, it contains a number of prime numbers, namely:
2
3
5
7
11
13
17
19
So, because it's has to be dividable by 19, you can only check multiples of 19, because 19 is a prime number. After that, you check if it can be divided by the one below that, etc. If the number can be divided by all the prime numbers successfully, it can be divided by the numbers 1 through 20.
float primenumbers[] = { 19, 17, 13, 11, 7, 5, 3, 2; };
float num = 20;
while (1)
{
bool dividable = true;
for (int i = 0; i < 8; i++)
{
if (num % primenumbers[i] != 0)
{
dividable = false;
break;
}
}
if (dividable) { break; }
num += 1;
}
std::cout << "The smallest number dividable by 1 through 20 is " << num << std::endl;

C or C++: Libraries for factoring integers? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 11 months ago.
The community reviewed whether to reopen this question 8 months ago and left it closed:
Original close reason(s) were not resolved
Improve this question
It seems that there are several really fast prime factorization algorithms around (one that looks ideal is quadratic sieving). However, rather than make my own (likely poor) implementation I would like to use a ready-made library for simplicity.
I need to be able to factor integers of up to 15 digits efficiently. Because of that, I'm not looking for the algorithm that necessarily scales asymptotically best since we can assume the numbers being factored are less than 1015.
I've already had a look at some of the implementations listed on Wikipedia's Quadratic Sieve page. However, some of the implementations don't seem well-maintained; some don't have documentation; and so on! I checked if a few well-known libraries, such as Boost, had factorization methods but they don't seem to.
Can anyone recommend a library that fits the above criteria?
Check out MSIEVE library for factoring large integers by Jason Papadopoulos.
Msieve is the result of my efforts to understand and optimize how
integers are factored using the most powerful modern algorithms.
This documentation corresponds to version 1.46 of the Msieve library.
Do not expect to become a factoring expert just by reading it. I've
included a relatively complete list of references that you can and
should look up if you want to treat the code as more than a black box
to solve your factoring problems.
To factor integers in C you can try to use a probabilistic approach :
The headers of my proposition :
#include <stdlib.h>
#include <sys/time.h>
typedef unsigned long long int positive_number; // __uint128_t
static inline positive_number multiplication_modulo(positive_number lhs, positive_number rhs, positive_number mod);
static int is_prime(positive_number n, int k); // prime checker
positive_number factor_worker(positive_number n);
positive_number factor(positive_number n, int timeout);
The factorization process manager, because there is a timeout:
double microtime() {
struct timeval time; gettimeofday(&time, 0);
return (double) time.tv_sec + (double) time.tv_usec / 1e6;
}
// This is the master function you can call, expecting a number and a timeout(s)
positive_number factor(positive_number n, int timeout) {
if (n < 4) return n;
if (n != (n | 1)) return 2;
double begin = microtime();
int steps = 8; // primality check iterations
positive_number a, b;
for (a = n >> 1, b = (a + n / a) >> 1; b < a; a = b, b = (a + n / a) >> 1, ++steps);
if (b * b == n) return b ; // we just computed b = sqrt(n)
if (is_prime(n, steps)) return n;
do { positive_number res = factor_worker(n);
if (res != n) return res;
if (++steps % 96 == 0 && is_prime(n, 32)) return n ; // adjust it
} while (microtime() - begin < timeout);
return n;
}
The multiplier helper because computations are done modulo N :
static inline positive_number multiplication_modulo(positive_number lhs, positive_number rhs, positive_number mod) {
positive_number res = 0; // we avoid overflow in modular multiplication
for (lhs %= mod, rhs%= mod; rhs; (rhs & 1) ? (res = (res + lhs) % mod) : 0, lhs = (lhs << 1) % mod, rhs >>= 1);
return res; // <= (lhs * rhs) % mod
}
The prime checker helper, of course :
static int is_prime(positive_number n, int k) {
positive_number a = 0, b, c, d, e, f, g; int h, i;
if ((n == 1) == (n & 1)) return n == 2;
if (n < 51529) // fast constexpr check for small primes (removable)
return (n & 1) & ((n < 6) * 42 + 0x208A2882) >> n % 30 && (n < 49 || (n % 7 && n % 11 && n % 13 && n % 17 && n % 19 && n % 23 && n % 29 && n % 31 && n % 37 && (n < 1369 || (n % 41 && n % 43 && n % 47 && n % 53 && n % 59 && n % 61 && n % 67 && n % 71 && n % 73 && ( n < 6241 || (n % 79 && n % 83 && n % 89 && n % 97 && n % 101 && n % 103 && n % 107 && n % 109 && n % 113 && ( n < 16129 || (n % 127 && n % 131 && n % 137 && n % 139 && n % 149 && n % 151 && n % 157 && n % 163 && n % 167 && ( n < 29929 || (n % 173 && n % 179 && n % 181 && n % 191 && n % 193 && n % 197 && n % 199 && n % 211 && n % 223))))))))));
for (b = c = n - 1, h = 0; !(b & 1); b >>= 1, ++h);
for (; k--;) {
for (g = 0; g < sizeof(positive_number); ((char*)&a)[g++] = rand()); // random number
do for (d = e = 1 + a % c, f = n; (d %= f) && (f %= d););
while (d > 1 && f > 1);
for (d = f = 1; f <= b; f <<= 1);
for (; f >>= 1; d = multiplication_modulo(d, d, n), f & b && (d = multiplication_modulo(e, d, n)));
if (d == 1) continue;
for (i = h; i-- && d != c; d = multiplication_modulo(d, d, n));
if (d != c) return 0;
}
return 1;
}
The factorization worker, a single call does not guarantee a success, it's a probabilistic try :
positive_number factor_worker(positive_number n) {
size_t a; positive_number b = 0, c, d, e, f;
for (a = 0; a < sizeof(positive_number); ((char*)&b)[a++] = rand()); // pick random polynomial
c = b %= n;
do {
b = multiplication_modulo(b, b, n); if(++b == n) b = 0;
c = multiplication_modulo(c, c, n); if(++c == n) c = 0;
c = multiplication_modulo(c, c, n); if(++c == n) c = 0;
for (d = n, e = b > c ? b - c : c - b; e; f = e, e = multiplication_modulo(d / f, f, n), e = (d - e) % n, d = f);
// handle your precise timeout in the for loop body
} while (d == 1);
return d;
}
Example of usage :
#include <stdio.h>
positive_number exec(positive_number n) {
positive_number res = factor(n, 2); // 2 seconds
if (res == n) return res + printf("%llu * ", n) * fflush(stdout) ;
return exec(res) * exec(n / res);
}
int main() {
positive_number n = 0, mask = -1, res;
for (int i = 0; i < 1000;) {
int bits = 4 + rand() % 60; // adjust the modulo for tests
for (size_t k = 0; k < sizeof(positive_number); ((char*)&n)[k++] = rand());
// slice a random number with the "bits" variable
n &= mask >> (8 * sizeof (positive_number) - bits); n += 4;
printf("%5d. (%2d bits) %llu = ", ++i, bits, n);
res = exec(n);
if (res != n) return 1;
printf("1\n");
}
}
You can put it into a primes.c file then compile + execute :
gcc -O3 -std=c99 -Wall -pedantic primes.c ; ./a.out ;
Also, 128-bit integers GCC extension extension may be available.
Example output :
358205873110913227 = 380003149 * 942639223 took 0.01s
195482582293315223 = 242470939 * 806210357 took 0.0021s
107179818338278057 = 139812461 * 766597037 took 0.0023s
44636597321924407 = 182540669 * 244529603 took 0s
747503348409771887 = 865588487 * 863578201 took 0.016s
// 128-bit extension available output :
170141183460469231731687303715506697937 =
13602473 * 230287853 * 54315095311400476747373 took 0.646652s
Info : This C99 100 lines probabilistic factorization software proposition is based on a Miller–Rabin primality test followed or not by a Pollard's rho algo. Like you, i initially aimed to factorize just a little long long int. By my tests it's working fast enough to me, even for some larger. Thank you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
How about GMP-ECM (Elliptic Curve Method for Integer Factorization)?
If the link to the official project page at Inria is unavailable, you can check a recent version on the web archive.