loading...

Daily Challenge #3 - Vowel Counter

dev.to staff on June 30, 2019

Hope you’re ready for another challenge! Let’s get started with Day 3. Today’s challenge is modified from user @jayeshcp on CodeWars. Write a ... [Read Full]
markdown guide
 

JavaScript:

f=s=>s.match(/[aeiou]/gi).length

Demo on CodePen.

 

Nice solution, mine was similar in using regex match, but not as short. This one will error on a string without any vowels because match will return a null which doesn't have a length.

 

That's a good point. This could be avoided by checking if the result of the match is null and using an empty string instead. Something like this:

f=s=>(`${s}`.match(/[aeiou]/gi)||'').length;

I also used template literals before the match so numeric values or null would be process too... and now the code is even uglier than before :P

Typo ${s}

f=s=>(`${s}`.match(/[aeiou]/gi)||'').length;

Good catch! I corrected it. Thank you for letting me know!

 

I think this is the best solution if you're ok with regex.

 

Ruby

Long Solution (my first solution)

def getVowelCount(str)
  vowels = ["a", "e", "i", "o", "u"]
  count = 0
  str.downcase.split('').each do |char|
    vowels.each do |vowel|
      char == vowel ? count += 1 : count += 0
    end
  end 
  count
end

Short Solution (my refactored solution)

def getVowelCount(str)
  str.downcase.count("aeiou")
end
 

It would be interesting to know if str.count("aeiouAEIOU") was faster, or if reordering the letters to try to get the most likely match first was better – e.g. str.count("eiaouEIAOU")

 
const vowelString = 'whatever vowel string';
const count = [...(vowelString.toLowerCase())].map((letter) =>  [...'aeiou'].includes(letter) ? 1 : 0).reduce((aggr, curr) => aggr + curr);
 
 

Hi, i loved this solution. Took me a bit to get my head around the use of reduce here and it's awesome. Thanks. I learned something nice today.

 

Cool., I didn't know we can use spread on a string. 👍🏻

 

Thinking the string as a Set with O(1) for look up operations: solution is O(n), where n = len(str)

def count_vowels(str):
    vowels = "aeiouAEIOU"
    count = 0
    for c in str:
        if c in vowels:
            count += 1
    return count;

JS lambda way

conat vowels = new Set("aeiouAEIOU");
const counVowels = input => [...input].reduce((total, current) => (total += vowels.has(current)), 0);
 

My python solution!

def count_vowels(word):
    return len(l for l in word if l in "aeiou")
 

What if the word is in uppercase? Succinct though, my solution ended up like this:

import re

word = "sUpercalifragilisticexpialidocious"
def count_vowels(word):
    word = word.lower()
    letters = list(word)
    count = 0
    for letter in letters:
        if re.match("[aeiou]",letter):
            count += 1
    print count

count_vowels(word)

 

Oh I've been waiting for this one all morning! Decided I wanted to go all out on this on!

  • Rust
  • TDD
  • AND a Live Stream!

Come check it out while I work my way through this challenge! I'm live now and about to get started!

twitch.tv/coreyja

 

Here is my Rust solution all TDD'ed out!

#[macro_use]
extern crate lazy_static;

pub fn vowel_count(some_string: &str) -> usize {
    lazy_static! {
        static ref VOWELS: Vec<char> = vec!['a', 'e', 'i', 'o', 'u'];
    }

    some_string
        .to_ascii_lowercase()
        .chars()
        .filter(|c| VOWELS.contains(c))
        .count()
}

#[cfg(test)]
mod tests {
    use crate::vowel_count;

    #[test]
    fn it_works_with_an_empty_string() {
        assert_eq!(vowel_count(""), 0);
    }

    #[test]
    fn it_works_non_vowel_strings() {
        assert_eq!(vowel_count("d"), 0);
        assert_eq!(vowel_count("drthpCVM  *&^"), 0);
        assert_eq!(vowel_count("1234567890!@#$%^&*()--__+="), 0);
        assert_eq!(vowel_count("NPlkv.,<>?/"), 0);
    }

    #[test]
    fn it_works_for_strings_of_just_vowels() {
        assert_eq!(vowel_count("a"), 1);
        assert_eq!(vowel_count("A"), 1);
        assert_eq!(vowel_count("AaeEiIoOuU"), 10);
        assert_eq!(vowel_count("eoiuioEAUIAEoieaiAoe"), 20);
    }

    #[test]
    fn it_works_for_mixed_strings() {
        assert_eq!(vowel_count("deadpool"), 4);
        assert_eq!(
            vowel_count("This is just a sentence! With some words and symbols #$%"),
            13
        );
        assert_eq!(vowel_count("TESTING OUT YELLING WITH ALL CAPS"), 9);
        assert_eq!(
            vowel_count("!@#      \nThis is THE MOST COMPLICATED test SoO farrrr"),
            12
        );
    }
}

I'm still live streaming as I type this out, but once I wrap up I'll post a link to the video here!

 

Ahhh! :panic:

Turns out OBS didn't want to behave for me today, and split my stream into 2 and dies before I finished, but we got almost all of it recorded! Learnings for next stream!

Links to the video that recorded for the longest here

 

Here is my try at it in JavaScript:

/**
 * Count the number of vowels in the input and return an integer.
 */
function countVowels (inputText) {
  // Create a regular expression that matches vowels. Look for all matches (g flag) and ignore case (i flag).
  const vowelRegularExpression = /[aeiou]/gi

  // Convert the input text to lower case and find the matches.
  const vowelMatches = inputText.match(vowelRegularExpression)

  // If there are matches, return the length of the match array. Otherwise, there were no matches, so return 0.
  return (vowelMatches ? vowelMatches.length : 0)
}
 

Why not so simple as this (JS)...

const vowelsCounter = str => [...str].filter(l => 'aeiouAEIOU'.includes(l)).length;
 
import { compose } from 'crocks';

const toLowerCase = s => s.toLowerCase();
const spread = s => [...s];
const length = xs => xs.length;
const included = xs => x => xs.includes(x);
const filter = p => xs => xs.filter(p);

const charIncludesCount = chars => compose(
  length,
  filter(included(toLowerCase(chars)),
  spread,
  toLowerCase
);

const vowelCount = charIncludesCount ('aeiou');
 

JS one that's probably pretty speedy

vowelCount = string => {
  let count = 0,
    i;
  for (i = string.length; i > 0; ) {
    const c = string.charCodeAt(--i) & ~0x20; // that's a tilde btw
    count+=Number(c < 70 ? c == 69 || c == 65 : c == 73 || c == 79 || c == 85)
  }
  return count;
};

Note that:

{E:'E'.charCodeAt(0), A:'A'.charCodeAt(0), I:'I'.charCodeAt(0), O:'O'.charCodeAt(0), U:'U'.charCodeAt(0)}

-> {E:69, A:65, I:73, O:79, U:85}

and vowels go pretty much eaiou in terms of how common they are in english.

 

Python regex example

import re
def num_vowels(s):
    return len(re.findall('[aeiou]', s))
 

TI-Basic Calculator, where the string is in Ans:

sum(seq(0<inString("AEIOUaeiou",sub(Ans,I,1)),I,1,length(Ans

And yes you can omit ending parens, which helps saves some bytes (:

 

JavaScript, using reduce:

function countVowels(string) {
    const vowels = 'aeiouAEIOU';
    return string.split('').reduce((counter, current) => {
        if(vowels.indexOf(current) != -1) {
            if(counter[current]) {
                counter[current] += 1;
            } else {
                counter[current] = 1;
            }
        }
        return counter;
    }, {});
}

console.log(countVowels('How much wood would a woodchuck chuck if a woodchuck could chuck wood?'));

// { o: 11, u: 7, a: 2, i: 1 }
 

This is my solution in Swift (with an extension 😊) :

extension String {
    func numberOfVowels() -> Int {
        var count = 0
        let vowels: [Character] = ["a","e","i","o", "u", "y"]

        self.lowercased().forEach { char in
            if vowels.contains(char) {
                count += 1
            }
        }

        return count
    }
}
 

In go!

func countVowels(s string) int {
    l := strings.ToLower(s)
    count := 0
    for _, c := range l {
        switch c {
        case 'a':
            fallthrough
        case 'e':
            fallthrough
        case 'i':
            fallthrough
        case 'o':
            fallthrough
        case 'u':
            count++
        }
    }
    return count
}

Go playground example

Uses fallthrough mostly because I wanted to, count++ would be smaller, but all cases behave the same (also its more easily maintainable).

 

Haxe

static function vowels(s:String):Int {
  var vowels = 0;
  for (i in 0...s.length) {
    switch (s.charAt(i)) {
      case 'a' | 'A' | 'e' | 'E' | 'i' | 'I' | 'o' | 'O' | 'u' | 'U':
        vowels++;
    }
  }
  return vowels;
}

iterators library looked useful but you can't fold an iterator, only an iterable, disappoint.

You also have to traverse the tree to get to the next letter. But I see what you mean. Only counting equality checks, hard-coding behaves like a linear search. My bad.

I think you might still be missing Brian's point that a hash set has O(1) lookup time, which is faster than the tree set's O(log n).

(On paper. Real-world implementations vary. e.g. Ruby's hashes just do linear search at this size.)

 

My solution is a bit longer because I don't know regex, but it gets the job done.

CodePen


const countVowels = text => {
  let count = 0;
  text.toLowerCase().split("").forEach(char => {
    if (char === "a" || char === "e" || char === "i" || char === "o" || char === "u")
      count++;
  })
  return count;
}

 

GO

func FindVowelsCount(sentence string) int {
    vowels := []string{"a", "e", "i", "o", "u"}
    lowerCaseSentence := strings.ToLower(sentence)

    vowelsCount := 0
    for _, c := range lowerCaseSentence {
        if contains(vowels, string(c)) {
            vowelsCount++
        }
    }

    return vowelsCount
}

func contains(list []string, item string) bool {
    for _, w := range list {
        if w == item {
            return true
        }
    }
    return false
}
 

Could also

const compose = (...fns) => fns.reduce((f, g) => (...args) => (f(g(...args)));
 

Python

def vowelcounter(string):
    i = 0
    string = string.lower()

    for x in string:
        if x in 'aeiou':
            i += 1
    print(i)

vowelcounter("This is a test")
 

Nim

from unicode import toLower

proc countVowels(input: string): int =
  for i in toLower(input):
    if i in "aeiou":
      result += 1

if isMainModule:
  const input = "@PPLes!43"

  echo countVowels(input)
 
use regex::Regex;

fn main() {
    let re = Regex::new(r"[aeiou]").unwrap();
    let mut result: i32 = 0;
    for _mat in re.find_iter("Hello, world!") {
        result += 1;
    }
    println!("Vowel count: {:?}", result)
}

Link to playground - play.rust-lang.org/?version=stable...

 

A solution in Elixir

defmodule VowelCounter do
  @vowels ~r/(a|e|i|o|u)/i
  
  def count(""), do: 0

  def count(string) do
    @vowels 
    |> Regex.scan(string)
    |> Enum.count() 
  end
end
 

Ruby:

def removeAccents(str)
    accents = {
        ['á','à','â','ä','ã'] => 'a',
        ['é','è','ê','ë'] => 'e',
        ['í','ì','î','ï'] => 'i',
        ['ó','ò','ô','ö','õ'] => 'o',
        ['ú','ù','û','ü'] => 'u'
      }
      accents.each do |ac,rep|
        ac.each do |s|
          str = str.gsub(s, rep)
        end
      end
      str = str.gsub(/[^a-zA-Z0-9\. ]/,"")
      str = str.gsub(/[ ]+/," ")
  str = str.gsub(/ /,"-")
  return str
end


def verifyVowels(texto)
    allLc = removeAccents(texto.downcase);
    countVowels = 0;
    allLc.split("").each do |letra|
        if (letra == 'a') | (letra == 'e') | (letra == 'i') | (letra == 'o') | (letra == 'u')
            countVowels+= 1;
        end
    end
    return countVowels
end
 

Here is my simple solution with PHP:

function getCount($str) {
  $vowelsCount = 0;

  $vowels = ['a', 'e', 'i', 'o', 'u'];

  $index = 0;
  for(; $index < mb_strlen($str); $index++) {
    if (in_array($str[$index], $vowels)) {
      $vowelsCount += 1;
    }
  }

  return $vowelsCount;
}
 
function countVowels(string) {
  if(typeof(string) !== 'string')
    throw new Error('input must be a string');

  const vowels = 'aeiouAEIOU';
  let vowelCount = 0;

  for(index in string) {
    if(vowels.includes(string.charAt(index)))
      vowelCount++;
  }
  return vowelCount;
}

ledgible I hope

 
const isIncludedIn = <Data>(collection: Data[]) => (value: Data) =>
  collection.includes(value);
const toChars = (input: string) => [...input];
const length = (xs: any[]) => xs.length;
const keepIf = filter => (xs: any[]) => xs.filter(filter);
const pipe = (...fns: Function[]) =>
  fns.reduce((f, g) => (...args) => g(f(...args)));

const detect = (detectableChars: string[]) =>
  pipe(
    toChars,
    keepIf(isIncludedIn(detectableChars)),
    length,
  );

const VOWELS = {
  LOWERCASE: ["a", "e", "i", "o", "u"],
  UPPERCASE: ["A", "E", "I", "O", "U"],
};
const DETECTABLE_LETTERS = [...VOWELS.LOWERCASE, ...VOWELS.UPPERCASE];
export const vowelCounter = detect(DETECTABLE_LETTERS);

 
const test = require('./tester');
const vowelCount = str => String(str)
    .toLowerCase()
    .split('')
    .filter(ch => 'aeiou'.indexOf(ch) > -1)
    .length;

test(vowelCount, [
    {
        in: ["Hello O'Henry !"],
        out: 4,
    },
    {
        in: ['gnsp'],
        out: 0
    }
]);
 

Powershell

I do try to keep it as an actual function and give pretty/usable output.

function Get-VowelCount {
    param(
        [string]$InString
    )

    [pscustomobject]@{
        String              = $InString
        LowerCaseCount = [regex]::Matches($InString,'[aeiou]').Count
        UpperCaseCount = [regex]::Matches($InString, '[AEIOU]').count
    }
}
 

//TS

my solution with TDD:

test:

import vowelCounter from './vowel-counter';

describe('tdd vowel counter', () => {
    test('should be 0 if empty string', () => {
        expect(vowelCounter('')).toEqual(0);
    });
    test('should be return counter', () => {
        expect(vowelCounter('aWscErvO')).toEqual(3);
        expect(vowelCounter('aaaa')).toEqual(4);
        expect(vowelCounter('IIIII')).toEqual(5);
        expect(vowelCounter('AEr#_%^&tioCda')).toEqual(5);
    });
});

and func


export default (str: string): number =>
    str
        .toLowerCase()
        .split('')
        .filter(val => ['a', 'e', 'i', 'o', 'u'].includes(val)).length;
 

In F#

let isVowel (c:char) =
    match c.ToString().ToLowerInvariant() with
    | "a" | "e" | "i" | "o" | "u" -> 1
    | _ -> 0

let vowelCount (s:string) = s.ToCharArray() |> Array.sumBy(fun x -> isVowel x)

printfn "%d" (vowelCount "The cUnNinG fOx jumpEd over the lazy dog - twice!")
 

Here's my solution:
PHP:


function countVowels($string){
    preg_match_all("/[aeiou]/i", $string, $matches);
    return sizeof($matches[0]);
}
echo "Number of vowels : " . countVowels("sUpercalifragilisticexpialidocious");


 

Dart

import 'dart:io';

main(){
  stdout.writeln('Phrase?');
  String phrase = stdin.readLineSync();
  var regExp =  RegExp(r'[aeiou]');
  phrase.length > 2 ? print("Vocal count: " + regExp.allMatches(phrase.toLowerCase()).length.toString()) : print('Invalid Phrase');
}
 

SQL (Postgres)


\set x 'Hello world'

 select count(*) from                                                                                            
   (select 
     regexp_matches(:'x', '[aeiou]', 'gi')) 
     as vowels; 

 

This is very easy in Perl, as the transliteration operator returns the number of matches:

sub vowel_count2 { shift =~ tr/aeiouAEIOU// }

One can also use the Saturn (or Goatse) "secret" operator with a regex match:

sub vowel_count { my $count =()= shift =~ /[aeiou]/gi }

The global match returns all the matches in list context, the assignment to () enforces list context, and enforcing scalar context on it by a scalar assignment returns the number of elements.

 

Java:


  public static void main(String[] args) {

        Scanner scan = new Scanner(System.in);
        System.out.println("Type the word:");
        String word = scan.nextLine();

        String[] letters = word.split("");
        int count = 0;

        for (String l : letters) {
            if (l.matches("[aeiouAEIOU]")) {
                count += 1;
            }
        }

        System.out.println("The number of vowels is: " + count);
}

 
const charCounter = ({strToCount = "", chars = ""} = {}) => {
    const charsToCount = chars.toLowerCase();
    return Array.from(strToCount.toLowerCase())
        .reduce((acc, candidate) => acc += charsToCount.includes(candidate) 
        ? 1 : 0, 0)
}

const countVowels= strToCount => charCounter({strToCount, chars: "aeiou"});

assert(countVowels("The quick brown fox jumps over the lazy dog.") === 11);
assert(countVowels("Hello") === 2);
assert(countVowels("Xyl") === 0);
assert(countVowels("aeiouAEIOU") === 10);
 

A little late to the party, but this is my JavaScript solution:

function vowelCounter(text) {
  const letters = text.toLowerCase().split('');
  const count = [...'aeiou'].map(vowel => 
    letters.filter(letter => letter === vowel)).flat().length;
  return count;
}

 
module Vowels (countVowels) where

import Data.Char (toUpper)

isVowel :: Char -> Bool
isVowel = flip elem "AEIOU"

countChar :: Char -> Integer
countChar letter = if isVowel letter 1 else 0

countVowels :: String -> Integer
countVowels = sum . map (countChar . toUpper)

Will have to double check the syntax (on Mobile) but I think this will work

 

Ruby Language

with specs

def vowels str
  str.to_s.scan(/[aeiou]/i).size
end

require "spec"

describe "#vowels" do
  it { expect(vowels nil).to eq 0}
  it { "aeiou".split('').each{|v| expect(vowels v).to eq 1} }
  it { "AEIOU".split('').each{|v| expect(vowels v).to eq 1} }
  it { expect(vowels "foo").to eq 2}
  it { expect(vowels "FOO").to eq 2}
  it { expect(vowels "BCDFG").to eq 0}
  it { expect(vowels "QuEUeInG").to eq 5}
end

output

>> rspec vowels.rb
.......

Finished in 0.00579 seconds (files took 0.14931 seconds to load)
7 examples, 0 failures
 

Python

Given the list :

vowels = ['a', 'e', 'i', 'o', 'u']

We can define a function:

def vowels_count(word):
    count = 0
    for vowel in vowels:
        count += word.lower().count(vowel)
    return count

Or simply in a one-liner:

vowel_count = lambda word: len([char for char in word if char in vowels])
 

function findVowelLetters(s){
var v = ["a","e","o","i","u"];
var vow = "";
var slowerCase = s.toLowerCase();
for(var f of v){
for(var i =0; i<s.length ; i++){
if(slowerCase[i] === f){
vow += f;
}
}
}
return vow;

}

 

BASH

echo "some STRING 123 (-_-)" | grep -o -i "[aieou]" | wc -l
 

Shell/awk oneliner:

string="Some random string"
awk '{IGNORECASE=1; print gsub(/a|e|i|o|u/, "")}' <<< $string
 

Not sure if I follow. O(n log n) is worst than O(n). Insertions in a binary tree are expensive to keep it balanced.
If you use a set or hashmap assuming zero collisions, the look up is O(1). Then the bottke neck is in the string iteration. Right?

 

Clojure:

;; with regex
(defn vowels [s]
  (count (re-seq #"(?i)[aeiou]" s)))
;; without
(defn vowels [s]
  (count (filter #(some #{%} "AaEeIiOoUu") s)))
 

PHP

function count_vowels(string $str) {
    return preg_match_all('/([aeiou])./', strtolower($str));
}
 

C++

int alphaArray [26];

for (int i = 0; i < 26; i++) {
    alphaArray[i] = 0;
}

for (int index = 0; index < userInput.length(); index++) {

    userInput[index] = tolower(userInput[index]);
}

for (int characterIndex = 0; characterIndex < userInput.length(); characterIndex++) {

    alphaArray[userInput[characterIndex] - 97]++;
}

int vowels = alphaArray[0] + alphaArray[4] + alphaArray[8] + alphaArray[14] + alphaArray[20];

cout << "Total number of vowels" << vowels << endl;
cout << "Number of A's: " << alphaArray[0] << endl;
cout << "Number of E's: " << alphaArray[4] << endl;
cout << "Number of I's: " << alphaArray[8] << endl;
cout << "Number of O's: " << alphaArray[14] << endl;
cout << "Number of U's: " << alphaArray[20] << endl;
 

ReasonML

Sketch: sketch.sh/s/jjxviGaqjQ2P0ZI0SFC2Sg/

let is_vowel = letter =>
  switch (Char.lowercase_ascii(letter)) {
  | 'a'
  | 'e'
  | 'i'
  | 'o'
  | 'u'
  | 'y' => true
  | _ => false
  };

let explode = s => List.init(String.length(s), String.get(s));

let get_vowel_count = text =>
  text |> explode |> List.filter(is_vowel) |> List.length;

get_vowel_count("hello my name is Earl!");
 

R with some Regex fun:

vowelCounter <- function(s) {
  vowelMatches <- sum(attr(gregexpr("[aeiou]",s, ignore.case = TRUE,
                                    perl= TRUE)[[1]],"match.length"),
                      na.rm = TRUE)
  vowelMatches[vowelMatches == -1 ] <- 0
  return(vowelMatches)
}

 

Python

def vowel(str): 
    count = 0
    vowels = set("aeiouAEIOU") 
    for alphabet in str: 
        if alphabet in vowels: 
            count = count + 1
    print("No. of vowels :", count) 
str = "The Practical Dev"
vowel(str) 
 

Rubeh

require 'set'
vwls = %w"a e i o u".to_set

def sm_vwls(strng)
  strng.chars.sum { |c| vwls.include?(c) }
end
 

Haskell

countVowels :: String -> Int
countVowels = length . filter (flip elem "aeiou")
 

Java

Objects.requireNonNull(input, "cannot be null");
return Arrays.stream(input.split(""))
   .map(s -> s.toLowerCase())
   .filter(s -> s.matches("[aeiou]"))
   .count();
 
 

Here comes Another 🚀

Python

def challenge3(s):
    s = s.lower()
    N = 0
    for i in s:
        if i in ["a" , "e" , "i" , "o" , "u"]:
            N += 1
    return N
 
private static List<char> vowels = new List<char>('e','a','i','o','u','E','A','I','O','U');

public static int VowelCount(this string str) => 
    str.Count(c => vowels.Contains(c));
 

Haskell:

import Data.Char

countVowels :: [Char] -> Int
countVowels = length . filter (`elem` "aeiou" ) . map toLower
 

Groovy has a nice built-in Pattern matcher

Integer countVowels(String text) {
    return (text =~ /(?i)[aeiou]/).size()
}
 
vowels = (str) => (str.match(/[aeiou]/gi) || '').length;

;)

 

Using Regex in C#

var vowelCount = Regex.Matches(input, @"[AEIOUaeiou]").Count;
 

Ruby

def vowel_count(text)
  text.scan(/([aeiou])/i).size
end


puts vowel_count("Hello World!!!!") #3
 

We don't care about the vowels being ordered for this problem, so you'd be paying extra time (vs. a hash-based set, or just hard-coded equality checks) for a property you're not using.

 

// Java

public static int countVowels(String input) {
return input.length()-input.replaceAll("(?i)[aeiou]", "").length();
}

 

Python :
def count_vowels(word):
word=word.lower()
data={x:word.count(x) for x in "aeiou"}
return data

 

var vowelCount = Regex.Matches(str, @"[AEIOUaeiou]").Count;
Console.WriteLine(vowelCount);

code of conduct - report abuse