Largest Prime Removing Digits From Left-Hand End
Recently on Fermat's Library in Twitter, the following curiosity was posted:
What if we tried the same but from the left-hand end? For example, "113" would be a candidate because:
113 is prime
13 is prime
3 is prime
What's the largest of such a value? Is the a max one? Well let's leave the digit "zero" aside for now since we're looking to have unique numbers at each step of the sequence.
There is actually a Max value for that! Here it is:
Code to find it is down below - it uses BigInteger and Miller-Rabin for quick primality test. Also, DFS with pruning. Equally interesting as the twitter post. Cheers, ACC.
What if we tried the same but from the left-hand end? For example, "113" would be a candidate because:
113 is prime
13 is prime
3 is prime
What's the largest of such a value? Is the a max one? Well let's leave the digit "zero" aside for now since we're looking to have unique numbers at each step of the sequence.
There is actually a Max value for that! Here it is:
357686312646216567629137
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Numerics; namespace FermatLibraryProblem { class Program { static void Main(string[] args) { BigInteger max = 0; Process(0, 1, ref max); Console.WriteLine(); Console.WriteLine("Solution: {0}", max); } public static void Process(BigInteger number, BigInteger multiplier, ref BigInteger max) { if (number != 0 && !IsPrimeMillerRabin(number)) return; if (number > max) { max = number; Console.WriteLine("New Max: {0}", max); } for (int i = 1; i < 10; i++) { Process(multiplier * i + number, 10 * multiplier, ref max); } } public static bool IsPrimeMillerRabin(BigInteger n) { //It does not work well for smaller numbers, hence this check int SMALL_NUMBER = 1000; if (n <= SMALL_NUMBER) { return IsPrime(n); } int MAX_WITNESS = 500; for (long i = 2; i <= MAX_WITNESS; i++) { if (IsPrime(i) && Witness(i, n) == 1) { return false; } } return true; } public static BigInteger SqRtN(BigInteger N) { /*++ * Using Newton Raphson method we calculate the * square root (N/g + g)/2 */ BigInteger rootN = N; int count = 0; int bitLength = 1; while (rootN / 2 != 0) { rootN /= 2; bitLength++; } bitLength = (bitLength + 1) / 2; rootN = N >> bitLength; BigInteger lastRoot = BigInteger.Zero; do { if (lastRoot > rootN) { if (count++ > 1000) // Work around for the bug where it gets into an infinite loop { return rootN; } } lastRoot = rootN; rootN = (BigInteger.Divide(N, rootN) + rootN) >> 1; } while (!((rootN ^ lastRoot).ToString() == "0")); return rootN; } public static bool IsPrime(BigInteger n) { if (n <= 1) { return false; } if (n == 2) { return true; } if (n % 2 == 0) { return false; } for (int i = 3; i <= SqRtN(n) + 1; i += 2) { if (n % i == 0) { return false; } } return true; } private static int Witness(long a, BigInteger n) { BigInteger t, u; BigInteger prev, curr = 0; BigInteger i; BigInteger lln = n; u = n / 2; t = 1; while (u % 2 == 0) { u /= 2; t++; } prev = BigInteger.ModPow(a, u, n); for (i = 1; i <= t; i++) { curr = BigInteger.ModPow(prev, 2, lln); if ((curr == 1) && (prev != 1) && (prev != lln - 1)) return 1; prev = curr; } if (curr != 1) return 1; return 0; } } }
Comments
Post a Comment