Solution to problem 5 in Python

This commit is contained in:
David Doblas Jiménez 2022-02-28 21:33:53 +01:00
parent 5bb0f51743
commit e467b686d7

123
src/Year_2015/P5.py Normal file
View File

@ -0,0 +1,123 @@
# --- Day 5: Doesn't He Have Intern-Elves For This? ---
# Santa needs help figuring out which strings in his text file are naughty or
# nice.
# A nice string is one with all of the following properties:
# It contains at least three vowels (aeiou only), like aei, xazegov, or
# aeiouaeiouaeiou.
# It contains at least one letter that appears twice in a row, like xx,
# abcdde (dd), or aabbccdd (aa, bb, cc, or dd).
# It does not contain the strings ab, cd, pq, or xy, even if they are part
# of one of the other requirements.
# For example:
# ugknbfddgicrmopn is nice because it has at least three vowels
# (u...i...o...), a double letter (...dd...), and none of the disallowed
# substrings.
# aaa is nice because it has at least three vowels and a double letter,
# even though the letters used by different rules overlap.
# jchzalrnumimnmhp is naughty because it has no double letter.
# haegwjzuvuyypxyu is naughty because it contains the string xy.
# dvszwmarrgswjxmb is naughty because it contains only one vowel.
# How many strings are nice?
from collections import Counter
with open("files/P5.txt") as f:
strings = [line for line in f.read().strip().split()]
def has_enough_vowels(s: str) -> bool:
num_vowels = sum(s.lower().count(v) for v in "aeiou")
if num_vowels >= 3:
return True
return False
def has_double_letter(s: str) -> bool:
double_letters = sum(1 for i, j in zip(s, s[1:]) if i == j)
if double_letters >= 1:
return True
return False
def has_substring(s: str) -> bool:
substrings = ["ab", "cd", "pq", "xy"]
for substring in substrings:
if substring in s:
return True
return False
def part_1() -> None:
nice = 0
for string in strings:
if (
has_enough_vowels(string)
and has_double_letter(string)
and not has_substring(string)
):
nice += 1
print(f"There are {nice} nice strings")
# --- Part Two ---
# Realizing the error of his ways, Santa has switched to a better model of
# determining whether a string is naughty or nice. None of the old rules apply,
# as they are all clearly ridiculous.
# Now, a nice string is one with all of the following properties:
# It contains a pair of any two letters that appears at least twice in the
# string without overlapping, like xyxy (xy) or aabcdefgaa (aa), but not like
# aaa (aa, but it overlaps).
# It contains at least one letter which repeats with exactly one letter
# between them, like xyx, abcdefeghi (efe), or even aaa.
# For example:
# qjhvhtzxzqqjkmpb is nice because is has a pair that appears twice (qj)
# and a letter that repeats with exactly one letter between them (zxz).
# xxyxx is nice because it has a pair that appears twice and a letter that
# repeats with one between, even though the letters used by each rule overlap.
# uurcxstgmygtbstg is naughty because it has a pair (tg) but no repeat with
# a single letter between them.
# ieodomkazucvgmuy is naughty because it has a repeating letter with one
# between (odo), but no pair that appears twice.
# How many strings are nice under these new rules?
def has_pairs(s: str) -> bool:
for i in range(len(s) - 3):
_str = s[i : i + 2]
if _str in s[i + 2 :]:
return True
return False
def has_letter_between(s: str) -> bool:
_my_str = zip(s, s[1:], s[2:])
for triple in _my_str:
if triple[0] == triple[-1]:
return True
return False
def part_2() -> None:
nice = 0
for string in strings:
if has_pairs(string) and has_letter_between(string):
nice += 1
print(f"There are {nice} nicer strings")
if __name__ == "__main__":
part_1()
part_2()