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