7
7
"""
8
8
import unittest
9
9
import itertools as it
10
+ import collections
11
+ from typing import Callable
12
+
13
+
14
+ def is_permutation_of_palindrome (word : str ) -> bool :
15
+ """
16
+ Checks if a word is a palindrome by analyzing the frequencies of characters.
17
+ A palindrome is a word or phrase that is the same forwards and backwards.
18
+ When determining character frequencies, word will be put to lowercase
19
+ and spaces will not be counted
20
+ A palindrome also has the following property:
21
+ * all characters have an even count or all except one are even
22
+ Runtime: O(n)
23
+ Space Complexity: O(n)
24
+ :param word: the word we check, 'word' is a possible permutation of a palindrome
25
+ :return: true if word is a permutation of a palindrome, false otherwise
26
+ """
27
+ char_frequencies = collections .Counter (word .lower ().replace (' ' , '' ))
28
+ num_odd_freq_chars = 0
29
+ num_even_freq_chars = 0
30
+
31
+ for key , val in char_frequencies .items ():
32
+ if num_odd_freq_chars > 1 :
33
+ return False
34
+ if val % 2 == 0 :
35
+ num_even_freq_chars += 1
36
+ else :
37
+ num_odd_freq_chars += 1
38
+ return True
10
39
11
40
12
41
def _is_palindrome (word : str ) -> bool :
13
42
"""
14
- Checks if word is a palindrome.
43
+ Checks if word is a palindrome by checking if the forward version is the same as the backward version .
15
44
A palindrome is a word or phrase that is the same forwards and backwards.
16
45
Whitespace will not be considered when determining palindrome.
17
46
This function is case insensitive.
18
- :param word: the word we check
47
+ :param word: the word we check, possible permutation of a palindrome
19
48
:return: true if word is a palindrome, false otherwise
20
49
"""
21
50
word_no_spaces = word .replace (' ' , '' ).lower ()
22
51
reversed_word = word_no_spaces [::- 1 ]
23
52
return word_no_spaces == reversed_word
24
53
25
54
26
- def is_permutation_of_palindrome (word : str ) -> bool :
55
+ def is_permutation_of_palindrome_brute_force (word : str ) -> bool :
27
56
"""
28
57
Given a string, this function will return whether the string is a permutation of a palindrome.
29
58
A palindrome is a word or phrase that is the same forwards and backwards.
@@ -49,19 +78,23 @@ def is_permutation_of_palindrome(word: str) -> bool:
49
78
50
79
51
80
class TestIsPermutationOfPalindromeFunction (unittest .TestCase ):
52
- def test_is_permutation_of_palindrome (self ) :
81
+ def _run_tests (self , f : Callable [[ str ], bool ]) -> None :
53
82
cases = [
54
83
("Tact Coa" , True ),
55
84
("car race" , True ),
56
85
("ppilffli" , True ),
57
86
("gwas" , False ),
58
- ("sldkjflksd " , False ),
87
+ ("sldkjflks " , False ),
59
88
(" " , True ),
60
89
("" , True ),
61
90
("a" , True )
62
91
]
63
92
for word , expected in cases :
64
- self .assertEqual (is_permutation_of_palindrome (word ), expected , msg = word )
93
+ self .assertEqual (f (word ), expected , msg = word )
94
+
95
+ def test_is_permutation_of_palindrome (self ):
96
+ self ._run_tests (is_permutation_of_palindrome_brute_force )
97
+ self ._run_tests (is_permutation_of_palindrome )
65
98
66
99
def test_is_palindrome (self ):
67
100
cases = [
@@ -72,7 +105,9 @@ def test_is_palindrome(self):
72
105
("miguel" , False ),
73
106
(" " , True ),
74
107
("" , True ),
75
- ("a" , True )
108
+ ("a" , True ),
109
+ ("Tacoo Cat" , True ),
110
+ ("Tacooo Cat" , True )
76
111
]
77
112
for word , expected in cases :
78
113
self .assertEqual (_is_palindrome (word ), expected , msg = word )
0 commit comments