13
\$\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\$
  • 6
    \$\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\$ – Martin Ender May 21 '15 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 '15 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 '15 at 14:37
  • \$\begingroup\$ Is a single trailing space okay? \$\endgroup\$ – Alex A. May 21 '15 at 15:19
  • 3
    \$\begingroup\$ Use the Sandbox for Proposed Challenges. \$\endgroup\$ – mbomb007 May 22 '15 at 1:09

34 Answers 34

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\$
  • \$\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\$ – Christopher Wirt Jun 19 '15 at 18:28
10
\$\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\$
  • \$\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 '15 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\$ – Andrea Biondo May 21 '15 at 19:22
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\$
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\$

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\$

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\$
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\$
  • \$\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\$ – chilemagic May 21 '15 at 14:42
  • \$\begingroup\$ Yes, thanks. I can't count on my fingers anymore how many times I forgot y///. :( \$\endgroup\$ – manatwork May 21 '15 at 14:45
3
\$\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\$
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\$
  • \$\begingroup\$ FYI, you needto call this like echo <word> | code, where <word> is your word or phrase \$\endgroup\$ – Pureferret Dec 21 '15 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\$
  • \$\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 '15 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 '15 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\$
  • \$\begingroup\$ Do you know of any online compilers where I could test this? \$\endgroup\$ – Spikatrix May 21 '15 at 10:58
  • \$\begingroup\$ There aren't any, but you can get a free trial here. \$\endgroup\$ – LegionMammal978 May 21 '15 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 '15 at 10:46
  • \$\begingroup\$ @Calle In Mathematica scripts, InputString takes the next line of input. \$\endgroup\$ – LegionMammal978 May 22 '15 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 '15 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\$
  • \$\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 '15 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\$
  • \$\begingroup\$ R is not so bad. ;) You can use cat() rather than write(..., stdout()). \$\endgroup\$ – Alex A. May 21 '15 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\$
  • \$\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 '15 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 '15 at 7:18
  • \$\begingroup\$ Ah, my tests weren't extensive enough to notice that. \$\endgroup\$ – mbomb007 May 29 '15 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\$
  • \$\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\$ – kirbyfan64sos Jun 18 '15 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\$
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\$

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\$
0
\$\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\$
0
\$\begingroup\$

C# 186

public class a{public static void Main(string[] a){Console.Write(string.Join(" ",Console.ReadLine().Split(' ').Select(x=>x.ToCharArray().Count(y=>"aeoui".ToCharArray().Contains(y)))));}}
\$\endgroup\$
  • \$\begingroup\$ This fails for the third test case. Your program doesn't seem to count AEIOU. \$\endgroup\$ – Spikatrix Jun 20 '15 at 6:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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