-2

I've been looking everywhere for a good answer to my question. How do you create a function to count vowels, consonants, and punctuation characters in a sentence. I managed to find an answer for the first two, but not the last one.

func findVowelsConsonantsPunctuation(_ sentence:String) -> (Vowels:Int, Consonants:Int, Punctuation:Int) {
    var Vowels = 0, Consonants = 0, Punctuation = 0
    for character in sentence {
        switch String(character).lowercased() {
        case "a","e","i","o","u":
            Vowels += 1
        case "b","c","d","f","g","h","j","k","l","m","n","p","q","r","s","t","v","w","x","y","z":
            Consonants += 1
        default:
            break
        }
    }

    return (Vowels, Consonants, Punctuation)
}
Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
  • You mean everything else then vowels and consonants? Then just count the default case. – Retterdesdialogs Oct 29 '18 at 15:47
  • I mean count capitalization and spaces. – Conrad Kusion Oct 29 '18 at 15:48
  • What's wrong with simply putting `punctuation += 1` in the `default` case? – rmaddy Oct 29 '18 at 15:52
  • Will that detect spaces and capitalization? – Conrad Kusion Oct 29 '18 at 15:54
  • Check for capitalization with https://jjude.com/swift-challenge-009/ and if your character is a space with String(character) == " " – Retterdesdialogs Oct 29 '18 at 15:56
  • 2
    Your question says nothing about capitalization. Why do you need capitalization? Both `a` and `A` are already being matched as a vowel, for example. – rmaddy Oct 29 '18 at 16:03
  • The challenge I have specifically says to match capitalization and spaces. – Conrad Kusion Oct 29 '18 at 16:05
  • @rmaddy sentences can contain numbers and other special characters (especially when the input String is UTF-8 and not ASCII) that are not punctuation characters – Dávid Pásztor Oct 29 '18 at 16:05
  • You can count punctuation characters and uppercase characters by `case CharacterSet.punctuationCharacters, CharacterSet.uppercaseLetters: punctuation += 1`. However, are you sure your input sentence will always be English? Hardcoding vowels and consonants will only work if your language doesn't change. – Dávid Pásztor Oct 29 '18 at 16:09
  • @DávidPásztor I'm well aware of what a `String` can contain. I'm trying to get the OP to clarify their question. – rmaddy Oct 29 '18 at 16:17
  • Should this function return `(vowels: Int, consonants: Int, punctuation: Int, spaces: Int, capitalLetters: Int)`? – ielyamani Oct 29 '18 at 16:20
  • @Carpsen90 No, the capital letters and spaces are characterized under Punctuation – Conrad Kusion Oct 29 '18 at 16:27
  • Categorizing capital letters as punctuation is not right, wouldn't you say? Maybe you could call that third category `other` which would include numerals and emojis, etc – ielyamani Oct 29 '18 at 16:34

1 Answers1

0

You could do something like this:

extension CharacterSet {
    static let vowels: CharacterSet = CharacterSet(charactersIn: "aeiou")
    static let consonants = CharacterSet.letters.subtracting(.vowels)
}

func findVowelsConsonantsPunctuation(_ sentence: String) -> (vowels: Int, consonants: Int, punctuation: Int) {
    //Let's ignore diacritics
    let str = sentence.folding(options: .diacriticInsensitive, locale: .current)

    //The counters
    var vowels = 0, consonants = 0, punctuation = 0

    for character in str {
        let charSet = CharacterSet(charactersIn: String(character))

        //Consonants
        if CharacterSet.consonants.isSuperset(of: charSet) {
            consonants += 1
        }

        //Vowels
        else if CharacterSet.vowels.isSuperset(of: charSet) {
            vowels += 1
        }

        //Anything other than letters is considered as punctuation
        else {
            punctuation += 1
        }
    }

    return (vowels, consonants, punctuation)
}

Here are some examples:

findVowelsConsonantsPunctuation("Hellö world! ")  //(vowels 3, consonants 7, punctuation 4)
findVowelsConsonantsPunctuation("H311o")            //(vowels 1, consonants 1, punctuation 3)

A Swift way of writing the above function would be:

func findVowelsConsonantsPunctuation(_ sentence: String) -> (consonants: Int, vowels: Int, punctuation: Int) {
    let str = sentence.folding(options: .diacriticInsensitive, locale: .current)
    return str.reduce((0, 0, 0)) { tuple, character in
        let charSet = CharacterSet(charactersIn: String(character))
        if CharacterSet.consonants.isSuperset(of: charSet) {
            return (tuple.0 + 1, tuple.1, tuple.2)
        }
        else if CharacterSet.vowels.isSuperset(of: charSet) {
            return (tuple.0, tuple.1 + 1, tuple.2)
        }
        else {
            return (tuple.0, tuple.1, tuple.2 + 1)
        }
    }
}

I've switched the order of vowels and consonants in the return value since it is more probable to find a consonant than a vowel, which means the first if condition will be true more often than the others.

ielyamani
  • 17,807
  • 10
  • 55
  • 90