-- Reads in strings, counts the number of distinct vowels
-- For strings with 0..3 vowels, stores the head (2 chars)
-- For strings with 4..6 vowels, stores the tail (3 chars)
-- Prints all heads, followed by all tails
-- Example input:
--  abcde
--  aeiou
--  bbb
-- Example output:
--  ab
--  bb
--  iou

with ada.text_io; use ada.text_io; 

procedure vc  is 
   subtype Distinct_Vowel_Count is Natural range 0 .. 6;

   function number_distinct_vowels(s: String) return Distinct_Vowel_Count is
      a, e, i, o, u, y : Boolean := false;
      ans : Distinct_Vowel_Count;
   begin
      for c of s loop
         case c is
            when 'a' => a := true;
            when 'e' => e := true;
            when 'i' => i := true;
            when 'o' => o := true;
            when 'u' => u := true;
            when 'y' => y := true;
            when others => null;
         end case;
      end loop;
      --  How to potentially make the loop more efficient

      ans :=   (if a then 1 else 0)
             + (if e then 1 else 0)
             + (if i then 1 else 0)
             + (if o then 1 else 0)
             + (if u then 1 else 0)
             + (if y then 1 else 0);

      return ans;
      -- or simply return the expression above
   end number_distinct_vowels;

   Max_Num_Strings: Constant Natural := 100;

   subtype String_Count is Natural range 0 .. Max_Num_Strings;
   subtype String_Index is String_Count range 1 .. String_Count'Last;

   head_length: Constant Natural := 2;
   tail_length: Constant Natural := 3;
   -- 0 would be unusual, but allowed

   -- The two type must be unconstrained so that a slice can be passed in the main
   type Head_Array_Type is array(String_Index range <>) of String(1 .. head_length);
   type Tail_Array_Type is array(String_Index range <>) of String(1 .. tail_length);
   --  Constrained types like the following don't work when passing slices in the main
   --  type Head_Array_Type is array(String_Index) of String(1 .. head_length);
   --  type Tail_Array_Type is array(String_Index) of String(1 .. tail_length);

   procedure get_and_process(
      heads: out Head_Array_Type; 
      tails: out Tail_Array_Type;
      hc: out String_Count;
      tc: out String_Count
      )
   is
   begin
      hc := 0;  -- Initialize here
      tc := 0;
      while not end_of_file loop
         read_block: declare
            s: String := get_line;
            num_vowels: Distinct_Vowel_Count := number_distinct_vowels(s);
            tail_start: Integer := s'last - tail_length + s'first;
         begin
            if s'length < Natural'Max(head_length, tail_length) then
               raise Constraint_Error with " String is too short";
            end if;
            case num_vowels is 
               when 0 ..  3 =>
                  hc := hc + 1;
                  heads(hc) := s(1 .. head_length);
               when 4 .. 6 => 
                  tc := tc + 1;
                  tails(tc) := s(tail_start .. s'last);
            end case;
         end read_block;
      end loop;
   end get_and_process;

   procedure put(heads: Head_Array_Type; tails: Tail_Array_Type) is
   begin
      for i in heads'range loop
         put(heads(i));
      end loop;
      new_line;

      for c of tails loop
         put(c);
      end loop;
      new_line;
   end put;

   head_count: String_Count;  -- Don't initialize here
   tail_count: String_Count;

   heads: Head_Array_Type(String_Index);
   tails: Tail_Array_Type(String_Index);

begin
   get_and_process(heads, tails, head_count, tail_count);
   put(heads(1 .. head_count), tails(1 .. tail_count));
end vc;