Last active
December 27, 2023 18:14
-
-
Save comex/81ff10bf095db2d86a52a148c8b11d62 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# https://news.ycombinator.com/item?id=38782678 | |
import timeit, random, string, re | |
def is_palindrome_chatgpt_1(s): | |
# [written by ChatGPT] | |
# Convert the string to lowercase and remove non-alphanumeric characters | |
cleaned_string = ''.join(char.lower() for char in s if char.isalnum()) | |
# Compare the cleaned string with its reverse | |
return cleaned_string == cleaned_string[::-1] | |
def is_palindrome_chatgpt_1_noclean(s): | |
# [manually modified from is_palindrome_chatgpt_1 to remove the cleaning/lowercase step] | |
return s == s[::-1] | |
def is_palindrome_chatgpt_2(s): | |
# [written by ChatGPT, does not clean] | |
left, right = 0, len(s) - 1 | |
while left < right: | |
if s[left] != s[right]: | |
return False | |
left += 1 | |
right -= 1 | |
return True | |
NOT_LOWERCASE_ALNUM = re.compile('[^a-z0-9]') | |
def is_palindrome_fast(s): | |
# [written by hand] | |
s = NOT_LOWERCASE_ALNUM.sub('', s.lower()) | |
half_length = (len(s) + 1) // 2 | |
return s[:half_length] == s[:-half_length-1:-1] | |
def is_palindrome_fast_noclean(s): | |
# [modified from is_palindroem_fast to remove the cleaning/lowercase step] | |
half_length = (len(s) + 1) // 2 | |
return s[:half_length] == s[:-half_length-1:-1] | |
is_palindrome_funcs = [is_palindrome_chatgpt_1, is_palindrome_chatgpt_1_noclean, is_palindrome_chatgpt_2, is_palindrome_fast, is_palindrome_fast_noclean] | |
alnum = string.ascii_letters + string.digits | |
def random_alnum(length): | |
return ''.join(random.choice(alnum) for _ in range(length)) | |
def setup(): | |
test_inputs = [] | |
for length in range(2, 5000): | |
# add palindrome input | |
half = random_alnum(length // 2) | |
mid = random_alnum(1) if length % 2 == 1 else '' | |
full = half + mid + half[::-1] | |
assert len(full) == length | |
assert all(is_palindrome(full) for is_palindrome in is_palindrome_funcs) | |
test_inputs.append(full) | |
# add almost-palindrome input | |
possible_change_positions = list(range(length)) | |
if length % 2 == 1: | |
possible_change_positions.remove(length // 2) | |
change_pos = random.choice(possible_change_positions) | |
new_char = 'a' if full[change_pos] not in 'Aa' else 'b' | |
full = full[:change_pos] + new_char + full[change_pos + 1:] | |
assert len(full) == length | |
assert not any(is_palindrome(full) for is_palindrome in is_palindrome_funcs) | |
test_inputs.append(full) | |
return test_inputs | |
def go(): | |
test_inputs = setup() | |
for func in is_palindrome_funcs: | |
print(func, timeit.timeit(lambda: sum(func(inp) for inp in test_inputs), number=1)) | |
go() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment