Count how many vowels and consonants occur in a string

From Rosetta Code
Revision as of 06:15, 28 July 2021 by Wherrera (talk | contribs) (julia example)
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.
Task
Count how many vowels and consonants occur in a string


Other tasks related to string operations:
Metrics
Counting
Remove/replace
Anagrams/Derangements/shuffling
Find/Search/Determine
Formatting
Song lyrics/poems/Mad Libs/phrases
Tokenize
Sequences



ALGOL 68

Showing total and distinct vowel/consonant counts, as in the Go, Wren etc. samples. <lang algol68>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</lang>

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)

Factor

Works with: Factor version 0.99 2021-06-02

<lang factor>USING: ascii combinators io kernel math.statistics prettyprint sequences ;

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 ] bi@</lang>

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

Go

Same approach as the Wren entry. <lang go>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))
   }

}</lang>

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.

Julia

<lang julia>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")
   end

end

testvccount()

</lang>

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)


Phix

with javascript_semantics
constant s = "Now is the time for all good men to come to the aid of their country.",
fmt = "The string \"%s\"\n  contains %d vowels (%d distinct), %d consonants (%d distinct), and %d other\n"
sequence r = sort(filter(apply(true,find,{lower(s),{"aeioubcdfghjklmnpqrstvwxyz"}}),"!=",0))
integer ls = length(s), v = abs(binary_search(6,r))-1, uv = length(unique(r[1..v])),
        lr = length(r), c = lr-v,    other = ls-lr,    uc = length(unique(r[v+1..$]))
printf(1,fmt,{s,v,uv,c,uc,other})
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

Raku

Note that the task does not ask for the total count of vowels and consonants, but for how many occur.

<lang perl6>my @vowels = <a e i o u>; my @consonants = ;

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";</lang>

Output:
5 vowels and 8 consonants occur in the string "Forever Ring Programming Language"

REXX

version 1

<lang rexx>/* REXX */ Parse Arg s If s= Then

 s='Forever Wren programming language'

con='BCDFGHJKLMNPQRSTVWXYZ' vow='AEIOU' su=translate(s) /* translate to uppercase */ suc=su sx= /* eliminate duplicate characters */ Do While suc<>

 Parse Var suc c +1 suc
 If pos(c,sx)=0 Then sx=sx||c
 End

Say s /* show input string */ Call count su /* count all consonants and vowels */ Call count sx,'distinct' /* count unique consonants and vowels */ Exit count: Parse Arg s,tag sc=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</lang>

Output:
Forever Wren programming language
19  consonants, 11  vowels
9 distinct consonants, 5 distinct vowels

version 2

<lang rexx>/*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. */

  1. .= 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; return init: @.1='AEIOU'; @.2="BCDFGHJKLMNPQRSTVWXYZ"; upper $; $=space($,0); L=length($); return</lang>

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

<lang ring> load "stdlib.ring" see "working..." + nl str = '"' + "Forever Ring Programming Language" + '"' vowel = 0 cons =0

for n = 1 to len(str)

   strc = str[n]
   if isvowel(str[n]) = 1
      vowel += 1
   ok
   if isconsonant(strc)
      cons += 1
   ok

next

see "Input string = " + str + nl see "In string occur " + vowel + " vowels" + nl see "In string occur " + cons + " consonants" + nl see "done..." + nl

func isconsonant(c)

    bool1 = not isvowel(c)
    bool2 = (ascii(c) > 64 and ascii(c) < 91)
    bool3 = (ascii(c) > 96 and ascii(c) < 123)
    if bool1 and (bool2 or bool3)
       return 1
    else
       return 0
    ok

</lang>

Output:
working...
Input string = "Forever Ring Programming Language"
In string occur 11 vowels
In string occur 19 consonants
done...

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. <lang ecmascript>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")

}</lang>

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 <lang asm> .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 si

vowcon: 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 ! $20

cv20:

       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 ! Item

cv25: jmp cv50 cv30:  ; other: consonants

       inc     cl              ;    CTC++
       test    ebx, ebp        ;    if (CSet&Item) = 0 then
       jne     cv50
        inc    dl              ;     CDC++
        or     ebx, ebp        ;     CSet:= CSet ! Item

cv50: jmp cv10 cv90:

       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 code

common: 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 si

so10: int 29h strout: 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   numout

no10: pop ax

       add     al, '0'
       int     29h
       ret

str1 db "X86 Assembly Language!", 0 str2 db "Now is the time for all good men to come to the aid of their country.", 0 msg1 db "Contains ", 0 msg2 db " total", 0 msg2a db " distinct", 0 msg3 db " vowels and ", 0 msg4 db " consonants." crlf db 0Dh, 0Ah, 0

       end     start</lang>
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

<lang XPL0>string 0; \use zero-terminated strings int 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);
   ];

]</lang>

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.