Skip to content

Instantly share code, notes, and snippets.

@swift-student
Last active February 19, 2020 19:35
Show Gist options
  • Save swift-student/4f52ca462e12811bdeff920b7a5b839c to your computer and use it in GitHub Desktop.
Save swift-student/4f52ca462e12811bdeff920b7a5b839c to your computer and use it in GitHub Desktop.

So to begin with, to test for a palindrome, I would start at the first and last character and work my way towards the middle comparing the characters. Once I reach halfway, if all the characters were the same, I know that the string is a palindrome.

However, I believe that the question is asking if any permutation of the string (rearranging the string in any way) can form a palindrome. I could rearrange the string into all possible permutations using recursion, however that would be more complicated than simply answering the question "can I make a palindrome from these characters".

To form a palindrome, all characters with the exception of one (the pivot at the middle in the case of an odd number of characters) must have an equal partner. So if I find more than one character that doesn't have an equal partner, my function would return false. Otherwise I can return true.

Also, one must consider the case of, well... case. If the characters are a mix of upper and lower case, should the function factor in case when looking for equal characters? I would argue no, especially considering phrases that may start with a capitalized word. So I would go ahead and make all my characters lower cased before going through my function.

Here is what I came up with for a function:

func canBePalindrome(string: String) -> Bool {
    var uniqueCharacters = 0
    var string = string.lowercased()
    
    while string.count > 0 {
        let characterToMatch = string.removeFirst()
        let matchIndex = string.firstIndex(of: characterToMatch)
        
        if let matchIndex = matchIndex {
            string.remove(at: matchIndex)
        } else {
            uniqueCharacters += 1
            if uniqueCharacters > 1 {
                return false
            }
        }
    }
    
    return true
}

canBePalindrome(string: "tacocat") // returns true
canBePalindrome(string: "A nut for a jar of tuna") // returns true
canBePalindrome(string: "aaiieennll") // returns true
canBePalindrome(string: "yyoouui") // returns true
canBePalindrome(string: "daily") // returns false
canBePalindrome(string: "Was it a car or a cat I saw") // returns true

Once I realized that the required task was to test if a string can be permutated into a palindrome, writing the function was rather simple. While the string still has characters to remove, I take one out, look for a match and if there is none, increment my unique characters count. If the count goes over 1, the string can't be permutated into a palindrome and we return false. Otherwise, if we remove all the characters from the string, and the unique character count doesn't go over 1, the string can be permutated into a palindrome and we return true.

@SLEsserman
Copy link

This is beautiful, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment