Task: Find largest left truncatable prime in a given base


C++: #include <gmpxx.h>

#include <algorithm>
#include <cassert>
#include <functional>
#include <iostream>
#include <vector>

using big_int = mpz_class;

const unsigned int small_primes[] = {2,  3,  5,  7,  11, 13, 17, 19, 23,
                                     29, 31, 37, 41, 43, 47, 53, 59, 61,
                                     67, 71, 73, 79, 83, 89, 97};

bool is_probably_prime(const big_int& n, int reps) {
    return mpz_probab_prime_p(n.get_mpz_t(), reps) != 0;
}

big_int largest_left_truncatable_prime(unsigned int base) {
    std::vector<big_int> powers = {1};
    std::vector<big_int> value = {0};
    big_int result = 0;

    std::function<void(unsigned int)> add_digit = [&](unsigned int i) {
        if (i == value.size()) {
            value.resize(i + 1);
            powers.push_back(base * powers.back());
        }
        for (unsigned int d = 1; d < base; ++d) {
            value[i] = value[i - 1] + powers[i] * d;
            if (!is_probably_prime(value[i], 1))
                continue;
            if (value[i] > result) {
                if (!is_probably_prime(value[i], 50))
                    continue;
                result = value[i];
            }
            add_digit(i + 1);
        }
    };

    for (unsigned int i = 0; small_primes[i] < base; ++i) {
        value[0] = small_primes[i];
        add_digit(1);
    }
    return result;
}

int main() {
    for (unsigned int base = 3; base < 18; ++base) {
        std::cout << base << ": " << largest_left_truncatable_prime(base)
                  << '\n';
    }
    for (unsigned int base = 19; base < 32; base += 2) {
        std::cout << base << ": " << largest_left_truncatable_prime(base)
                  << '\n';
    }
}




Java: import java.math.BigInteger;
import java.util.*;

class LeftTruncatablePrime
{
  private static List<BigInteger> getNextLeftTruncatablePrimes(BigInteger n, int radix, int millerRabinCertainty)
  {
    List<BigInteger> probablePrimes = new ArrayList<BigInteger>();
    String baseString = n.equals(BigInteger.ZERO) ? "" : n.toString(radix);
    for (int i = 1; i < radix; i++)
    {
      BigInteger p = new BigInteger(Integer.toString(i, radix) + baseString, radix);
      if (p.isProbablePrime(millerRabinCertainty))
        probablePrimes.add(p);
    }
    return probablePrimes;
  }
  
  public static BigInteger getLargestLeftTruncatablePrime(int radix, int millerRabinCertainty)
  {
    List<BigInteger> lastList = null;
    List<BigInteger> list = getNextLeftTruncatablePrimes(BigInteger.ZERO, radix, millerRabinCertainty);
    while (!list.isEmpty())
    {
      lastList = list;
      list = new ArrayList<BigInteger>();
      for (BigInteger n : lastList)
        list.addAll(getNextLeftTruncatablePrimes(n, radix, millerRabinCertainty));
    }
    if (lastList == null)
      return null;
    Collections.sort(lastList);
    return lastList.get(lastList.size() - 1);
  }
  
  public static void main(String[] args)
  {
    if (args.length != 2) {
      System.err.println("There must be exactly two command line arguments.");
      return;
    }
    int maxRadix;
    try {
      maxRadix = Integer.parseInt(args[0]);
      if (maxRadix < 3) throw new NumberFormatException(); 
    } catch (NumberFormatException e) {
      System.err.println("Radix must be an integer greater than 2.");
      return;
    }
    int millerRabinCertainty;
    try {
      millerRabinCertainty = Integer.parseInt(args[1]);
    } catch (NumberFormatException e) {
      System.err.println("Miiller-Rabin Certainty must be an integer.");
      return;
    }  
    for (int radix = 3; radix <= maxRadix; radix++)
    {
      BigInteger largest = getLargestLeftTruncatablePrime(radix, millerRabinCertainty);
      System.out.print("n=" + radix + ": ");
      if (largest == null)
        System.out.println("No left-truncatable prime");
      else
        System.out.println(largest + " (in base " + radix + "): " + largest.toString(radix));
    }
  }
  
}