I'm working on modernizing Rosetta Code's infrastructure. Starting with communications. Please accept this time-limited open invite to RC's Slack.. --Michael Mol (talk) 20:59, 30 May 2020 (UTC)

# Count how many vowels and consonants occur in a string

Count how many vowels and consonants occur in a string is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
Count how many vowels and consonants occur in a string

## Action!

PROC CountVovelsConsonants(CHAR ARRAY s BYTE POINTER vov,con)  BYTE i  CHAR c   vov^=0 con^=0  FOR i=1 TO s(0)  DO    c=s(i)    IF c>='A AND c<='Z THEN      c==+'a-'A    FI    IF c>='a AND c<='z THEN      IF c='a OR c='e OR c='i OR c='o OR c='u THEN        vov^==+1      ELSE        con^==+1      FI    FI  ODRETURN PROC Test(CHAR ARRAY s)  BYTE vov,con   PrintE("Input string:")  PrintE(s)  CountVovelsConsonants(s,@vov,@con)  PrintF("Vovel count=%I, consonant count=%I%E%E",vov,con)RETURN PROC Main()  Test("Now is the time for all good men to come to the aid of their country.")  Test("Forever Action! programming language")RETURN
Output:
Input string:
Now is the time for all good men to come to the aid of their country.
Vovel count=22, consonant count=31

Input string:
Forever Action! programming language
Vovel count=13, consonant count=19


This solution uses Ada 2012 aspect clauses to define discontinuous subtypes

---- count vowels and consonants in a string--with Ada.Text_IO; use Ada.Text_IO; procedure count_vowels_and_consonants is   subtype letter is Character with        Static_Predicate => letter in 'A' .. 'Z' | 'a' .. 'z';   subtype Vowel is Character with        Static_Predicate => Vowel in 'A' | 'E' | 'I' | 'O' | 'U' | 'a' | 'e' |            'i' | 'o' | 'u';   subtype consonant is Character with        Dynamic_Predicate => consonant in letter        and then consonant not in Vowel;    Input           : String (1 .. 1_024);   length          : Natural;   consonant_count : Natural := 0;   vowel_count     : Natural := 0;begin   Put ("Enter a string: ");   Get_Line (Item => Input, Last => length);   -- count consonants   for char of Input (1 .. length) loop      if char in consonant then         consonant_count := consonant_count + 1;      elsif char in Vowel then         vowel_count := vowel_count + 1;      end if;   end loop;   Put_Line ('"' & Input (1 .. length) & '"');   Put_Line     ("contains" & vowel_count'Image & " vowels and" & consonant_count'Image &      " consonants.");end count_vowels_and_consonants;
Output:
Enter a string: If not now then when? If not us then who?
"If not now then when? If not us then who?"
contains 10 vowels and 20 consonants.


## ALGOL 68

Showing total and distinct vowel/consonant counts, as in the Go, Wren etc. samples.

BEGIN # count the vowels and consonants in a string                         #    # returns the 0-based index of the upper case letter c in the alphabet  #    # or -1 if c is not a letter                                            #    OP   L = ( CHAR c )INT:         IF c >= "A" AND c <= "Z" THEN ABS c - ABS "A" ELIF c >= "a" AND c <= "z" THEN ABS c - ABS "a" ELSE -1 FI;    # prints the counts of vowels and consonants in s                       #    PROC print vc counts = ( STRING s )VOID:         BEGIN            [ 0 : 26 ]BOOL used;  FOR i FROM LWB used  TO UPB used  DO used[  i ] := FALSE OD;            [ 0 : 26 ]BOOL vowel; FOR i FROM LWB vowel TO UPB vowel DO vowel[ i ] := FALSE OD;            vowel[ L "A" ] := vowel[ L "E" ] := vowel[ L "I" ] := vowel[ L "O" ] := vowel[ L "U" ] := TRUE;            INT v total := 0, c total := 0, v count := 0, c count := 0;            FOR i FROM LWB s TO UPB s DO                IF   INT c index = L s[ i ];                     c index >= LWB used                THEN                    IF vowel[ c index ] THEN v total ELSE c total FI +:= 1;                    IF NOT used[ c index ] THEN                        IF vowel[ c index ] THEN v count ELSE c count FI +:= 1;                        used[ c index ] := TRUE                    FI                FI            OD;            print( ( """", s, """ contains", newline ) );            print( ( "    ", whole( v count, 0 ), " vowels and ", whole( c count, 0 ), " consonants (distinct)", newline ) );            print( ( "    ", whole( v total, 0 ), " vowels and ", whole( c total, 0 ), " consonants (total)",    newline ) )         END; # print vc counts #    # test cases                                                            #    print vc counts( "Now is the time for all good men to come to the aid of their country" );    print vc counts( "Help avoid turns" )END
Output:
"Now is the time for all good men to come to the aid of their country" contains
5 vowels and 13 consonants (distinct)
22 vowels and 31 consonants (total)
"Help avoid turns" contains
5 vowels and 9 consonants (distinct)
5 vowels and 9 consonants (total)


## AutoHotkey

str := "Now is the time for all good men to come to the aid of their country."oV:= [], oC := [], v := c := o := 0for i, ch in StrSplit(str)    if (ch ~= "i)[AEIOU]")        v++, oV[ch] := (oV[ch]?oV[ch]:0) + 1    else if (ch ~= "i)[A-Z]")        c++, oC[ch] := (oC[ch]?oC[ch]:0) + 1    else         o++ Vowels := "{"for ch, count in oV    Vowels .= """" ch """:" count ", "Vowels := Trim(Vowels , ", ") "}"Consonants := "{"for ch, count in oC    Consonants .= """" ch """:" count ", "Consonants := Trim(Consonants , ", ") "}" MsgBox % result := str "nn" v+c+o " characters, " v " vowels, " c " consonants and " o " other"        . "n" Vowels "n" Consonants
Output:
Now is the time for all good men to come to the aid of their country.
69 characters, 22 vowels, 31 consonants and 16 other
{"a":2, "e":6, "i":4, "o":9, "u":1}
{"c":2, "d":2, "f":2, "g":1, "h":3, "l":2, "m":3, "N":3, "r":3, "s":1, "t":7, "w":1, "y":1}

## AWK

 # syntax: GAWK -f COUNT_HOW_MANY_VOWELS_AND_CONSONANTS_OCCUR_IN_A_STRING.AWKBEGIN {    str = "Now is the time for all good men to come to the aid of their country."    printf("%s\n",str)    str = toupper(str)    for (i=1; i<=length(str); i++) {      if (substr(str,i,1) ~ /[AEIOU]/) {        count_vowels++      }      else if (substr(str,i,1) ~ /[BCDFGHJKLMNPQRSTVWXYZ]/) {        count_consonants++      }      else {        count_other++      }    }    printf("%d characters, %d vowels, %d consonants, %d other\n",length(str),count_vowels,count_consonants,count_other)    exit(0)}
Output:
Now is the time for all good men to come to the aid of their country.
69 characters, 22 vowels, 31 consonants, 16 other


## BCPL

get "libhdr" let ucase(c) =    'a' <= c <= 'z' -> c - 32,    c let letter(c) = 'A' <= ucase(c) <= 'Z' let vowel(c) =    ucase(c) = 'A' |     ucase(c) = 'E' |     ucase(c) = 'I' |     ucase(c) = 'O' |     ucase(c) = 'U' let consonant(c) = letter(c) & ~vowel(c) let count(p, s) = valof$( let total = 0 for i = 1 to s%0 if p(s%i) then total := total + 1 resultis total$) let example(s) be$( let v = count(vowel,s) let c = count(consonant,s) writef("'%S': %N vowels, %N consonants.*N", s, v, c)$) let start() be     example("If not now, then when? If not us, then who?")
Output:
'If not now, then when? If not us, then who?': 10 vowels, 20 consonants.

## C

/* https://rosettacode.org/wiki/Count_how_many_vowels_and_consonants_occur_in_a_string */ #include <stdio.h> char vowels[] = {'a','e','i','o','u','\n'}; int len(char * str) {	int i = 0;	while (str[i] != '\n') i++;	return i;} int  isvowel(char c){	int b = 0;	int v = len(vowels);	for(int i = 0; i < v;i++) {		if(c == vowels[i]) {			b = 1;			break; 		}	}	return b;} int isletter(char c){	return ((c >= 'a') && (c <= 'z') || (c >= 'A') && (c <= 'Z'));} int isconsonant(char c){	return isletter(c) && !isvowel(c);} int cVowels(char * str) {	int i = 0;	int count = 0;	while (str[i] != '\n') {		if (isvowel(str[i])) {			count++;;		}		i++;	}	return count;} int cConsonants(char * str ) {	int i = 0;	int count = 0;	while (str[i] != '\n') {		if (isconsonant(str[i])) {			count++;		}		i++;	}	return count;} int main() { 	char buff[] = "This is 1 string\n";	printf("%4d, %4d, %4d, %s\n", cVowels(buff), cConsonants(buff), len(buff), buff); 	char buff2[] = "This is a second string\n";	printf("%4d, %4d, %4d, %s\n", cVowels(buff2), cConsonants(buff2), len(buff2),  buff2);  	printf("a: %d\n", isvowel('a'));	printf("b: %d\n", isvowel('b'));	printf("Z: %d\n", isconsonant('Z'));	printf("1: %d\n", isletter('1'));}
Output:
   3,    9,   16, This is 1 string

6,   13,   23, This is a second string

a: 1
b: 0
Z: 1
1: 0



## Cowgol

include "cowgol.coh"; sub vowels_consonants(s: [uint8]): (vowels: intptr, consonants: intptr) is    vowels := 0;    consonants := 0;     while [s] != 0 loop        var ch := [s] | 32;        if ch >= 'a' and ch <= 'z' then            if ch == 'a' or ch == 'e' or ch == 'i'            or ch == 'o' or ch == 'u' then                vowels := vowels + 1;            else                consonants := consonants + 1;            end if;        end if;        s := @next s;    end loop;end sub; sub example(s: [uint8]) is      var vowels: intptr;    var consonants: intptr;    (vowels, consonants) := vowels_consonants(s);     print("'");    print(s);    print("': ");    print_i32(vowels as uint32);    print(" vowels, ");    print_i32(consonants as uint32);    print(" consonants.");    print_nl();end sub; example("If not now, then when? If not us, then who?");
Output:
'If not now, then when? If not us, then who?': 10 vowels, 20 consonants.

## F#

 // Count how many vowels and consonants occur in a string. Nigel Galloway: August 1th., 202type cType = Vowel |Consonant |Otherlet fN g=match g with 'a'|'e'|'i'|'o'|'u'->Vowel |g when System.Char.IsLetter g->Consonant |_->Otherlet n="Now is the time for all good men to come to the aid of their country."|>Seq.countBy(System.Char.ToLower>>fN)printfn "%A" n
Output:
seq [(Consonant, 31); (Vowel, 22); (Other, 16)]


## Factor

Works with: Factor version 0.99 2021-06-02
USING: ascii combinators io kernel math.statistics prettyprintsequences ; : letter-type ( char -- str )    {        { [ dup "aeiouAEIOU" member? ] [ drop "vowel" ] }        { [ Letter? ] [ "consonant" ] }        [ "other" ]    } cond ; "Forever Factor programming language""Now is the time for all good men to come to the aid of their country."[ dup ... " -> " write [ letter-type ] histogram-by . nl ] [email protected]
Output:
"Forever Factor programming language"
-> H{ { "other" 3 } { "consonant" 20 } { "vowel" 12 } }

"Now is the time for all good men to come to the aid of their country."
-> H{ { "other" 16 } { "consonant" 31 } { "vowel" 22 } }


## FreeBASIC

 Dim As String cadena = """Forever the FreeBASIC programming language"""Dim As Integer vocal = 0, consonante = 0 Function isVowel (Byval n As String) As Boolean    Select Case Asc(n)    Case 97, 65, 101, 69, 105, 73, 111, 79, 117, 85 'aAeEiIoOuU        Return True    Case Else         Return False    End SelectEnd Function Function isConsonant (Byval c As String) As Boolean    Dim As Boolean bool1, bool2, bool3    bool1 = Not isvowel(c)    bool2 = (Asc(c) > 64 And Asc(c) < 91)    bool3 = (Asc(c) > 96 And Asc(c) < 123)    If bool1 And (bool2 Or bool3) Then        Return True    Else        Return False    End IfEnd Function For n As Integer = 1 To Len(cadena)    Dim As String letra = Mid(cadena,n,1)    If isVowel(letra) Then vocal += 1    If isConsonant(letra) Then consonante += 1Next n Print "Input string = "; cadena Print "In string occur"; vocal; " vowels" Print "In string occur"; consonante; " consonants" Sleep
Output:
Input string = "Forever the FreeBASIC programming language"
In string occur 15 vowels
In string occur 23 consonants


## Go

Same approach as the Wren entry.

package main import (    "fmt"    "strings") func main() {    const (        vowels     = "aeiou"        consonants = "bcdfghjklmnpqrstvwxyz"    )    strs := []string{        "Forever Go programming language",        "Now is the time for all good men to come to the aid of their country.",    }    for _, str := range strs {        fmt.Println(str)        str = strings.ToLower(str)        vc, cc := 0, 0        vmap := make(map[rune]bool)        cmap := make(map[rune]bool)        for _, c := range str {            if strings.ContainsRune(vowels, c) {                vc++                vmap[c] = true            } else if strings.ContainsRune(consonants, c) {                cc++                cmap[c] = true            }        }        fmt.Printf("contains (total) %d vowels and %d consonants.\n", vc, cc)        fmt.Printf("contains (distinct %d vowels and %d consonants.\n\n", len(vmap), len(cmap))    }}
Output:
Forever Go programming language
contains (total) 11 vowels and 17 consonants.
contains (distinct 5 vowels and 8 consonants.

Now is the time for all good men to come to the aid of their country.
contains (total) 22 vowels and 31 consonants.
contains (distinct 5 vowels and 13 consonants.


The English of the task description is (perhaps unintentionally ?) ambiguous.

One of (at least) four possible meanings here:

import Control.Monad (join)import Data.Bifunctor (bimap, first, second)import Data.Bool (bool)import Data.Char (toUpper)import qualified Data.Set as S ----- SETS OF UNIQUE VOWELS AND CONSONANTS IN A STRING --- vowelsAndConsonantsUsed ::  String -> String -> String -> (S.Set Char, S.Set Char)vowelsAndConsonantsUsed vowels alphabet =  foldr    ( \c vc ->        if_          (S.member c vs)          (first (S.insert c))          (if_ (S.member c cs) (second (S.insert c)) id)          vc    )    (S.empty, S.empty)  where    vs = S.fromList $vowels <> fmap toUpper vowels cs = S.fromList$        filter          (S.notMember vs)          (alphabet <> fmap toUpper alphabet) --------------------------- TEST -------------------------main :: IO ()main = do  putStrLn "Unique vowels and consonants used, with counts:\n"  mapM_ print $[(,) . S.toList <*> S.size] <*> ( [fst, snd] <*> [ vowelsAndConsonantsUsed "aeiou" ['a' .. 'z'] "Forever Fortran 2018 programming language" ] ) ------------------------- GENERAL ------------------------ both :: (a -> b) -> (a, a) -> (b, b)both = join bimap if_ :: Bool -> a -> a -> aif_ p t f = if p then t else f Output: Unique vowels and consonants used, with counts: ("aeiou",5) ("Fglmnprtv",9) Another of (at least) four possible meanings: import Control.Monad (join)import Data.Bifunctor (bimap)import Data.Char (isAlpha)import Data.List (intercalate, partition)import qualified Data.Map.Strict as M ------------ COUNTS OF EACH VOWEL AND CONSONANT ---------- vowelAndConsonantCounts :: String -> ([(Char, Int)], [(Char, Int)])vowelAndConsonantCounts = join bimap M.toList . M.partitionWithKey (const . isVowel) . fst . M.partitionWithKey (const . isAlpha) . charCounts charCounts :: String -> M.Map Char IntcharCounts = foldr (flip (M.insertWith (+)) 1) M.empty isVowel :: Char -> BoolisVowel = (elem "aeiouAEIOU") --------------------------- TEST -------------------------main :: IO ()main = do let (v, c) = vowelAndConsonantCounts "Forever Fortran 2018 programming language" (vTotal, cTotal) = both (foldr ((+) . snd) 0) (v, c) putStrLn$    unlines $[ show (vTotal + cTotal) <> " 'vowels and consonants'\n" ] <> fmap ('\t' :) ( concatMap report [ ("vowels", vTotal, v), ("consonants", cTotal, c) ] ) ------------------------ FORMATTING ---------------------- report :: (String, Int, [(Char, Int)]) -> [String]report (label, total, xs) = [ show total <> ( " characters drawn from " <> show (length xs) <> (' ' : label) <> ":" ) ] <> (('\t' :) . show <$> xs)    <> [""] ------------------------- GENERIC ------------------------ both :: (a -> b) -> (a, a) -> (b, b)both = join bimap
Output:
33 'vowels and consonants'

12 characters drawn from 5 vowels:
('a',4)
('e',3)
('i',1)
('o',3)
('u',1)

21 characters drawn from 9 consonants:
('F',2)
('g',4)
('l',1)
('m',2)
('n',3)
('p',1)
('r',6)
('t',1)
('v',1)

## JavaScript

This is a new genre of deliberately ambiguous task description, perhaps ?

I suppose it might be thought to offer scope for variety, but is it really consistent with the core Rosetta goal of comparability ?

(There seem to have been a surprising number of these recently, often associated with tasks of uncertain novelty ...)

(() => {    "use strict";     // -------- COUNT OF "VOWELS AND CONSONANTS" ---------     // countOfVowelsAndConsonants :: String -> Int    const countOfVowelsAndConsonants = s =>        Array.from(s).filter(isAlpha).length;      // ---------------------- TEST -----------------------    const main = () =>        ${countOfVowelsAndConsonants( "Forever Fortran 2018 programming language" )} "vowels and consonants"; // --------------------- GENERIC --------------------- // isAlpha :: Char -> Bool const isAlpha = c => (/[A-Za-z\u00C0-\u00FF]/u).test(c); // MAIN --- return main();})(); Output: 33 "vowels and consonants" ### Counts of distinct vowels and distinct consonants seen ? (() => { "use strict"; // NUMBERS OF DISTINCT VOWELS, AND DISTINCT CONSONANTS // distinctVowelsAndConsonants :: // String -> ([Char], [Char]) const distinctVowelsAndConsonants = s => both( cs => sort(Array.from(new Set(cs))) )( partition(isVowel)( Array.from(s).filter(isAlpha) ) ); // ---------------------- TEST ----------------------- // main :: IO () const main = () => { const vc = both( cs => (${cs.join("")}, ${cs.length}) )( distinctVowelsAndConsonants( "Forever Fortran 2018 programming language" ) ); return [ Distinct vowels:${vc[0]},            Distict consonants: ${vc[1]} ].join("\n\n"); }; // --------------------- GENERIC --------------------- // Tuple (,) :: a -> b -> (a, b) const Tuple = a => b => ({ type: "Tuple", "0": a, "1": b, length: 2 }); // both :: (a -> b) -> (a, a) -> (b, b) const both = f => ab => Tuple( f(ab[0]) )( f(ab[1]) ); // isAlpha :: Char -> Bool const isAlpha = c => (/[A-Za-z\u00C0-\u00FF]/u).test(c); // isVowel :: Char -> Bool const isVowel = c => (/[AEIOUaeiou]/u).test(c); // partition :: (a -> Bool) -> [a] -> ([a], [a]) const partition = p => // A tuple of two lists - those elements in // xs which match p, and those which do not. xs => xs.reduce( (a, x) => p(x) ? ( Tuple(a[0].concat(x))(a[1]) ) : Tuple(a[0])(a[1].concat(x)), Tuple([])([]) ); // sort :: Ord a => [a] -> [a] const sort = xs => // An A-Z sorted copy of xs. xs.slice() .sort((a, b) => a < b ? -1 : (a > b ? 1 : 0)); // MAIN --- return main();})(); Output: Distinct vowels: (aeiou, 5) Distict consonants: (Fglmnprtv, 9) ### Counts of vowel and consonant occurrences ? (() => { "use strict"; // ---- COUNTS OF VOWEL AND CONSONANT OCCURRENCES ---- // vowelConsonantOccurrenceTotals :: String -> (Int, Int) const vowelConsonantOccurrenceTotals = s => Array.from(s).reduce( (ab, c) => ( isAlpha(c) ? ( isVowel(c) ? ( first(succ) ) : second(succ) ) : identity )(ab), Tuple(0)(0) ); // ---------------------- TEST ----------------------- const main = () => { const vc = vowelConsonantOccurrenceTotals( "Forever Fortran 2018 programming language" ); return [ Vowel occurrences:${vc[0]},            Consonent occurrences: ${vc[1]} ].join("\n\n"); }; // --------------------- GENERIC --------------------- // Tuple (,) :: a -> b -> (a, b) const Tuple = a => b => ({ type: "Tuple", "0": a, "1": b, length: 2 }); // first :: (a -> b) -> ((a, c) -> (b, c)) const first = f => // A simple function lifted to one which applies // to a tuple, transforming only its first item. xy => { const tpl = Tuple(f(xy[0]))(xy[1]); return Array.isArray(xy) ? ( Array.from(tpl) ) : tpl; }; // identity :: a -> a const identity = x => // The identity function. x; // isAlpha :: Char -> Bool const isAlpha = c => (/[A-Za-z\u00C0-\u00FF]/u).test(c); // isVowel :: Char -> Bool const isVowel = c => (/[AEIOUaeiou]/u).test(c); // second :: (a -> b) -> ((c, a) -> (c, b)) const second = f => // A function over a simple value lifted // to a function over a tuple. // f (a, b) -> (a, f(b)) xy => { const tpl = Tuple(xy[0])(f(xy[1])); return Array.isArray(xy) ? ( Array.from(tpl) ) : tpl; }; // succ :: Int -> Int const succ = x => 1 + x; return main();})(); Output: Vowel occurrences: 12 Consonent occurrences: 21 ### Counts of occurrence for each vowel and consonant ? (() => { "use strict"; // COUNTS OF OCCURRENCE FOR EACH VOWEL AND CONSONANT // countsOfEachVowelAndConsonant :: // String -> ([(Char, Int)], [(Char, Int)]) const countsOfEachVowelAndConsonant = s => partition( cn => isVowel(cn[0]) )( sort( Object.entries( charCounts( Array.from(s).filter(isAlpha) ) ) ) .map(([c, n]) => Tuple(c)(n)) ); // ---------------------- TEST ----------------------- const main = () => { const report = label => cns => { const total = cns.reduce( (a, cn) => a + cn[1], 0 ), rows = cns.map( compose(s => \t${s}, showTuple)                    ).join("\n");                 return [                    ${label} counts:\n${rows},                    \ttotal: ${total} ].join("\n\n"); }; const counts = countsOfEachVowelAndConsonant( "Forever Fortran 2018 programming language" ); return Array.from( bimap( report("Vowel") )( report("Consonant") )( counts ) ).join("\n\n"); }; // --------------------- GENERIC --------------------- // Tuple (,) :: a -> b -> (a, b) const Tuple = a => b => ({ type: "Tuple", "0": a, "1": b, length: 2 }); // bimap :: (a -> b) -> (c -> d) -> (a, c) -> (b, d) const bimap = f => // Tuple instance of bimap. // A tuple of the application of f and g to the // first and second values respectively. g => tpl => Tuple(f(tpl[0]))( g(tpl[1]) ); // charCounts :: String -> Dict const charCounts = s => { // A dictionary of characters seen, // with their frequencies. const go = (dct, c) => Object.assign(dct, { [c]: 1 + (dct[c] || 0) }); return Array.from(s).reduce(go, {}); }; // compose (<<<) :: (b -> c) -> (a -> b) -> a -> c const compose = (...fs) => // A function defined by the right-to-left // composition of all the functions in fs. fs.reduce( (f, g) => x => f(g(x)), x => x ); // isAlpha :: Char -> Bool const isAlpha = c => (/[A-Za-z\u00C0-\u00FF]/u).test(c); // isVowel :: Char -> Bool const isVowel = c => (/[AEIOUaeiou]/u).test(c); // partition :: (a -> Bool) -> [a] -> ([a], [a]) const partition = p => // A tuple of two lists - those elements in // xs which match p, and those which do not. xs => xs.reduce( (a, x) => p(x) ? ( Tuple(a[0].concat(x))(a[1]) ) : Tuple(a[0])(a[1].concat(x)), Tuple([])([]) ); // sort :: Ord a => [a] -> [a] const sort = xs => // An A-Z sorted copy of xs. xs.slice() .sort((a, b) => a < b ? -1 : (a > b ? 1 : 0)); // showTuple :: Tuple -> String const showTuple = tpl => (${tpl[0]}, ${tpl[1]}); // MAIN --- return main();})(); Output: Vowel counts: (a, 4) (e, 3) (i, 1) (o, 3) (u, 1) total: 12 Consonant counts: (F, 2) (g, 4) (l, 1) (m, 2) (n, 3) (p, 1) (r, 6) (t, 1) (v, 1) total: 21 ## jq Works with: jq Works with gojq, the Go implementation of jq This entry focuses solely on the A-Z alphabet.  def is_lowercase_vowel: IN("a","e","i","o","u");def is_lowercase_letter: "a" <= . and . <= "z";def is_lowercase_consonant: is_lowercase_letter and (is_lowercase_vowel|not); def synopsis: # Output: a stream of the constituent characters def characters: ascii_downcase | explode[] | [.] | implode; # For the sake of DRYness: def s(stream;$vowels; $consonants): reduce stream as$c ({($vowels): 0, ($consonants):0};      if $c|is_lowercase_vowel then .[$vowels] += 1       elif $c|is_lowercase_consonant then .[$consonants] += 1      else . end);     s( characters; "vowels"; "consonants" )  + s( [characters]|unique[]; "distinct_vowels"; "distinct_consonants" ); def task:  def pp: "Synopsis for:", ., synopsis;   "Forever HOPL",  "Now is the time for all good men to come to the aid of their country."  | pp, ""; task
Output:
Synopsis for:
Forever HOPL
{
"vowels": 4,
"consonants": 7,
"distinct_vowels": 2,
"distinct_consonants": 6
}

Synopsis for:
Now is the time for all good men to come to the aid of their country.
{
"vowels": 22,
"consonants": 31,
"distinct_vowels": 5,
"distinct_consonants": 13
}


isvowel(c) = c in ['a', 'e', 'i', 'o', 'u', 'A', 'E', "I", 'O', 'U']isletter(c) = 'a' <= c <= 'z' || 'A' <= c <= 'Z'isconsonant(c) = !isvowel(c) && isletter(c) function vccounts(s)    a = collect(lowercase(s))    au = unique(a)    count(isvowel, a), count(isconsonant, a), count(isvowel, au), count(isconsonant, au)end function testvccount()    teststrings = [        "Forever Julia programming language",        "Now is the time for all good men to come to the aid of their country."]    for s in teststrings        vcnt, ccnt, vu, cu = vccounts(s)        println("String: $s\n Vowels:$vcnt (distinct $vu)\n Consonants:$ccnt (distinct $cu)\n") endend testvccount()  Output: String: Forever Julia programming language Vowels: 13 (distinct 5) Consonants: 18 (distinct 9) String: Now is the time for all good men to come to the aid of their country. Vowels: 22 (distinct 5) Consonants: 31 (distinct 13)  ## Ksh  #!/bin/ksh # Count how many vowels and consonants occur in a string # # Variables:#string1="Now is the time for all good men to come to the aid of their country."string=${1:-${string1}} # Allow command line input consonant="b|c|d|f|g|h|j|k|l|m|n|p|q|r|s|t|v|w|x|y|z"vowel="a|e|i|o|u" integer i rctypeset -ia lettercnt uniquecnttypeset -a letlist # # Functions:## # Function _vorc(ch) - Return 0 if consonant; 1 if vowel; 99 else#function _vorc { typeset _ch ; typeset -l _char="$1" 	[[ "${_char}" == @(${consonant}) ]] && return 0	[[ "${_char}" == @(${vowel}) ]] && return 1	return 99} #	# Function _uniq(char, type, list, arr) - increment arr[] if chart not in list[]#function _uniq {	typeset _char ; _char="$1" typeset _type ; integer _type=$2	typeset _list ; nameref _list="$3" typeset _arr ; nameref _arr="$4" 	if [[ "${_char}" != @(${_list[_type]% *}) ]]; then		_list[_type]+="${_char}|" # Add letter to the proper list (( _arr[_type]++ )) # Increment uniq counter fi} ####### main # ###### echo "${string}" | while read ; do	for ((i=0; i<${#REPLY}; i++)); do char="${REPLY:${i}:1}" _vorc "${char}" ; rc=$? (( rc != 99 )) && (( lettercnt[rc]++ )) && _uniq "${char}" ${rc} letlist uniquecnt donedone printf "\n%s\n\n" "${string}"printf "Consonants: %3d  (Unique: %2d)\n" "${lettercnt[0]}" "${uniquecnt[0]}"printf "   Vowlels: %3d  (Unique: %2d)\n" "${lettercnt[1]}" "${uniquecnt[1]}"
Output:
Now is the time for all good men to come to the aid of their country.

Consonants:  31  (Unique: 13)
Vowlels:  22  (Unique:  5)

## Mathematica/Wolfram Language

vowels = {"a", "e", "i", "o", "u"};conso = {"b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z"};vowels = Join[vowels, [email protected]];conso = Join[conso, [email protected]];str = "The universe is under no obligation to make sense to you.";<|"vowels" -> StringCount[str, Alternatives @@ vowels],  "consonants" -> StringCount[str, Alternatives @@ conso],  "other" -> StringCount[str, Except[Alternatives @@ Join[vowels, conso]]]|>
Output:
<|"vowels" -> 22, "consonants" -> 24, "other" -> 11|>

## Modula-2

MODULE VowelsAndConsonants;FROM InOut IMPORT WriteString, WriteCard, WriteLn;FROM Strings IMPORT Length; PROCEDURE uppercase(c: CHAR): CHAR;BEGIN    IF (c >= 'a') AND (c <= 'z') THEN        c := CHR(ORD(c) - 32);    END;    RETURN c;END uppercase; PROCEDURE CountVowelsAndConsonants(s: ARRAY OF CHAR; VAR v, c: CARDINAL);    VAR i, length: CARDINAL;        ch: CHAR;BEGIN    v := 0;    c := 0;    length := Length(s);    IF length > 0 THEN        FOR i := 0 TO length-1 DO            ch := uppercase(s[i]);            IF (ch >= 'A') AND (ch <= 'Z') THEN                IF (ch = 'A')                 OR (ch = 'E')                 OR (ch = 'I')                 OR (ch = 'O')                 OR (ch = 'U') THEN                    INC(v);                ELSE                    INC(c);                END;            END;        END;    END;END CountVowelsAndConsonants; PROCEDURE Display(s: ARRAY OF CHAR);    VAR v, c: CARDINAL;BEGIN    WriteString('"');    WriteString(s);    WriteString('": ');    CountVowelsAndConsonants(s, v, c);    WriteCard(v, 0);    WriteString(' vowels, ');    WriteCard(c, 0);    WriteString(' consonants.');    WriteLn;END Display; BEGIN    Display("If not now, then when? If not us, then who?");END VowelsAndConsonants.
Output:
"If not now, then when? If not us, then who?": 10 vowels, 20 consonants.

## Nim

import strutils const  Vowels = {'a', 'e', 'i', 'o', 'u'}  Consonants = {'a'..'z'} - Vowels func value(val: int; unit: string): string =  $val & ' ' & unit & (if val > 1: "s" else: "") proc vcCount(text: string) = var vowels, consonants: set[char] var vowelCount, consonantCount = 0 for c in text.toLowerAscii: if c in Consonants: consonants.incl c inc consonantCount elif c in Vowels: vowels.incl c inc vowelCount echo "“$#” contains" % text  echo "    $1 and$2 (distinct)".format(value(vowels.card, "vowel"),                                         value(consonants.card, "consonant"))  echo "    $1 and$2 (total)".format(value(vowelCount, "vowel"),                                      value(consonantCount, "consonant")) vcCount("Now is the time for all good men to come to the aid of their country.")
Output:
“Now is the time for all good men to come to the aid of their country.” contains
5 vowels and 13 consonants (distinct)
22 vowels and 31 consonants (total)

#!/usr/bin/perl use strict; # https://rosettacode.org/wiki/Count_how_many_vowels_and_consonants_occur_in_a_stringuse warnings; while( <DATA> )  {  print "@{[ $- = tr/aeiouAEIOU// ]} vowels @{[ tr/a-zA-Z// -$-    ]} consonants in: $_\n" } __DATA__test oneTEST ONENow is the time for all good men to come to the aid of their country.Forever Perl Programming Language Output: 3 vowels 4 consonants in: test one 3 vowels 4 consonants in: TEST ONE 22 vowels 31 consonants in: Now is the time for all good men to come to the aid of their country. 11 vowels 19 consonants in: Forever Perl Programming Language  ## Phix with javascript_semantics procedure count_vowels_and_consonants(string s) constant vco = {"vowels","consonants","other"}, fvco = {"%d %s (%d distinct)"} sequence r = sort(filter(apply(true,find,{lower(s),{"aeioubcdfghjklmnpqrstvwxyz"}}),"!=",0)) integer v = abs(binary_search(6,r))-1, uv = length(unique(r[1..v])), c = length(r)-v, uc = length(unique(r[v+1..$])),
o = length(s)-length(r),       uo = length(unique(lower(s)))-(uv+uc)
string {sv,sc,so} = apply(true,sprintf,{fvco,columnize({{v,c,o},vco,{uv,uc,uo}})})
printf(1,"The string \"%s\"\n  contains %s, %s, and %s.\n",{s,sv,sc,so})
end procedure
count_vowels_and_consonants("Now is the time for all good men to come to the aid of their country.")

Output:
The string "Now is the time for all good men to come to the aid of their country."
contains 22 vowels (5 distinct), 31 consonants (13 distinct), and 16 other (2 distinct).


## Python

Translation of: Julia
def isvowel(c):    """ true if c is an English vowel (ignore y) """    return c in ['a', 'e', 'i', 'o', 'u', 'A', 'E', "I", 'O', 'U'] def isletter(c):    """ true if in English standard alphabet """    return 'a' <= c <= 'z' or 'A' <= c <= 'Z' def isconsonant(c):    """ true if an English consonant """    return  not isvowel(c) and isletter(c) def vccounts(s):    """ case insensitive vowel counts, total and unique """    a = list(s.lower())    au = set(a)    return sum([isvowel(c) for c in a]), sum([isconsonant(c) for c in a]), \        sum([isvowel(c) for c in au]), sum([isconsonant(c) for c in au]) def testvccount():    teststrings = [        "Forever Python programming language",        "Now is the time for all good men to come to the aid of their country."]    for s in teststrings:        vcnt, ccnt, vu, cu = vccounts(s)        print(f"String: {s}\n    Vowels: {vcnt} (distinct {vu})\n    Consonants: {ccnt} (distinct {cu})\n") testvccount()
Output:

String: Forever Python programming language

Vowels: 11 (distinct 5)
Consonants: 21 (distinct 11)

String: Now is the time for all good men to come to the aid of their country.

Vowels: 22 (distinct 5)
Consonants: 31 (distinct 13)



Or, selecting another of the various possible meanings of an ambiguous task description:

'''Total and individual counts of vowel and consonant instances''' from functools import reduce  # vowelAndConsonantCounts :: String ->#   ([(Char, Int)], [(Char, Int)])def vowelAndConsonantCounts(s):    '''The sorted character counts for each       vowel seen in the string, tupled with the sorted       character counts for each consonant seen.    '''    return both(sorted)(        partition(lambda kv: isVowel(kv[0]))([            (k, v) for (k, v) in list(charCounts(s).items())            if k.isalpha()        ])    )  # ------------------------- TEST -------------------------# main :: IO ()def main():    '''Total and individual counts for a given string'''     vs, cs = vowelAndConsonantCounts(        "Forever Fortran 2018 programming language"    )    nv, nc = valueSum(vs), valueSum(cs)    print(f'{nv + nc} "vowels and consonants"\n')     print(f'\t{nv} characters drawn from {len(vs)} vowels:')    print(showCharCounts(vs))    print(f'\n\t{nc} characters drawn from {len(cs)} consonants:')    print(showCharCounts(cs))  # ----------------------- DISPLAY ------------------------ # showCharCounts :: [(Char, Int)] -> Stringdef showCharCounts(kvs):    '''Indented listing of character frequencies.    '''    return '\n'.join(['\t\t' + repr(kv) for kv in kvs])  # ----------------------- GENERIC ------------------------ # both :: (a -> b) -> (a,  a) -> (b,  b)def both(f):    '''The same function applied to both       values of a tuple.    '''    def go(ab):        return f(ab[0]), f(ab[1])    return go  # charCount :: String -> Dictdef charCounts(s):    '''A dictionary of characters seen,       with their frequencies.    '''    def go(dct, c):        dct.update({c: 1 + dct.get(c, 0)})        return dct     return reduce(go, list(s), dict())  # isVowel :: Char -> Booldef isVowel(c):    '''True if the character is an Anglo-Saxon vowel'''    return c in "aeiouAEIOU"  # partition :: (a -> Bool) -> [a] -> ([a], [a])def partition(p):    '''The pair of lists of those elements in xs       which respectively do, and don't       satisfy the predicate p.    '''    def go(a, x):        ts, fs = a        return (ts + [x], fs) if p(x) else (ts, fs + [x])    return lambda xs: reduce(go, xs, ([], []))  # valueSum :: [(String, Int)] -> Intdef valueSum(kvs):    '''The sum of values in a [(key, value)] list'''    return sum(kv[1] for kv in kvs)  # MAIN ---if __name__ == '__main__':    main()
Output:
33 "vowels and consonants"

12 characters drawn from 5 vowels:
('a', 4)
('e', 3)
('i', 1)
('o', 3)
('u', 1)

21 characters drawn from 9 consonants:
('F', 2)
('g', 4)
('l', 1)
('m', 2)
('n', 3)
('p', 1)
('r', 6)
('t', 1)
('v', 1)

## Quackery

  [ bit     [ 0 $"AEIOUaeiuo" witheach [ bit | ] ] constant & 0 != ] is vowel ( c --> b ) [ bit [ 0$ "BCDFGHJKLMNPQRSTVWXYZ"      $"bcdfghjklmnpqrstvwxyz" join witheach [ bit | ] ] constant & 0 != ] is consonant ( c --> b ) [ 0 0 rot witheach [ tuck vowel + dip [ consonant + ] ] ] is task ($ --> n n )   $"How fleeting are all human passions compared"$ " with the massive continuity of ducks." join   task    echo say " vowels" cr  echo say " consonants"
Output:
26 vowels
43 consonants


OR, depending on how you interpret the task…

  [ 0 $"AEIOU" witheach [ bit | ] ] constant is vowels ( --> n ) [ 0$ "BCDFGHJKLMNPQRSTVWXYZ"      witheach [ bit | ] ] constant    is consonants (   --> n   )   [ 0 swap     [ dup 0 > while      tuck 1 & +      swap 1 >> again ]     drop ]                            is bitcount    ( n --> n   )  [ 0 swap witheach [ upper bit | ]    dup consonants & bitcount   swap vowels & bitcount ]           is task        ( $--> n n )$ "How fleeting are all human passions compared"   $" with the massive continuity of ducks." join task echo say " distinct vowels" cr echo say " distinct consonants" Output: 5 distinct vowels 16 distinct consonants  ## Raku Note that the task does not ask for the total count of vowels and consonants, but for how many occur. my @vowels = <a e i o u>;my @consonants = <b c d f g h j k l m n p q r s t v w x y z>; sub letter-check ($string) {    my $letters =$string.lc.comb.Set;    "{sum $letters{@vowels}} vowels and {sum$letters{@consonants}} consonants occur in the string \"$string\"";} say letter-check "Forever Ring Programming Language"; Output: 5 vowels and 8 consonants occur in the string "Forever Ring Programming Language" ## REXX ### version 1 /* REXX */Parse Arg sIf s='' Then s='Forever Wren programming language'con='BCDFGHJKLMNPQRSTVWXYZ'vow='AEIOU'su=translate(s) /* translate to uppercase */suc=susx='' /* eliminate duplicate characters */Do While suc<>'' Parse Var suc c +1 suc If pos(c,sx)=0 Then sx=sx||c EndSay s /* show input string */Call count su /* count all consonants and vowels */Call count sx,'distinct' /* count unique consonants and vowels */Exitcount:Parse Arg s,tagsc=translate(s,copies('+',length(con))copies(' ',256),con||xrange('00'x,'ff'x))sv=translate(s,copies('+',length(vow))copies(' ',256),vow||xrange('00'x,'ff'x))Say length(space(sc,0)) tag 'consonants,' length(space(sv,0)) tag 'vowels'Return Output: Forever Wren programming language 19 consonants, 11 vowels 9 distinct consonants, 5 distinct vowels ### version 2 /*REXX program counts the vowels and consonants (unique and total) in a given string. */parse arg$                                      /*obtain optional argument from the CL.*/if $='' then$= 'Now is the time for all good men to come to the aid of their country.'say 'input: '  $/*display the original string ──► term.*/call init /*initialize some constants and input. */#.= 0; call cnt 1; call cnt 2 /*count unique vowels and consonants.*/say 'There are ' #.1 " unique vowels, there are " #.2 ' unique consonants.'say 'There are ' L - length( space( translate($, , @.1), 0))     " vowels total, "    ,    'there are '    L - length( space( translate($, , @.2), 0)) " consonants total."exit 0 /*stick a fork in it, we're all done. *//*──────────────────────────────────────────────────────────────────────────────────────*/cnt: arg k; do j=1 to length(@.k); if pos(substr(@.k,j,1),$)>0 then #.k=#.k+1; end; returninit: @.1='AEIOU'; @.2="BCDFGHJKLMNPQRSTVWXYZ"; upper $;$=space($,0); L=length($); return
output   when using the default input:
input:  Now is the time for all good men to come to the aid of their country.
There are  5  unique vowels,  there are  13  unique consonants.
There are  22  vowels total,  there are  31  consonants total.


## Ring

? "working..."str = '"' + "Forever Ring Programming Language" + '"'vowel = 0 vowels = [] for x in "AEIOUaeiou" add(vowels, x) nextltrc = 0 all = 'A':'z' while all[27] != 'a' del(all, 27) end for n in str    if find(vowels, n) > 0 vowel++ ok    if find(all, n) > 0 ltrc++ oknext ? "Input string = " + str? "In string occur " + vowel + " vowels"? "In string occur " + (ltrc - vowel)  + " consonants"put "done..."
Output:
working...
Input string = "Forever Ring Programming Language"
In string occur 11 vowels
In string occur 19 consonants
done...

## Ruby

RE_V = /[aeiou]/RE_C = /[bcdfghjklmnpqrstvwxyz]/str  = "Now is the time for all good men to come to the aid of their country." grouped = str.downcase.chars.group_by do |c|  case c    when RE_V then :Vowels    when RE_C then :Consonants    else :Other  endend grouped.each{|k,v| puts "#{k}: #{v.size}, #{v.uniq.size} unique."}
Output:
Consonants: 31, 13 unique.
Vowels: 22, 5 unique.
Other: 16, 2 unique.


## Wren

Library: Wren-str

In the absence of any indications to the contrary, we take a simplistic view of only considering English ASCII vowels (not 'y') and consonants.

import "/str" for Str var vowels = "aeiou"var consonants = "bcdfghjklmnpqrstvwxyz" var strs = [    "Forever Wren programming language",    "Now is the time for all good men to come to the aid of their country."] for (str in strs) {    System.print(str)    str = Str.lower(str)    var vc = 0    var cc = 0    var vmap = {}    var cmap = {}    for (c in str) {        if (vowels.contains(c)) {            vc = vc  + 1            vmap[c] = true        } else if (consonants.contains(c)) {            cc = cc + 1            cmap[c] = true        }    }    System.print("contains (total) %(vc) vowels and %(cc) consonants.")    System.print("contains (distinct) %(vmap.count) vowels and %(cmap.count) consonants.\n")}
Output:
Forever Wren programming language
contains (total) 11 vowels and 19 consonants.
contains (distinct) 5 vowels and 9 consonants.

Now is the time for all good men to come to the aid of their country.
contains (total) 22 vowels and 31 consonants.
contains (distinct) 5 vowels and 13 consonants.


## X86 Assembly

Translation of XPL0. Assemble with tasm, tlink /t

        .model  tiny        .code        .486        org     100h ;Register assignments:;al  = Char;ebx = CSet;cl  = CTC;ch  = VTC;dl  = CDC;dh  = VDC;si  = Str;edi = VSet;ebp = Item start:  mov     si, offset str1 ;Text(Str1)        call    vowcon        mov     si, offset str2 ;Text(Str2) ;Display numbers of vowels and consonants in string at sivowcon: push    si        xor     cx, cx          ;CTC:= 0;  VTC:= 0        xor     dx, dx        xor     ebx, ebx        xor     edi, edi ;while Str(I) # 0 do; Ch:= Str(I); I++cv10:   lodsb                   ;al:= ds:[si++]        cmp     al, 0        je      cv90            ; if Ch>=^A & Ch<=^Z then        cmp     al, 'A'        jb      cv20         cmp    al, 'Z'         ja     cv20          or    al, 20h         ;  Ch:= Ch ! \$20cv20:        cmp     al, 'a'         ; if Ch>=^a & Ch<=^z then        jb      cv50        cmp     al, 'z'        ja      cv50         push    cx              ;  Item:= 1 << (Ch-^a)        mov     cl, al        sub     cl, 'a'        xor     ebp, ebp        ;  mov ebp, 1        inc     bp        shl     ebp, cl        pop     cx         cmp     al, 'a'         ;  case Ch of a e i o u vowels        je      cv22        cmp     al, 'e'        je      cv22        cmp     al, 'i'        je      cv22        cmp     al, 'o'        je      cv22        cmp     al, 'u'        jne     cv30 cv22:   inc     ch              ;    VTC++        test    edi, ebp        ;    if (VSet&Item) = 0 then        jne     cv25         inc    dh              ;     VDC++         or     edi, ebp        ;     VSet:= VSet ! Itemcv25:   jmp     cv50cv30:                           ;  other: consonants        inc     cl              ;    CTC++        test    ebx, ebp        ;    if (CSet&Item) = 0 then        jne     cv50         inc    dl              ;     CDC++         or     ebx, ebp        ;     CSet:= CSet ! Itemcv50:   jmp     cv10cv90:        pop     si        call    strout        mov     si, offset crlf ;CrLf        call    strout        mov     di, offset msg2 ;Text(" total")        call    common         mov     cx, dx          ;get distinct counts        mov     di, offset msg2a;Text(" distinct")        call    common        mov     si, offset crlf        jmp     strout ;Common display codecommon: mov     si, offset msg1 ;Text("Contains ")        call    strout        mov     al, ch          ;numout(VTC/VDC)        call    numout        mov     si, di          ;Text(" total/distinct")        call    strout        mov     si, offset msg3 ;Text(" vowels and ")        call    strout        mov     al, cl          ;numout(CTC/CDC)        call    numout        mov     si, offset msg4 ;Text(" consonants.^M^J")        jmp     strout ;Display string pointed to by siso10:   int     29hstrout: lodsb                   ;al:= ds:[si++]        cmp     al, 0        jne     so10        ret ;Display positive number in al (less than 100)numout: aam     10      ;ah:= al/10; al:= rem        push    ax        test    ah, ah        je      no10         mov    al, ah         call   numoutno10:   pop     ax        add     al, '0'        int     29h        ret str1    db      "X86 Assembly Language!", 0str2    db      "Now is the time for all good men to come to the aid of their country.", 0msg1    db      "Contains ", 0msg2    db      " total", 0msg2a   db      " distinct", 0msg3    db      " vowels and ", 0msg4    db      " consonants."crlf    db      0Dh, 0Ah, 0        end     start
Output:
X86 Assembly Language!
Contains 6 total vowels and 11 consonants.
Contains 3 distinct vowels and 8 consonants.

Now is the time for all good men to come to the aid of their country.
Contains 22 total vowels and 31 consonants.
Contains 5 distinct vowels and 13 consonants.


## XPL0

string 0;               \use zero-terminated stringsint  VTC, VDC,          \vowel total count, vowel distinct count     CTC, CDC,          \consonant total count, consonant distinct count     VSet, CSet,        \vowel and consonant bit arrays     Char, Item, I, J;char Str;[Str:= ["Forever XPL0 programming language.",        "Now is the time for all good men to come to the aid of their country."];for J:= 0 to 1 do    [I:= 0;  VTC:= 0;  VDC:= 0;  CTC:= 0;  CDC:= 0;  VSet:= 0;  CSet:= 0;    while Str(J,I) do        [Char:= Str(J,I);  I:= I+1;        if Char>=^A & Char<=^Z then            Char:= Char - ^A + ^a;      \to lower case        if Char>=^a & Char<=^z then            [Item:= 1 << (Char-^a);     \item in character set [a..z]            case Char of                ^a, ^e, ^i, ^o, ^u:                    [VTC:= VTC+1;       \vowel                    if (Item & VSet) = 0 then VDC:= VDC+1;                    VSet:= VSet ! Item;                    ]            other   [CTC:= CTC+1;       \consonant                    if (Item & CSet) = 0 then CDC:= CDC+1;                    CSet:= CSet ! Item;                    ];            ];        ];    Text(0, @Str(J,0));  CrLf(0);    Text(0, "Contains ");  IntOut(0, VTC);  Text(0, " total vowels and ");    IntOut(0, CTC);  Text(0, " consonants.^M^J");    Text(0, "Contains ");  IntOut(0, VDC);  Text(0, " distinct vowels and ");    IntOut(0, CDC);  Text(0, " consonants.^M^J");    CrLf(0);    ];]
Output:
Forever XPL0 programming language.
Contains 10 total vowels and 19 consonants.
Contains 5 distinct vowels and 9 consonants.

Now is the time for all good men to come to the aid of their country.
Contains 22 total vowels and 31 consonants.
Contains 5 distinct vowels and 13 consonants.