17
\$\begingroup\$

This is a rather easy challenge.

Challenge

Input will contain a string (not null or empty) of maximum length 100. Output the number of vowels in each word of the string, separated by spaces.

Rules

  • The string will not be more than 100 characters in length.
  • The string will only contain alphabets A-Z , a-z and can also contain spaces.
  • Input must be consumed from the stdin or command line arguments.
  • Output must be outputted in the stdout.
  • You can write a full program, or a function that takes input from the stdin and outputs the result.
  • The vowels that your program/function needs to count are aeiou and AEIOU.

Test Cases

This is the first test case     --> 1 1 1 1 1 2
one plus two equals three       --> 2 1 1 3 2
aeiou AEIOU                     --> 5 5
psst                            --> 0
the quick brown fox jumped over the lazy dog --> 1 2 1 1 2 2 1 1 1

Scoring

This is , so the shortest submission (in bytes) wins.

\$\endgroup\$
11
  • 7
    \$\begingroup\$ Is there a reason why you insist on a rather restrictive I/O format? Not every language can (conveniently) interact with STDIN and STDOUT. We have defaults for this (which you are of course free to override if you wish), which also allow command-line argument, function argument, return value etc. (They can also be found in the tag wiki.) \$\endgroup\$ May 21, 2015 at 10:58
  • \$\begingroup\$ @MartinBüttner , "Is there a reason why you insist on a rather restrictive I/O format?" -- No. I just like stdin with stdout. I don't like to "get input" via the function arguments. command-line arguments seems ok. I've added it into the post. \$\endgroup\$
    – Spikatrix
    May 21, 2015 at 11:04
  • 4
    \$\begingroup\$ WIKIPEDIA: The name "vowel" is often used for the symbols that represent vowel sounds in a language's writing system, particularly if the language uses an alphabet. In writing systems based on the Latin alphabet, the letters A, E, I, O, U, and sometimes Y are all used to represent vowels. However, not all of these letters represent vowels in all languages. What do YOU mean by vowels? \$\endgroup\$
    – edc65
    May 21, 2015 at 14:37
  • \$\begingroup\$ Is a single trailing space okay? \$\endgroup\$
    – Alex A.
    May 21, 2015 at 15:19
  • 3
    \$\begingroup\$ Use the Sandbox for Proposed Challenges. \$\endgroup\$
    – mbomb007
    May 22, 2015 at 1:09

41 Answers 41

11
\$\begingroup\$

C, 113 108 103 96 bytes

Thanks @andrea-biondo for a particularly nice 5 byte saving.

main(a,v,c)char**v;{do{for(a=0;c=*v[1]++%32;2016%(c+27)||a++);printf("%d ",a);}while(v[1][-1]);}

This still feels sort of bloated so hopefully I can get it down quite some bytes later tonight.

The interesting part is perhaps that

!(124701951%((c-65&31)+33))

will be 1 if c is an (upper or lower case) ASCII vowel, and 0 for other characters a-zA-Z. The subexpression c-65&31 maps 'a' and 'A' to 0, 'b' and 'B' to 2, etc. When we add 33 the vowels correspond to the numbers 33, 37, 41, 47, 53 respectively, all of which are (conveniently) prime. In our range only such numbers will divide 124701951 = 33*37*41*47*53, ie only for vowels will the remainder of 124701951%(...) be zero.

EDIT: In this way one can consider the expression !(n%((c-65&31)+s)) where (n,s) = (124701951, 33) as determining whether the character c is a vowel. In the comments @andrea-biondo pointed out that the pair (n,s) = (2016,28) can also be used in this expression to determine vowelhood. I'll leave the current explanation in terms of primes above, but the reason this shorter pairing works is again because in the range 28--53 the only numbers with prime factors entirely in the set of prime factors of 2016 are 28, 32, 36, 42, 48, which correspond precisely to the vowels.

EDIT2: Another 5 bytes saved since (c-65&31)+28 can be shortened to c%32+27.

EDIT3: Converted to a do-while loop to finally get it below 100 bytes.

Test cases:

$ ./vowelc "This is the first test case"
1 1 1 1 1 2 
$ ./vowelc "one plus two equals three"
2 1 1 3 2 
$ ./vowelc "aeiou AEIOU"
5 5 
$ ./vowelc "psst"                     
0
\$\endgroup\$
2
  • \$\begingroup\$ OMG! This is just awesome! You can save more bytes by using a; outside main. This way, you reduce some bytes as you don't need to declare a in main(...) and also, don't need to initialize a from the loop. \$\endgroup\$
    – Spikatrix
    May 21, 2015 at 14:11
  • 1
    \$\begingroup\$ @CoolGuy: a is re-initialized at every loop, so you can't initialize it once to zero by declaring global. I wrote a small bruteforcer to find the smallest (n, s) pair such that n%((c-65&31)+s) is zero for vowels and non-zero for consonants (a-z, A-Z). I found (2016, 28) and it seems to work well: !(2016%((c-65&31)+28)) is 5 chars shorter. Anyway, very nice solution :) \$\endgroup\$ May 21, 2015 at 19:22
8
\$\begingroup\$

Pyth, 17 bytes

jdml@"aeiou"dcrzZ

Straightforward solution. Try it online: Demonstration or Test harness

Explanation:

               z   input
              r Z  convert to lower-case
             c     split at spaces
  m                map each word d to:
    @"aeiou"d         filter d for chars in "aeiou"
   l                  length
jd                 join by spaces and implicitly print
\$\endgroup\$
1
  • \$\begingroup\$ It always amuses me when people write a Pyth solution and call it "Straightforward" (Though this one is admittedly easier to grasp than most) +1 \$\endgroup\$ Jun 19, 2015 at 18:28
7
\$\begingroup\$

CJam, 21 19 bytes

r{el_"aeiou"--,Sr}h

How it works:

r{               }h    e# Read the first word and enter a do-while loop
  el_                  e# Convert the word into lower case and take a copy of it
     "aeiou"           e# All small caps vowels
            -          e# Remove all vowels from the copied word
             -         e# Remove all non-vowels from the original word
              ,        e# At this point, we have a string with all vowels of the word
                       e# Simply take its length
               S       e# Put a space after the number of vowel
                r      e# Read the next word. This serves as the truthy condition for the
                       e# do-while loop for us as if there are no word left, this returns
                       e# null/falsy and the do-while loop is exited

Try it online here

\$\endgroup\$
0
6
\$\begingroup\$

R, 44 43 bytes

cat(nchar(gsub("[^aeiou]","",scan(,""),T)))

Ungolfed + explanation:

# Read a string from STDIN. scan() automatically constructs a vector
# from input that contains spaces. The what= argument specifies that
# a string will be read rather than a numeric value. Since it's the
# second specified argument to scan(), we can simply do scan(,"").

s <- scan(what = "")

# For each word of the input, remove all consonants using gsub(),
# which is vectorized over its input argument.

g <- gsub("[^aeiou]", "", s, ignore.case = TRUE)

# Print the number of remaining characters in each word to STDOUT
# using cat(), which automatically separates vector values with a
# single space.

cat(nchar(g))
\$\endgroup\$
5
\$\begingroup\$

Python 3, 65 bytes

print(*[sum(c in'aeiouAEIOU'for c in w)for w in input().split()])

Very straightforward, fairly readable. w stands for word, c stands for character.

\$\endgroup\$
3
  • \$\begingroup\$ -4: lambda s:[sum(c in'aeiouAEIOU'for c in w)for w in s.split()]) \$\endgroup\$
    – Makonede
    Apr 15, 2021 at 16:45
  • \$\begingroup\$ Correction: -1 by using mine but doing split(' '), since the way you have zero-length words aren't counted \$\endgroup\$
    – Makonede
    Apr 15, 2021 at 16:51
  • \$\begingroup\$ 64 bytes \$\endgroup\$
    – movatica
    May 10, 2021 at 11:57
5
\$\begingroup\$

Perl, 35 34 31

say map{lc=~y/aeiou//.$"}split

30 characters +1 for -n.

Like a lot of Perl code, this works from right to left. split will split the inputted line on whitespace. map will run the code between {} on each word that was split. lc makes the word lower case. =~y/aeiou// will give us the count of vowels. .$" will append a space to the word. say then prints all the words!

Run with:

echo 'aeiou AEIOU' | perl -nE'say map{lc=~y/aeiou//.$"}split'
\$\endgroup\$
4
\$\begingroup\$

Ruby, 38 bytes

$><<$*.map{|x|x.count'AIUEOaiueo'}*' '

Usage:

mad_gaksha@madlab /tmp/ $ ruby t.rb This is the first test case
1 1 1 1 1 2
\$\endgroup\$
1
  • \$\begingroup\$ As of Ruby 2.7, |x|x can be replaced with numbered parameter _1 \$\endgroup\$
    – user114296
    Aug 23, 2022 at 21:52
4
\$\begingroup\$

Perl: 30 characters

(Kind of forces the rules: the numbers in the output are separated with as many spaces as the input words were.)

s|\w+|@{[$&=~/[aeiou]/gi]}|ge

Sample run:

bash-4.3$ while read s; do printf '%-30s --> ' "$s"; perl -pe 's|\w+|@{[$&=~/[aeiou]/gi]}|ge' <<< "$s"; done < test-case.txt
This is the first test case    --> 1 1 1 1 1 2
one plus two equals three      --> 2 1 1 3 2
aeiou AEIOU                    --> 5 5
psst                           --> 0

Perl: 27 characters

(Just to show how short would be if I didn't forget about y///'s return value. Again. Now go and upvote chilemagic's answer which reminded me about y///'s return value. Again.)

s|\w+|lc($&)=~y/aeiou//|ge
\$\endgroup\$
2
  • \$\begingroup\$ Dang this beats my answer. This s!\w+!lc($&)=~y/aeiou//!ge gets it down to 27 bytes (26 characters +1 for the -p. \$\endgroup\$
    – hmatt1
    May 21, 2015 at 14:42
  • \$\begingroup\$ Yes, thanks. I can't count on my fingers anymore how many times I forgot y///. :( \$\endgroup\$
    – manatwork
    May 21, 2015 at 14:45
3
\$\begingroup\$

JavaScript (ES6), 68

I/O via popup. Run the snippet in Firefox to test.

// As requested by OP

alert(prompt().replace(/\w+/g,w=>w.replace(/[^aeiou]/ig,'').length))

// Testable
f=s=>s.replace(/\w+/g,w=>w.replace(/[^aeiou]/ig,'').length)

test=[
 ['This is the first test case','1 1 1 1 1 2']
,['one plus two equals three','2 1 1 3 2']
,['aeiou AEIOU', '5 5']
]  

out=x=>O.innerHTML+=x+'\n'

test.forEach(t=>{
  r=f(t[0])
  out('Test '+ ['Fail','OK'][0|r==t[1]]
      +'\nInput:  '+ t[0]
      +'\nOutput: '+r
      +'\nCheck:  '+t[1]+'\n')
})
<pre id=O></pre>

\$\endgroup\$
3
\$\begingroup\$

Rebol - 70

print map-each n split input" "[c: 0 find-all n charset"aeiou"[++ c]c]
\$\endgroup\$
3
\$\begingroup\$

PowerShell, 35 bytes

%{($_-replace"[^aeiou]",'').length}

Kinda boring, but actually competing for once? (PowerShell is case insentitive by default, woo)

\$\endgroup\$
1
  • \$\begingroup\$ FYI, you needto call this like echo <word> | code, where <word> is your word or phrase \$\endgroup\$ Dec 21, 2015 at 9:17
3
\$\begingroup\$

Bash - 85

while read l;do for w in $l;do x=${w//[^aouieAOUIE]};echo -n ${#x}\ ;done;echo;done

Explanation

  • read l read one line from input
  • for w in l splits the line into words using whitespace separator
  • x=${w//[^aouieAOUIE]/} deletes all except vowels from the word
  • ${#x} is the length of resulting string === number of vowels
\$\endgroup\$
2
  • \$\begingroup\$ Feels somehow overdone. The requirement says the input will contain only letters and spaces. So why you prepared it to process multiple input lines? Without while..do..done would be shorter. Also not needed the last / in the pattern substitution. And a single literal space is shorter escaped than quoted. read l;for w in $l;do x=${w//[^aouieAOUIE]};echo -n ${#x}\ ;done;echo \$\endgroup\$
    – manatwork
    May 23, 2015 at 15:25
  • \$\begingroup\$ I agree but the rule says 'You can write a full program, or a function that takes input from the stdin and outputs the result.' So I've decided to make the full program. I will edit the solution to save two bytes)) Thanks! \$\endgroup\$
    – xuesheng
    May 23, 2015 at 15:57
3
\$\begingroup\$

Julia, 76 72 69 65 bytes

for w=split(readline()) print(count(i->i∈"aeiouAEIOU",w)," ")end

Ungolfed + explanation:

# Read a string from STDIN and split it into words
s = split(readline())

# For each word in the string...
for w in s
    # Get the number of vowels of any case in the word
    c = count(i -> i ∈ "aeiouAEIOU", w)

    # Print the number of vowels identified
    print(c, " ")
end

This will include a single trailing space, which I'm told is legit.

\$\endgroup\$
2
\$\begingroup\$

Mathematica, 95 bytes

Not going to win any contests, but...

Print@StringRiffle[ToString[#~StringCount~Characters@"aeiouAEIOU"]&/@StringSplit@InputString[]]
\$\endgroup\$
5
  • \$\begingroup\$ Do you know of any online compilers where I could test this? \$\endgroup\$
    – Spikatrix
    May 21, 2015 at 10:58
  • \$\begingroup\$ There aren't any, but you can get a free trial here. \$\endgroup\$ May 21, 2015 at 23:49
  • \$\begingroup\$ @CoolGuy You can run Mathematica (Wolfram Language) code online if you get a free account here. (Not sure InputString exists in the web interface though, it's a dialog in Mathematica.) \$\endgroup\$
    – user11030
    May 22, 2015 at 10:46
  • \$\begingroup\$ @Calle In Mathematica scripts, InputString takes the next line of input. \$\endgroup\$ May 22, 2015 at 21:52
  • \$\begingroup\$ ok, I see. Well still not sure if it will work in the cloud notebook but at least now I know why it's being used for stdin. \$\endgroup\$
    – user11030
    May 22, 2015 at 22:03
2
\$\begingroup\$

golflua, 55 bytes

~@W I.r():l():gm("%w+")_,c=W:g("[aeiou]",'')I.w(c,' ')$

Basic pattern matching of vowels after forced lowercase. An (ungolfed) Lua equivalent would be

line=io.read()
for word in line:lower():gmatch("%w+") do
   _,c=word:gsub("[aeiou]",'')
   io.write(c," ")
end
\$\endgroup\$
1
  • \$\begingroup\$ As an aside, for the Lua version, it'd actually be 2 characters shorter to use gsub('[aeiouAEIOU]','') and skip out on lower(). \$\endgroup\$
    – Kyle Kanos
    May 22, 2015 at 15:17
2
\$\begingroup\$

R, 139 bytes

Read/write stdout() is terrible

s=function(x,y)strsplit(x,y)[[1]]
write(unlist(Map(function(x)sum(x%in%s("AIUEOaiueo","")),Map(s,s(readLines("stdin")," "),"")),),stdout())
\$\endgroup\$
1
  • \$\begingroup\$ R is not so bad. ;) You can use cat() rather than write(..., stdout()). \$\endgroup\$
    – Alex A.
    May 21, 2015 at 15:45
2
\$\begingroup\$

Python 3, 72 bytes

Inspired by @randomra's answer. It's the same length slightly longer, but using regex instead of list comprehension. It's also less readable.

import re
print(*map(len,re.sub("[^aeiou ]","",input(),0,2).split(" ")))
\$\endgroup\$
3
  • \$\begingroup\$ Save 7 bytes: import re;print(*map(len,re.sub("[^aeiou ]","",input()).split())). (Use newline instead of ; if you want.) \$\endgroup\$
    – mbomb007
    May 22, 2015 at 19:11
  • \$\begingroup\$ @mbomb007 It needs to be case insensitive (2 is the case insensitive flag) and split by " " so there can be 0 length stuff \$\endgroup\$
    – user34736
    May 23, 2015 at 7:18
  • \$\begingroup\$ Ah, my tests weren't extensive enough to notice that. \$\endgroup\$
    – mbomb007
    May 29, 2015 at 2:31
2
\$\begingroup\$

PHP - 94

foreach(explode(' ',$argv[1]) as$d){preg_match_all('/[aeiou]/i',$d,$v);echo count($v[0]).' ';}

Ungolfed version

$a = explode(' ',$argv[1]);
foreach($a as $d) {
    preg_match_all('/[aeiou]/i', $d, $v);
    echo count($v[0]).' ';
}
\$\endgroup\$
2
\$\begingroup\$

Objective-C, 223 bytes

-(void)p:(NSString*)s{NSArray*a=[s componentsSeparatedByString:@" "];for(NSString*w in a){int c=0;for(int i=0;i<w.length;i++){if([@"aeiouAEIOU"containsString:[w substringWithRange:NSMakeRange(i,1)]]){c++;}}NSLog(@"%d",c);}}

Not the most compact language, but it works.

Uncompressed version:

- (void)p:(NSString*)s{
    NSArray*a=[s componentsSeparatedByString:@" "];
    for (NSString*w in a) {
        int c=0;
        for (int i=0;i<w.length;i++) {
            if ([@"aeiouAEIOU" containsString:
                 [w substringWithRange:NSMakeRange(i, 1)]]) {
                c++;
            }
        }
        NSLog(@"%d",c);
    }
}
\$\endgroup\$
2
\$\begingroup\$

Matlab, 73 bytes

Your challenge is not very clear (but it is interesting). I'm assuming

  • By "vowel" you mean a, e, i, o, u.
  • The string does not contain leading or trailing spaces

Code:

diff(find(regexprep([' ' input('','s') ' '],'[^aeiouAEIOU ]','')==' '))-1
\$\endgroup\$
2
\$\begingroup\$

rs, 50 bytes

This doesn't quite count; rs was uploaded around 2 weeks after this was posted. However, evidently this wouldn't win anything anyway, so it's still cool.

*[aeiou]/_
(^| )[^_\s]+ |$/ 0
[^_\s0]/
(_+)/(^^\1)

Live demo.

The implementation is rather straightforward:

*[aeiou]/_            Replace all vowels with underscores.
(^| )[^_\s]+ |$/ 0    Replace words that have no vowels with a zero.
[^_\s0]/              Remove all other letters.
(_+)/(^^\1)           Convert the underscore sequences into numbers (e.g. '___' to 3).
\$\endgroup\$
2
\$\begingroup\$

Perl, 60 45

$/=" ";while(<>){$n=()=/[aeiou]/gi;print"$n "

Thanks to kirbyfan64sos for saving me 15 bytes - that really helped!
Note there's an extra space at the end of the output.

\$\endgroup\$
1
  • \$\begingroup\$ You can remove the call to split by setting adding $/=" ";, and you can shorted the loop prefix to while(<>). With those two changes, the code becomes $/=" ";while(<>){$n=()=/[aeiou]/gi;print"$n "}, saving 14 bytes! \$\endgroup\$ Jun 18, 2015 at 19:54
2
\$\begingroup\$

Haskell, 76 68 bytes

f=interact$unwords.map(show.length).filter(`elem`"aeiouAEIOU").words

Straightforward implementation, not sure if there is anything to golf here.

\$\endgroup\$
2
\$\begingroup\$

APL (Dyalog Extended), 2̶9̶ 28 bytes

{+/¨(∊∘'aeiou'⊢)¨' '(≠⊆⊢)⌊⍵}
 +/¨ ⍝ sum each word's vowel bit array
    (∊∘'aeiou'⊢)¨ ⍝ for each word, check for vowels
       ' '(≠⊆⊢) ⍝ split string on spaces
          ⌊⍵ ⍝ convert to lowercase

-1 thanks to Razetime

Try it online!

\$\endgroup\$
10
  • \$\begingroup\$ (≠∘' '⊆⊢)' '(≠⊆⊢). \$\endgroup\$
    – Razetime
    Apr 14, 2021 at 15:49
  • \$\begingroup\$ different idea(26): {≢¨∩∘'aeiou'¨' '(≠⊆⊢)⌊⍵} \$\endgroup\$
    – Razetime
    Apr 14, 2021 at 15:51
  • \$\begingroup\$ @Razetime Oh, that's good, I like the union. \$\endgroup\$ Apr 14, 2021 at 16:02
  • 2
    \$\begingroup\$ ≢⍤∩∘'aeiou'¨≠⊆⌊ \$\endgroup\$
    – rak1507
    Apr 17, 2021 at 13:23
  • 1
    \$\begingroup\$ github.com/abrudz/dyalog-apl-extended reading the descriptions of stuff here is quite helpful, there are lots of useful features that you might as well make full use of if you're golfing in extended \$\endgroup\$
    – rak1507
    Apr 17, 2021 at 21:43
1
\$\begingroup\$

KDB(Q), 30 bytes

{sum@'lower[" "vs x]in"aeiou"}

Explanation

            " "vs x              / split x string by space
      lower[       ]             / lower case
                    in"aeiou"    / check vowel
 sum@'                           / sum each booleans
{                            }   / lambda

Test

q){sum@'lower[" "vs x]in"aeiou"}"This is the first test case"
1 1 1 1 1 2i
\$\endgroup\$
1
\$\begingroup\$

Smalltalk - 66 72

This is in Smalltalk/X; the names for stdin and stdout may be different in squeak/pharo.

Stdin nextLine subStrings do:[:w|(w count:[:c|c isVowel])print.' 'print]

In Smalltalk/X (and many other dialects), symbols understand #value:, so it can be abbreviated to 66 chars:

 Stdin nextLine subStrings do:[:w|(w count:#isVowel)print.' 'print]

If coded as a function which get the string as argument "s":

[:s|s subStrings do:[:w|(w count:#isVowel)print.' 'print]]

Of course, in real code, one would use a utility function "f", which returns a vector of the counts, and print that. However, the output format is then not exactly what the challenge asked for:

f := [:s|s subStrings collect:[:w|(w count:#isVowel)]].
(f value: Stdin nextLine) print.
\$\endgroup\$
1
\$\begingroup\$

Python 2, 76 bytes

I made this before I saw any other solution, then checked to find two P3 solutions that are shorter :( Darn P2 limitations.

print' '.join(`sum(y in'aeiouAEIOU'for y in x)`for x in raw_input().split())
\$\endgroup\$
1
\$\begingroup\$

SAS, 72

data;infile stdin;file stdout;input c$@@;x=countc(c,'aeiou','i');put x@;

The restrictive I/O format for this one really hurts this one as it is responsible for 25 of the bytes here.

\$\endgroup\$
1
\$\begingroup\$

PowerShell, 65 bytes

($input-split'\s'|%{($_-split''-match'a|e|i|o|u').count})-join' '

test by using the pattern below after saving as vowels.ps1

"the quick brown fox" | vowels.ps1

This way it is an actual script and not just a code snippet thereby satisfying constraint:

"Input must be consumed from the stdin or command line arguments."

\$\endgroup\$
1
\$\begingroup\$

Jelly, 7 bytes

Ḳf€ØcL€

Try it online!

Found with help from Mr. Xcoder in chat

Explanation

Ḳf€ØcL€ - Main link. Argument: s (a string)  e.g. "aeiou AEIOU"
Ḳ       - Split the input on spaces               ["aeiou", "AEIOU"]
   Øc   - Generate the string "AEIOUaeiou" 
 f€     - Filter out consonants from €ach         ["aeiou", "AEIOU"]
     L€ - Length of €ach                          [5, 5]

If the output must be space-separated, then append a K to the end

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.