Solution to problem 2 in Python
This commit is contained in:
parent
c78882e46f
commit
c0c65bb040
119
src/Year_2018/P2.py
Normal file
119
src/Year_2018/P2.py
Normal 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()
|
Loading…
Reference in New Issue
Block a user