Skip to content

Instantly share code, notes, and snippets.

@comex
Last active December 27, 2023 18:14
Show Gist options
  • Save comex/81ff10bf095db2d86a52a148c8b11d62 to your computer and use it in GitHub Desktop.
Save comex/81ff10bf095db2d86a52a148c8b11d62 to your computer and use it in GitHub Desktop.
# 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