Task: EKG sequence convergence







Python: from itertools import count, islice, takewhile
from math import gcd

def EKG_gen(start=2):
    
    c = count(start + 1)
    last, so_far = start, list(range(2, start))
    yield 1, []
    yield last, []
    while True:
        for index, sf in enumerate(so_far):
            if gcd(last, sf) > 1:
                last = so_far.pop(index)
                yield last, so_far[::]
                break
        else:
            so_far.append(next(c))

def find_convergence(ekgs=(5,7)):
    "Returns the convergence point or zero if not found within the limit"
    ekg = [EKG_gen(n) for n in ekgs]
    for e in ekg:
        next(e)    
    return 2 + len(list(takewhile(lambda state: not all(state[0] == s for  s in state[1:]),
                                  zip(*ekg))))

if __name__ == '__main__':
    for start in 2, 5, 7, 9, 10:
        print(f"EKG({start}):", str([n[0] for n in islice(EKG_gen(start), 10)])[1: -1])
    print(f"\nEKG(5) and EKG(7) converge at term {find_convergence(ekgs=(5,7))}!")





Ada: with Ada.Text_IO;
with Ada.Containers.Generic_Array_Sort;

procedure EKG_Sequences is

   type Element_Type is new Integer;

   type    Index_Type is new Integer range 1 .. 100;
   subtype Show_Range is Index_Type  range 1 .. 30;

   type Sequence is array (Index_Type range <>) of Element_Type;
   subtype EKG_Sequence is Sequence (Index_Type);

   function GCD (Left, Right : Element_Type) return Integer is
      A : Element_Type := Left;
      B : Element_Type := Right;
   begin
      while A /= B loop
         if A > B
         then A := A - B;
         else B := B - A;
         end if;
      end loop;
      return Integer (A);
   end GCD;

   function Contains (A    : Sequence;
                      B    : Element_Type;
                      Last : Index_Type) return Boolean
   is (for some Value of A (A'First .. Last) =>  Value = B);

   function Are_Same (S, T : EKG_Sequence; Last : Index_Type) return Boolean is
      S_Copy : Sequence := S (S'First .. Last);
      T_Copy : Sequence := T (T'First .. Last);
      procedure Sort is
        new Ada.Containers.Generic_Array_Sort (Index_Type   => Index_Type,
                                               Element_Type => Element_Type,
                                               Array_Type   => Sequence);
   begin
      Sort (S_Copy);
      Sort (T_Copy);
      return S_Copy = T_Copy;
   end Are_Same;

   function Create_EKG (Start : Element_Type) return EKG_Sequence is
      EKG : EKG_Sequence := (1 => 1, 2 => Start, others => 0);
   begin
      for N in 3 .. Index_Type'Last loop
         for I in 2 .. Element_Type'Last loop
            
            
            if not Contains (EKG, I, N)
              and then GCD (EKG (N - 1), I) > 1
            then
               EKG (N) := I;
               exit;
            end if;
         end loop;
      end loop;
      return EKG;
   end Create_EKG;

   procedure Converge (Seq_A, Seq_B : Sequence;
                       Term         : out Index_Type;
                       Do_Converge  : out Boolean) is
   begin
      for I in 3 .. Index_Type'Last loop
         if Seq_A (I) = Seq_B (I) and then Are_Same (Seq_A, Seq_B, I) then
            Do_Converge := True;
            Term        := I;
            return;
         end if;
      end loop;
      Do_Converge := False;
      Term        := Index_Type'Last;
   end Converge;

   procedure Put (Seq : Sequence) is
      use Ada.Text_IO;
   begin
      Put ("[");
      for E of Seq (Show_Range) loop
         Put (E'Image);
      end loop;
      Put ("]");
   end Put;

   use Ada.Text_IO;
   EKG_2  : constant EKG_Sequence := Create_EKG (2);
   EKG_5  : constant EKG_Sequence := Create_EKG (5);
   EKG_7  : constant EKG_Sequence := Create_EKG (7);
   EKG_9  : constant EKG_Sequence := Create_EKG (9);
   EKG_10 : constant EKG_Sequence := Create_EKG (10);
begin
   Put ("EKG( 2): ");  Put (EKG_2);  New_Line;
   Put ("EKG( 5): ");  Put (EKG_5);  New_Line;
   Put ("EKG( 7): ");  Put (EKG_7);  New_Line;
   Put ("EKG( 9): ");  Put (EKG_9);  New_Line;
   Put ("EKG(10): ");  Put (EKG_10); New_Line;

   
   declare
      Term        : Index_Type;
      Do_Converge : Boolean;
   begin
      Converge (EKG_5, EKG_7, Term, Do_Converge);
      New_Line;
      if Do_Converge then
         Put_Line ("EKG(5) and EKG(7) converge at term "
                     & Term'Image);
      else
         Put_Line ("EKG5(5) and EKG(7) do not converge within "
                     & Term'Image & " terms");
      end if;
   end;
end EKG_Sequences;