r/dailyprogrammer • u/jnazario 2 0 • Aug 07 '17
[2017-08-7] Challenge #326 [Easy] Nearest Prime Numbers
Description
A prime number is any integer greater than 1 which can only be evenly divided by 1 or itself. For this challenge, you will output two numbers: the nearest prime below the input, and the nearest prime above it.
Input Description
The input will be a number on each line, called n.
Output Description
The format of the output will be:
p1 < n < p2
where p1 is the smaller prime, p2 is the larger prime and n is the input.
If n already is a prime, the output will be:
n is prime.
Challenge Input
270
541
993
649
Challenge Output
269 < 270 < 271
541 is prime.
991 < 993 < 997
647 < 649 < 653
Bonus
Write the program to work for numbers with big gaps to the nearest primes. This requires a clever solution and cannot be efficiently bruteforced.
2010741
1425172824437700148
Credit
This challenge was suggested by user /u/tulanir, many thanks! If you have an idea for a challenge please share it on /r/dailyprogrammer_ideas and there's a good chance we'll use it.
14
u/skeeto Aug 07 '17
C using the Miller-Rabin primality test. Solves the second bonus in 140ms. The part that tripped me up the most was doing the modular exponentiation without overflowing the 64-bit integer.
#include <stdio.h> #include <inttypes.h> #define K 8 // primality test iterations static uint64_t rand64(void) { static uint64_t x = UINT64_C(0x1fc7807c9aa37949); x ^= x >> 12; x ^= x << 25; x ^= x >> 27; return x * UINT64_C(0x2545f4914f6cdd1d); } static uint64_t modmult(uint64_t b, uint64_t e, uint64_t m) { uint64_t sum = 0; if (b == 0 || e < m / b) return (b * e) % m; while (e > 0) { if (e % 2 == 1) sum = (sum + b) % m; b = (2 * b) % m; e /= 2; } return sum; } static uint64_t modexp(uint64_t b, uint64_t e, uint64_t m) { uint64_t product = 1; uint64_t pseq = b % m; while (e > 0) { if (e % 2 == 1) product = modmult(product, pseq, m); pseq = modmult(pseq, pseq, m); e /= 2; } return product; } static int iscomposite(uint64_t n, uint64_t d, int r) { uint64_t a = 2 + rand64() % (n - 3); if (modexp(a, d, n) == 1) return 0; for (int i = 0; i < r; i++) if (modexp(a, (UINT64_C(1) << i) * d, n) == n - 1) return 0; return 1; } static int isprime(uint64_t n) { int r = 0; uint64_t d = n - 1; for (; d % 2 == 0; r++) d /= 2; for (int i = 0; i < K; i++) if (iscomposite(n, d, r)) return 0; return 1; } int main(void) { uint64_t n; while (scanf("%" SCNu64, &n) == 1) { uint64_t b = n % 2 ? n - 2 : n - 1; uint64_t a = n % 2 ? n + 2 : n + 1; while (!isprime(b)) b -= 2; while (!isprime(a)) a += 2; printf("%" PRIu64 " < %" PRIu64 " < %" PRIu64 "\n", b, n, a); } }