example = """
vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw
"""
packs_ex = example.split()day3
Each rucksack has two compartments. Items of a type should go into exactly one. Packing elf failed for exactly one item per rucksack.
Input: items now in each rucksack, 52 types a-zA-Z. First half in compartment 1, second in 2.
Read on.
Example:
Suppose we have the following list of 6 pack contents:
We can get their lengths:
lengths = [len(x) for x in packs_ex]
lengths[24, 32, 18, 30, 16, 24]
Each pack is evenly divided into two comparments:
Code
def get_compartments(packs: list[str] # List of pack contents like ['vJrwpWtw', ...]
) -> list[tuple]: # Split each pack like ('vJrw', 'pWtw')
"""Split each pack down the middle."""
lengths = [len(x) for x in packs]
return [(pack[:lengths[i]//2], pack[lengths[i]//2:])
for i, pack in enumerate(packs)]
get_compartments(packs_ex)[('vJrwpWtwJgWr', 'hcsFMMfFFhFp'),
('jqHRNqRjqzjGDLGL', 'rsFMfFZSrLrFZsSL'),
('PmmdzqPrV', 'vPwwTWBwg'),
('wMqvLMZHhHMvwLH', 'jbvcjnnSBnvTQFn'),
('ttgJtRGJ', 'QctTZtZT'),
('CrZsJsPPZsGz', 'wwsLwLmpwMDw')]
get_compartments
get_compartments (packs:list[str])
Split each pack down the middle.
| Type | Details | |
|---|---|---|
| packs | list | List of pack contents like [‘vJrwpWtw’, …] |
| Returns | list | Split each pack like (‘vJrw’, ‘pWtw’) |
Note each pack has precisely one item that is in both compartments:
Code
def get_shared(compartments: list[tuple] # ('vJrw','pWtw')
) -> list[str]: # Single char like 'w' here.
"""Find the shared item in each pack: same in both compartments."""
return [set(left).intersection(right).pop()
for left, right in compartments]
shared = get_shared(get_compartments(packs_ex))
shared['p', 'L', 'P', 'v', 't', 's']
priority
priority (char:str)
Return priority 1..52 of item in pack.
| Type | Details | |
|---|---|---|
| char | str | Single char like ‘w’ |
| Returns | int | Priority 1..52 |
Test that
assert [priority(x) for x in shared] == [16, 38, 42, 22, 20, 19]Part 1
Get the data
Decode both moves to R, P, S. Keep as a two-letter string like “RP”.
with open("../data/day3_input.txt") as f:
packs1 = [x.strip() for x in f.readlines()]
packs1[:5]['CjhshBJCSrTTsLwqwqwb',
'GtmnFHlDfcpHbLZjtTTRLWwb',
'fDfNHHjVFNvvrvVBJJdS',
'PPWvWQjPhrPQwlMWJJdMDGbJTdCJ',
'rsqsStgNNggBNBZHSrJGdJdCFRRZCFbGbTdJ']
Run
priorities = [priority(x) for x in
get_shared(get_compartments(packs1))]
sum(priorities)7766
Part 2
Elves are divided into “badged” groups of 3.
The “badge” is the only item type carried by all 3.
So in group B, all 3 elves have an item of type B. (Ok.) And at most two have any other item type. (Wait, what?)
Every set of 3 lines in your list is a badge group. In the example, the first 3 lines are group r and the second is Z.
We need to generalize get_shared(). Let’s try functools.reduce and define get_badge with that.
Find badge for a group
Code
from typing import Collection
from functools import reduce
def intersect(left: Collection, # Items in first group
right: Collection # Items in second group
) -> str: # Items common to both
"""Find set intersection btw two args."""
return set(left).intersection(right)
def get_badge(group: list[str] # List of item names
) -> str: # The single item common to all
"""Find common item. Assumes there is precisely 1."""
return reduce(intersect, group).pop()get_badge
get_badge (group:list[str])
Find common item. Assumes there is precisely 1.
| Type | Details | |
|---|---|---|
| group | list | List of item names |
| Returns | str | The single item common to all |
intersect
intersect (left:Collection, right:Collection)
Find set intersection btw two args.
| Type | Details | |
|---|---|---|
| left | Collection | Items in first group |
| right | Collection | Items in second group |
| Returns | str | Items common to both |
assert get_badge(packs_ex[:3]) == "r"
assert get_badge(packs_ex[3:6]) == "Z"Find groups from packlist
Code
def get_groups(packs: list[str] # List of all packs
) -> list[list]: # Divided into lists of 3
"""Split packlist into groups of 3"""
return [[packs[i], packs[i+1], packs[i+2]]
for i in range(0, len(packs), 3)]get_groups
get_groups (packs:list[str])
Split packlist into groups of 3
| Type | Details | |
|---|---|---|
| packs | list | List of all packs |
| Returns | list | Divided into lists of 3 |
get_groups(packs_ex)[['vJrwpWtwJgWrhcsFMMfFFhFp',
'jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL',
'PmmdzqPrVvPwwTWBwg'],
['wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn',
'ttgJtRGJQctTZtZT',
'CrZsJsPPZsGzwwsLwLmpwMDw']]
assert [get_badge(group)
for group in get_groups(packs_ex)] == ['r','Z']Run
badges = [get_badge(group)
for group in get_groups(packs1)]
sum([priority(x) for x in badges])2415