-- 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 vowel_codes  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 := 0;
   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 := 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

   --   subtype Long_Enough_String is String
   --      with Dynamic_Predicate =>
   --         Long_Enough_String'Length >= Natural'Max(head_length, tail_length);
   --  Will raise an exception immediately if a short string is assigned
   --    to a variable of this type

   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);

   head_count: String_Count := 0;
   tail_count: String_Count := 0;

   heads: Head_Array_Type;
   tails: Tail_Array_Type;

begin
   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 =>
               head_count := head_count + 1;
               heads(head_count) := s(1 .. head_length);
            when 4 .. 6 => 
               tail_count := tail_count + 1;
               tails(tail_count) := s(tail_start .. s'last);
         end case;
      end read_block;
   end loop;

   for i in 1 .. head_count loop
      put(heads(i));
   end loop;
   new_line;

   for i in 1 .. tail_count loop
      put(tails(i));
   end loop;
   new_line;

end vowel_codes;