Daily Challenge #80 - Longest Vowel Change

dev.to staff on October 01, 2019

The vowel substrings in the word codewarriors are o,e,a,io. The longest of these has a length of 2. Given a lowercase string that has alphabetic ch... [Read Full]
markdown guide
 

Javascript version

longestVowelList = (str) => {
  const vowels = ["a", "e", "i", "o", "u"];
  const result = vowels.map(vowel => {
    const regex = new RegExp(`[^${vowel}]+`);
    return str.split(regex)
       .filter(r => r !== "")
       .sort((a, b) => b.length - a.length);
  });
  return result.flat(1).join("");
}
console.log('---->',longestVowelList("codewarriors"));
//Output ----> aeioo
 

Gotta love JavaScript one-liners

const longest = str => str.split(/[^aeiou]+/).reduce((a, b) => b.length > a ? b.length : a, 0)
 

The new JS function matchAll is going to be really useful.
Here's a JS quickie

longestVowelRunLength = string => [...string.matchAll(/[aeiou]+/g)].reduce((acc, [match]) => Math.max(acc, match.length), 0)
 
import re

def longTokenLength(s):
    return max([len(x) for x in re.split("[^aeiou]",s)])

print longTokenLength("codewarriors")

Edit: It being python, I'm condensing my previous code down into a list comprehension.

 

Haskell

import Data.List (groupBy)

longest :: String -> Int
longest = maximum . map length . filter (isVowel . head) . groupBy bothVowels
  where
    bothVowels a b = (isVowel a) && (isVowel b)

isVowel :: Char -> Bool
isVowel = (flip elem) "aeiou"

longest "codewarriors" -- 2

I could have done it with a single fold, but I decided to group the characters by groups of vowels and non-vowels, filter out the groups that are not vowels, map the length of each group and pick the largest number.

Also, almost entirely point-free, a pity I couldn't figure out how to make bothVowels point-free.

 

Hi,
this is my first time sharing my code here, so please don't judge :)
But I really like these little challenges, thank you!

Here we go (python ftw!):

def vowel(input):
        vowels = ['a','e','i','o','u']
        lengthes = []
        lastVowel = False
        for c in input:
                if c in vowels:
                        if not lastVowel:
                                lengthes +=[1]
                        else:
                                lengthes[len(lengthes)-1] += 1
                        lastVowel = True
                else:
                        lastVowel = False
        return max(lengthes)

print(vowel("codewarriors"))

There is probably some room for improvement...

Have a nice day!

 

Hi @heidrichj you could also use the class Counter from collections package :)

from typing import Union
from collections import Counter

def vowel(word: str) -> Union[int, None]:
    letters = ('a', 'e', 'i', 'o', 'u')
    letters_on_word = Counter(word)

    for letter, quantity in letters_on_word.most_common():
        if letter in letters:
            return quantity

Tip:

Always use tuple in a list that is "fixed" to ensure that this list will be immutable

 

In golang! Could be simpler but lots of loops!

func vowel(input string) string {
    var ls string
    var ret string
    for _, c := range input {
        switch c {
        case 'a', 'e', 'i', 'o', 'u':
            ls += string(c)
        default:
            if len(ls) > len(ret) {
                ret = ls
            }
            ls = ""
        }
    }
    if len(ls) > len(ret) {
        ret = ls
    }

    return ret
}

Go Playground example original
EDIT:
Add new example with changes from comments
Go Playground example with new switch

EDIT 2:
Realized it would not handle vowels at the end of the string
Go Playground

 

Hey @peter , you can also use multiple values in a single case statement


switch c {
case 'a', 'e', 'i', 'o', 'u':
    ls += string(c)
default:
    arr = append(arr, ls)
    ls = ""
}

github.com/golang/go/wiki/Switch#m...

 

Hey good to know thanks! Just learning go so didn't realize I could do that. Thanks!

there's also strings.Count built-in method ;)

golang.org/pkg/strings/#Count

strings.Count("codewarriors", "a") // 1
 

Here's mine... would have liked to use String.prototype.matchAll, but my JS engine didn't support it. So used a generator and Array.from instead. :-)

function *matchAll(str, re) {
    let match;
    do {
        match = re.exec(str);       // get the first match of the regular expession
        if (match) yield match;     // if we have one, yield it
    } while (match != null);        // keep going until no more matches
}

const getLongestSequence = (str, re) =>
    Array.from(matchAll(str, re))   // generators are iterable
         .map(([seq]) => seq)       // extract the string from the regex match result
         .reduce((longest, cur) => 
             cur.length > longest.length ? cur : longest    // keep track of longest
         , "");

const getLongestVowelSequence = str => 
    getLongestSequence(str, /[aeiou]+/gi);  // use vowels -- g = global; i = case insensitive

Full Gist: gist.github.com/kerrishotts/a3ec30...

 

Just noticed that the challenge is to return the length ;-) Oh well -- getLongestVowelSequence("codewarriors").length will do ;-)

 

Javascript with reduce

const word = "codewarriors"

function findLongestVowels(word) {
  const regex = /[aeiou]/;

  const vowels = Array.prototype.reduce.call(word, 
      (currentLetters, nextLetter, index) => {
       if (regex.test(nextLetter)) {
           return regex.test(word[index-1]) ? 
                    currentLetters.concat('', nextLetter) : 
                    currentLetters.concat(' ', nextLetter);
       } else {
           return currentLetters;
       }
   }, "");

  const longestVowels = vowels.split(' ').reduce( (longest, current) => {
       return current.length > longest.length ? current : longest;
  }, "");

  return longestVowels.length;
}

console.log("Length of the longest vowel: " + findLongestVowels(word));
 
const longestVowelSequence = (str) => Math.max(...str.split(/[^aeiou]/).map(s => s.length))
 
 

This is the Swift version :)

func longestVowelSubstring(s: String) -> Int {
    let vowels: [Character] = ["a", "e", "i", "o", "u"]
    var max = 0
    var aux = 0

    for (_,char) in s.enumerated() {
        if (vowels.contains(char)) {
            aux += 1
            max = max < aux ? aux : max
        } else {
            aux = 0
        }
    }

    return max
}
 

Elm

module Vowel exposing (getLongestVowelSize)


getFirstVowelSubstring : String -> String
getFirstVowelSubstring string =
    case string of
        "" ->
            ""

        _ ->
            let
                first : String
                first =
                    String.left 1 string

                rest : String
                rest =
                    String.dropLeft 1 string
            in
            if List.member first [ "a", "e", "i", "o", "u", "y" ] then
                first ++ getFirstVowelSubstring rest

            else
                ""


getLongestVowel : String -> String -> String
getLongestVowel longest string =
    case string of
        "" ->
            longest

        _ ->
            let
                substring : String
                substring =
                    getFirstVowelSubstring string

                rest : String
                rest =
                    String.dropLeft 1 string
            in
            if String.length longest > String.length substring then
                getLongestVowel longest rest

            else
                getLongestVowel substring rest


getLongestVowelSize : String -> Int
getLongestVowelSize =
    getLongestVowel "" >> String.length

Tests

module VowelTest exposing (suite)

import Expect exposing (equal)
import Test exposing (Test, describe, test)
import Vowel exposing (getLongestVowelSize)


suite : Test
suite =
    describe "Vowel"
        [ test "Should return 0 for a string with no vowels" <|
            \_ -> equal 0 <| getLongestVowelSize "bcdfgh"
        , test "Should return 1 for a string with a one-vowel substring" <|
            \_ -> equal 1 <| getLongestVowelSize "abcdefghij"
        , test "Should return 2 for a string with a two-vowel substring" <|
            \_ -> equal 2 <| getLongestVowelSize "codewarriors"
        ]
 

Perl solution, tests included.

#!/usr/bin/perl
use warnings;
use strict;

sub longest_vowel_substring {
    my ($string) = @_;
    my $max_length = 0;
    $max_length < length $1 and $max_length = length $1
        while $string =~ /([aeiou]+)/g;
    $max_length
}

use Test::More tests => 2;
is longest_vowel_substring('codewarriors'), 2;
is longest_vowel_substring('xaaeexaeiooxxaxax'), 5;
code of conduct - report abuse