Task: Emirp primes








VB: Option Explicit

Private Const MAX As Long = 5000000
Private Emirps As New Collection
Private CollTemp As New Collection

Sub Main()
Dim t
t = Timer
    FillCollectionOfEmirps
    Debug.Print "At this point : Execution time = " & Timer - t & " seconds."
    Debug.Print "We have a Collection of the " & Emirps.Count & " first Emirps."
    Debug.Print "---------------------------"
    
    Debug.Print "the first 20 emirps: "; ExtractEmirps(1, 20)
    
    Debug.Print "all emirps between 7,700 and 8,000: "; ExtractEmirps(7700, 8000, True)
    
    Debug.Print "the 10,000th emirp: "; ExtractEmirps(10000, 10000)
  End Sub

Private Function ExtractEmirps(First As Long, Last As Long, Optional Value = False) As String
Dim temp$, i As Long, e
    If First = Last Then
        ExtractEmirps = Emirps(First)
    Else
        If Not Value Then
            For i = First To Last
                temp = temp & ", " & Emirps(i)
            Next
        Else
            For Each e In Emirps
                If e > First And e < Last Then
                    temp = temp & ", " & e
                End If
                If e = Last Then Exit For
            Next e
        End If
        ExtractEmirps = Mid(temp, 3)
    End If
End Function

Private Sub FillCollectionOfEmirps()
Dim Primes() As Long, e, i As Long
    Primes = Atkin
    For i = LBound(Primes) To UBound(Primes)
        CollTemp.Add Primes(i), CStr(Primes(i))
    Next i
    For Each e In CollTemp
        If IsEmirp(e) Then Emirps.Add e
    Next
End Sub

Private Function Atkin() As Long()
Dim MyBool() As Boolean
Dim SQRT_MAX As Long, i&, j&, N&, cpt&, MAX_TEMP As Long, temp() As Long
    ReDim MyBool(MAX)
    SQRT_MAX = Sqr(MAX) + 1
    MAX_TEMP = Sqr(MAX / 4) + 1
    For i = 1 To MAX_TEMP
        For j = 1 To SQRT_MAX
            N = 4 * i * i + j * j
            If N <= MAX And (N Mod 12 = 1 Or N Mod 12 = 5) Then
                MyBool(N) = True
            End If
        Next j
    Next i
    MAX_TEMP = Sqr(MAX / 3) + 1
    For i = 1 To MAX_TEMP
        For j = 1 To SQRT_MAX
            N = 3 * i * i + j * j
            If N <= MAX And N Mod 12 = 7 Then
                MyBool(N) = True
            End If
        Next j
    Next i
    For i = 1 To SQRT_MAX
        For j = 1 To SQRT_MAX
            N = 3 * i * i - j * j
            If i > j And N <= MAX And N Mod 12 = 11 Then
                MyBool(N) = True
            End If
        Next j
    Next i
    For i = 5 To SQRT_MAX Step 2
        If MyBool(i) Then
            For j = i * i To MAX Step i
                MyBool(j) = False
            Next
        End If
    Next
    ReDim temp(MAX / 2)
    temp(0) = 2: temp(1) = 3: cpt = 2
    For i = 5 To MAX Step 2
        If MyBool(i) Then temp(cpt) = i: cpt = cpt + 1
    Next
    ReDim Preserve temp(cpt - 1)
    Atkin = temp
End Function

Private Function IsEmirp(N) As Boolean
Dim a As String, b As String
    a = StrReverse(CStr(N)): b = CStr(N)
    If a <> b Then
        On Error Resume Next
        CollTemp.Add a, a
        If Err.Number > 0 Then
            IsEmirp = True
        Else
            CollTemp.Remove a
        End If
        On Error GoTo 0
    End If
End Function




Ada: with Ada.Text_IO, Miller_Rabin;

procedure Emirp_Gen is
   
   type Num is range 0 .. 2**63-1; 
   
   MR_Iterations: constant Positive := 25; 
     
     
   
   function Is_Emirp(E: Num) return Boolean is
      package MR is new Miller_Rabin(Num); use MR;
      
      function Rev(E: Num) return Num is
	 N: Num := E;
	 R: Num := 0;
      begin
	 while N > 0 loop
	    R := 10*R + N mod 10; 
	    N := N / 10;          
	 end loop;
	 return R;
      end Rev;
      
      R: Num := Rev(E); 
   begin
      return E /= R and then
	     (Is_Prime(E, MR_Iterations) = Probably_Prime) and then
	     (Is_Prime(R, MR_Iterations) = Probably_Prime);
   end Is_Emirp;
	
   function Next(P: Num) return Num is
      N: Num := P+1;
   begin
      while not (Is_Emirp(N)) Loop
	 N := N + 1;
      end loop;
      return N;
   end Next;
   
   Current: Num;
   Count: Num := 0;
   
begin
   
   Ada.Text_IO.Put("First 20 emirps:");
   Current := 1;
   for I in 1 .. 20 loop
      Current := Next(Current);
      Ada.Text_IO.Put(Num'Image(Current));
   end loop;
   Ada.Text_IO.New_Line;
   
   
   Ada.Text_IO.Put("Emirps between 7700 and 8000:");
   Current := 7699;
   loop
      Current := Next(Current);
      exit when Current > 8000;
       Ada.Text_IO.Put(Num'Image(Current));
   end loop;
   
   
   Ada.Text_IO.Put("The 10_000'th emirp:");
   for I in 1 .. 10_000 loop
      Current := Next(Current);
   end loop;
   Ada.Text_IO.Put_Line(Num'Image(Current));
end Emirp_Gen;