= """
example vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw
"""
= example.split() packs_ex
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:
= [len(x) for x in packs_ex]
lengths 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."""
= [len(x) for x in packs]
lengths 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]
= get_shared(get_compartments(packs_ex))
shared 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:
= [x.strip() for x in f.readlines()]
packs1 5] packs1[:
['CjhshBJCSrTTsLwqwqwb',
'GtmnFHlDfcpHbLZjtTTRLWwb',
'fDfNHHjVFNvvrvVBJJdS',
'PPWvWQjPhrPQwlMWJJdMDGbJTdCJ',
'rsqsStgNNggBNBZHSrJGdJdCFRRZCFbGbTdJ']
Run
= [priority(x) for x in
priorities
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
# Items in second group
right: Collection -> 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
= [get_badge(group)
badges for group in get_groups(packs1)]
sum([priority(x) for x in badges])
2415