Task: Extra primes





Java: public class ExtraPrimes {
    private static int nextPrimeDigitNumber(int n) {
        if (n == 0) {
            return 2;
        }
        switch (n % 10) {
            case 2:
                return n + 1;
            case 3:
            case 5:
                return n + 2;
            default:
                return 2 + nextPrimeDigitNumber(n / 10) * 10;
        }
    }

    private static boolean isPrime(int n) {
        if (n < 2) {
            return false;
        }
        if ((n & 1) == 0) {
            return n == 2;
        }
        if (n % 3 == 0) {
            return n == 3;
        }
        if (n % 5 == 0) {
            return n == 5;
        }

        int[] wheel = new int[]{4, 2, 4, 2, 4, 6, 2, 6};
        int p = 7;
        while (true) {
            for (int w : wheel) {
                if (p * p > n) {
                    return true;
                }
                if (n % p == 0) {
                    return false;
                }
                p += w;
            }
        }
    }

    private static int digitSum(int n) {
        int sum = 0;
        for (; n > 0; n /= 10) {
            sum += n % 10;
        }
        return sum;
    }

    public static void main(String[] args) {
        final int limit = 10_000;
        int p = 0, n = 0;

        System.out.printf("Extra primes under %d:\n", limit);
        while (p < limit) {
            p = nextPrimeDigitNumber(p);
            if (isPrime(p) && isPrime(digitSum(p))) {
                n++;
                System.out.printf("%2d: %d\n", n, p);
            }
        }
        System.out.println();
    }
}







Ada: with Ada.Text_Io;

procedure Extra_Primes is

   type Number   is new Long_Integer range 0 .. Long_Integer'Last;

   package Number_Io is new Ada.Text_Io.Integer_Io (Number);

   function Is_Prime (A : Number) return Boolean is
      D : Number;
   begin
      if A < 2       then return False; end if;
      if A in 2 .. 3 then return True;  end if;
      if A mod 2 = 0 then return False; end if;
      if A mod 3 = 0 then return False; end if;
      D := 5;
      while D * D <= A loop
         if A mod D = 0 then
            return False;
         end if;
         D := D + 2;
         if A mod D = 0 then
            return False;
         end if;
         D := D + 4;
      end loop;
      return True;
   end Is_Prime;

   subtype Digit is Number range 0 .. 9;
   type Digit_Array is array (Positive range <>) of Digit;

   function To_Digits (N : Number) return Digit_Array is
      Image : constant String := Number'Image (N);
      Res   : Digit_Array (2 .. Image'Last);
   begin
      for A in Image'First + 1 .. Image'Last loop
         Res (A) := Character'Pos (Image (A)) - Character'Pos ('0');
      end loop;
      return Res;
   end To_Digits;

   function All_Prime (Dig : Digit_Array) return Boolean is
     (for all D of Dig => Is_Prime (D));

   function Sum_Of (Dig : Digit_Array) return Number is
      Sum : Number := 0;
   begin
      for D of Dig loop
         Sum := Sum + D;
      end loop;
      return Sum;
   end Sum_Of;

   use Ada.Text_Io;
   Count : Natural := 0;
begin
   for N in Number range 1 .. 9_999 loop
      if Is_Prime (N) then
         declare
            Dig : constant Digit_Array := To_Digits (N);
         begin
            if All_Prime (Dig) and Is_Prime (Sum_Of (Dig)) then
               Count := Count + 1;
               Number_Io.Put (N, Width => 4); Put ("  ");
               if Count mod 8 = 0 then
                  New_Line;
               end if;
            end if;
         end;
      end if;
   end loop;
   New_Line;
   Put_Line (Count'Image & " extra primes.");
end Extra_Primes;