Solution to problem 2 in Python

This commit is contained in:
David Doblas Jiménez 2022-02-16 16:45:23 +01:00
parent c78882e46f
commit c0c65bb040

119
src/Year_2018/P2.py Normal file
View File

@ -0,0 +1,119 @@
# --- Day 2: Inventory Management System ---
# You stop falling through time, catch your breath, and check the screen on the
# device. "Destination reached. Current Year: 1518. Current Location: North
# Pole Utility Closet 83N10." You made it! Now, to find those anomalies.
# Outside the utility closet, you hear footsteps and a voice. "...I'm not sure
# either. But now that so many people have chimneys, maybe he could sneak in
# that way?" Another voice responds, "Actually, we've been working on a new
# kind of suit that would let him fit through tight spaces like that. But, I
# heard that a few days ago, they lost the prototype fabric, the design plans,
# everything! Nobody on the team can even seem to remember important details of
# the project!"
# "Wouldn't they have had enough fabric to fill several boxes in the warehouse?
# They'd be stored together, so the box IDs should be similar. Too bad it would
# take forever to search the warehouse for two similar box IDs..." They walk
# too far away to hear any more.
# Late at night, you sneak to the warehouse - who knows what kinds of paradoxes
# you could cause if you were discovered - and use your fancy wrist device to
# quickly scan every box and produce a list of the likely candidates (your
# puzzle input).
# To make sure you didn't miss any, you scan the likely candidate boxes again,
# counting the number that have an ID containing exactly two of any letter and
# then separately counting those with exactly three of any letter. You can
# multiply those two counts together to get a rudimentary checksum and compare
# it to what your device predicts.
# For example, if you see the following box IDs:
# abcdef contains no letters that appear exactly two or three times.
# bababc contains two a and three b, so it counts for both.
# abbcde contains two b, but no letter appears exactly three times.
# abcccd contains three c, but no letter appears exactly two times.
# aabcdd contains two a and two d, but it only counts once.
# abcdee contains two e.
# ababab contains three a and three b, but it only counts once.
# Of these box IDs, four of them contain a letter which appears exactly twice,
# and three of them contain a letter which appears exactly three times.
# Multiplying these together produces a checksum of 4 * 3 = 12.
# What is the checksum for your list of box IDs?
from itertools import combinations
from typing import Dict
with open("files/P2.txt") as f:
IDs = [line for line in f.read().strip().split()]
def part_1() -> None:
twice, three_times = 0, 0
for word in IDs:
twice_added, three_times_added = False, False
while not twice_added and not three_times_added:
for letter in word:
counts = word.count(letter)
if counts == 2 and not twice_added:
twice += 1
twice_added = True
elif counts == 3 and not three_times_added:
three_times += 1
three_times_added = True
print(f"The checksum for my list is {twice*three_times}")
# --- Part Two ---
# Confident that your list of box IDs is complete, you're ready to find the
# boxes full of prototype fabric.
# The boxes will have IDs which differ by exactly one character at the same
# position in both strings. For example, given the following box IDs:
# abcde
# fghij
# klmno
# pqrst
# fguij
# axcye
# wvxyz
# The IDs abcde and axcye are close, but they differ by two characters (the
# second and fourth). However, the IDs fghij and fguij differ by exactly one
# character, the third (h and u). Those must be the correct boxes.
# What letters are common between the two correct box IDs? (In the example
# above, this is found by removing the differing character from either ID,
# producing fgij.)
def part_2() -> None:
# each entry has word as key and a dict of all letters as value
dict_IDs: Dict[str, Dict[int, str]] = {}
for word in IDs:
dict_IDs[word] = {}
for pos, letter in enumerate(word):
dict_IDs[word][pos] = letter
# create combinations of two values for later comparison
pairs = list(combinations(dict_IDs.values(), 2))
for d1, d2 in pairs:
set1 = set(d1.items())
set2 = set(d2.items())
# only one letter on each set is different
if len(set1 ^ set2) == 2:
# remove extra letter from first set
d1.pop(list(set1 ^ set2)[1][0])
print(f"Common letters are {''.join(d1.values())}")
if __name__ == "__main__":
part_1()
part_2()