Skip to content
60 changes: 60 additions & 0 deletions puzzles/solutions/2022/d03/p1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import sys

# Lowercase item types are numbered 1 through 26, uppercase item types are numbered 27 through 52.
LOWERCASE_ITEM_TYPE_PRIORITY_ASCII_DIFFERENCE = ord("a") - 1
UPPERCASE_ITEM_TYPE_PRIORITY_ASCII_DIFFERENCE = ord("A") - 27


def get_rucksacks_compartments(
input_text: str,
) -> list[tuple[set, set]]:
"""
:param input_text: puzzle input
:return: list of (first compartment set, second compartment set) couples
"""
return [
(
set(rucksack[: len(rucksack) // 2]),
set(rucksack[len(rucksack) // 2 :]),
)
for rucksack in input_text.splitlines()
]


def get_shared_item_type(first_compartment: set, second_compartment: set) -> str:
"""
:param first_compartment: counter of item types in the first compartment
:param second_compartment: counter of item types in the second compartment
:return: shared item type between the two compartments
"""
return (first_compartment & second_compartment).pop()


def get_item_type_priority(item_type: str) -> int:
"""
:param item_type: item type
:return: priority of the item type
"""
difference = (
LOWERCASE_ITEM_TYPE_PRIORITY_ASCII_DIFFERENCE
if item_type.islower()
else UPPERCASE_ITEM_TYPE_PRIORITY_ASCII_DIFFERENCE
)
return ord(item_type) - difference


def get_answer(input_text: str):
"""Return the sum of the priorities of shared item types in all the rucksacks."""
rucksacks_compartments = get_rucksacks_compartments(input_text)
shared_items = "".join(
get_shared_item_type(first_compartment, second_compartment)
for first_compartment, second_compartment in rucksacks_compartments
)
return sum(map(get_item_type_priority, shared_items))


if __name__ == "__main__":
try:
print(get_answer(sys.argv[1]))
except IndexError:
pass # Don't crash if no input was passed through command line arguments.
43 changes: 43 additions & 0 deletions puzzles/solutions/2022/d03/p2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import functools
import sys

import p1


GROUP_SIZE = 3


def get_group_rucksacks(input_text: str) -> list[list[str]]:
"""
:param input_text: puzzle input
:return: list of combined rucksacks in a group
"""
rucksacks = input_text.splitlines()
groups = []
for rucksack_number in range(0, len(rucksacks), GROUP_SIZE):
group_rucksacks = rucksacks[rucksack_number : rucksack_number + GROUP_SIZE]
groups.append(group_rucksacks)
return groups


def get_group_badge(group_rucksacks: list[str]) -> str:
"""
:param group_rucksacks: list of rucksacks of the group
:return: group badge, which is the item type which is common between all rucksacks
"""
group_rucksacks = map(set, group_rucksacks)
return tuple(functools.reduce(set.intersection, group_rucksacks))[0]


def get_answer(input_text: str):
"""Return the sum of the priorities of the item types that correspond to the badges of each three-Elf group."""
group_rucksacks = get_group_rucksacks(input_text)
badges = list(map(get_group_badge, group_rucksacks))
return sum((map(p1.get_item_type_priority, badges)))


if __name__ == "__main__":
try:
print(get_answer(sys.argv[1]))
except IndexError:
pass # Don't crash if no input was passed through command line arguments.