Skip to content

Commit fc1c4e3

Browse files
susmith98svedirecclauss
authored andcommitted
Added a function that checks if given string can be rearranged to form a palindrome. (TheAlgorithms#2450)
* Added check_if_string_can_be_rearranged_as_palindrome function. * Added counter implementation and benchmark function. * flake changes * Update and rename check_if_string_can_be_converted_to_palindrome.py to can_string_be_rearranged_as_palindrome.py * Update can_string_be_rearranged_as_palindrome.py * # Co-authored-by: svedire <[email protected]> Co-authored-by: Christian Clauss <[email protected]>
1 parent 32c5c08 commit fc1c4e3

File tree

1 file changed

+113
-0
lines changed

1 file changed

+113
-0
lines changed

Diff for: strings/can_string_be_rearranged_as_palindrome.py

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# Created by susmith98
2+
3+
from collections import Counter
4+
from timeit import timeit
5+
6+
# Problem Description:
7+
# Check if characters of the given string can be rearranged to form a palindrome.
8+
# Counter is faster for long strings and non-Counter is faster for short strings.
9+
10+
11+
def can_string_be_rearranged_as_palindrome_counter(input_str: str = "",) -> bool:
12+
"""
13+
A Palindrome is a String that reads the same forward as it does backwards.
14+
Examples of Palindromes mom, dad, malayalam
15+
>>> can_string_be_rearranged_as_palindrome_counter("Momo")
16+
True
17+
>>> can_string_be_rearranged_as_palindrome_counter("Mother")
18+
False
19+
>>> can_string_be_rearranged_as_palindrome_counter("Father")
20+
False
21+
>>> can_string_be_rearranged_as_palindrome_counter("A man a plan a canal Panama")
22+
True
23+
"""
24+
return sum(c % 2 for c in Counter(input_str.replace(" ", "").lower()).values()) < 2
25+
26+
27+
def can_string_be_rearranged_as_palindrome(input_str: str = "") -> bool:
28+
"""
29+
A Palindrome is a String that reads the same forward as it does backwards.
30+
Examples of Palindromes mom, dad, malayalam
31+
>>> can_string_be_rearranged_as_palindrome("Momo")
32+
True
33+
>>> can_string_be_rearranged_as_palindrome("Mother")
34+
False
35+
>>> can_string_be_rearranged_as_palindrome("Father")
36+
False
37+
>>> can_string_be_rearranged_as_palindrome_counter("A man a plan a canal Panama")
38+
True
39+
"""
40+
if len(input_str) == 0:
41+
return True
42+
lower_case_input_str = input_str.replace(" ", "").lower()
43+
# character_freq_dict: Stores the frequency of every character in the input string
44+
character_freq_dict = {}
45+
46+
for character in lower_case_input_str:
47+
character_freq_dict[character] = character_freq_dict.get(character, 0) + 1
48+
"""
49+
Above line of code is equivalent to:
50+
1) Getting the frequency of current character till previous index
51+
>>> character_freq = character_freq_dict.get(character, 0)
52+
2) Incrementing the frequency of current character by 1
53+
>>> character_freq = character_freq + 1
54+
3) Updating the frequency of current character
55+
>>> character_freq_dict[character] = character_freq
56+
"""
57+
"""
58+
OBSERVATIONS:
59+
Even length palindrome
60+
-> Every character appears even no.of times.
61+
Odd length palindrome
62+
-> Every character appears even no.of times except for one character.
63+
LOGIC:
64+
Step 1: We'll count number of characters that appear odd number of times i.e oddChar
65+
Step 2:If we find more than 1 character that appears odd number of times,
66+
It is not possible to rearrange as a palindrome
67+
"""
68+
oddChar = 0
69+
70+
for character_count in character_freq_dict.values():
71+
if character_count % 2:
72+
oddChar += 1
73+
if oddChar > 1:
74+
return False
75+
return True
76+
77+
78+
def benchmark(input_str: str = "") -> None:
79+
"""
80+
Benchmark code for comparing above 2 functions
81+
"""
82+
print("\nFor string = ", input_str, ":")
83+
print(
84+
"> can_string_be_rearranged_as_palindrome_counter()",
85+
"\tans =",
86+
can_string_be_rearranged_as_palindrome_counter(input_str),
87+
"\ttime =",
88+
timeit(
89+
"z.can_string_be_rearranged_as_palindrome_counter(z.check_str)",
90+
setup="import __main__ as z",
91+
),
92+
"seconds",
93+
)
94+
print(
95+
"> can_string_be_rearranged_as_palindrome()",
96+
"\tans =",
97+
can_string_be_rearranged_as_palindrome(input_str),
98+
"\ttime =",
99+
timeit(
100+
"z.can_string_be_rearranged_as_palindrome(z.check_str)",
101+
setup="import __main__ as z",
102+
),
103+
"seconds",
104+
)
105+
106+
107+
if __name__ == "__main__":
108+
check_str = input(
109+
"Enter string to determine if it can be rearranged as a palindrome or not: "
110+
).strip()
111+
benchmark(check_str)
112+
status = can_string_be_rearranged_as_palindrome_counter(check_str)
113+
print(f"{check_str} can {'' if status else 'not '}be rearranged as a palindrome")

0 commit comments

Comments
 (0)