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