-- 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 pragma Assertion_Policy (Check); -- Turn on Dynamic_Predicate checking with ada.text_io; use ada.text_io; procedure vowels_variations is type Distinct_Vowel_Count is range 0 .. 6; -- Count number of distinct vowels in s -- A second version to consider function number_distinct_vowels(s: String) return Distinct_Vowel_Count is check: array(Character) of Boolean := (others => false); begin for c of s loop check(c) := true; end loop; return (if check('a') then 1 else 0) + (if check('e') then 1 else 0) + (if check('i') then 1 else 0) + (if check('o') then 1 else 0) + (if check('u') then 1 else 0) + (if check('y') then 1 else 0); -- Another way to calculate the answer -- for b of check loop -- if b then -- ans := ans + 1; -- end if; -- end loop; -- return ans; -- Yet Another way to calculate the answer -- subtype vowels is Character -- with static_predicate => vowels in 'a'|'e'|'i'|'o'|'u'|'y'; -- for v in vowels loop -- if check(v) then -- ans := ans + 1; -- end if; -- end loop; -- return ans; end number_distinct_vowels; -- Count number of distinct vowels in s -- A third version to consider function number_distinct_vowels2(s: String) return Distinct_Vowel_Count is type vowels is (a, e, i, o, u, y, not_a_vowel); function char2vowel(c: Character) return vowels is (case c is when 'a' => a, when 'e' => e, when 'i' => i, when 'o' => o, when 'u' => u, when 'y' => y, when others => not_a_vowel); subtype Binary_Distinct_Vowel_COunt is Distinct_Vowel_Count range 0 .. 1; function bool2BDVC(b: Boolean) return Binary_Distinct_Vowel_COunt is (if b then 1 else 0); check: array(vowels) of Boolean; ans: Distinct_Vowel_Count := 0; begin for c of s loop check(char2vowel(c)) := true; end loop; for v in vowels loop ans := ans + bool2BDVC(check(v)); -- ans := ans + Boolean'Pos(check(v)); -- The above works since False is at position 0, True at position 1! -- Not necessarily a good idea! end loop; return ans; end number_distinct_vowels2; subtype Long_String is String with Dynamic_Predicate => Long_String'length >= 3; -- Predicate_Failure => raise Constraint_Error with "String too short!"; -- Unfortunately Predicate_Failure is not yet implemented HEAD_LENGTH: Constant := 2; TAIL_LENGTH: COnstant := 3; MAX_NUM_STRINGS: Constant := 100; type String_Count is range 0 .. MAX_NUM_STRINGS; subtype String_Index is String_Count range 1 .. String_Count'last; package String_Count_IO is new Ada.Text_IO.Integer_IO(String_Count); use String_Count_IO; type Heads_Array is array(String_Index) of String(1 .. HEAD_LENGTH); type Tails_Array is array(String_Index) of String(1 .. TAIL_LENGTH); procedure process_one_string( s: Long_String; num_heads: in out String_Count; num_tails: in out String_Count; heads: in out Heads_Array; tails: in out Tails_Array) is HEAD_END: Constant Natural := s'first + HEAD_LENGTH - 1; TAIL_START: Constant Natural := s'last - TAIL_LENGTH + s'first; subtype Few_Vowels is Distinct_Vowel_Count range 0 .. 3; begin if number_distinct_vowels(s) in Few_Vowels then num_heads := num_heads + 1; heads(num_heads) := s(s'first .. HEAD_END); else num_tails := num_tails + 1; tails(num_tails) := s(TAIL_START .. s'last); end if; end process_one_string; -- Slightly shorter version procedure get_and_process_all_strings( num_heads: out String_Count; num_tails: out String_Count; heads: out Heads_Array; tails: out Tails_Array) is begin num_heads := 0; num_tails := 0; while not end_of_file loop process_one_string(get_line, num_heads, num_tails, heads, tails); end loop; end get_and_process_all_strings; procedure put(num_heads: String_Count; num_tails: String_Count; heads: Heads_Array; tails: Tails_Array) is begin for i in 1 .. num_heads loop put_line(heads(i)); end loop; for i in 1 .. num_tails loop put_line(tails(i)); end loop; end put; heads: Heads_Array; -- Array for heads tails: Tails_Array; -- Array for tails num_heads, num_tails: String_Count := 0; -- Number of heads and tails begin get_and_process_all_strings(num_heads, num_tails, heads, tails); put(num_heads, num_tails, heads, tails); put(num_heads); -- Where is this put from? put(num_tails); end vowels_variations;