Welcome to another installment in my Advent of Code 2020 series, where I present my solutions to this year’s Advent of Code challenges!
In this installment, I share my Python solution to Day 8 of Advent of Code, titled Handheld Halting.
Spoiler alert!
Please be warned: If you want to try solving the challenge on your own and without any help, stop reading now! The remainder of this post will be all about my solution to both parts of the Day 8 challenge.
The Day 8 challenge, part one
The challenge
Here’s the text from part one of the challenge:
Your flight to the major airline hub reaches cruising altitude without incident. While you consider checking the in-flight menu for one of those drinks that come with a little umbrella, you are interrupted by the kid sitting next to you.
Their handheld game console won’t turn on! They ask if you can take a look.
You narrow the problem down to a strange infinite loop in the boot code (your puzzle input) of the device. You should be able to fix it, but first you need to be able to run the code in isolation.
The boot code is represented as a text file with one instruction per line of text. Each instruction consists of an operation (
acc
,jmp
, ornop
) and an argument (a signed number like+4
or-20
).
acc
increases or decreases a single global value called the accumulator by the value given in the argument. For example,acc +7
would increase the accumulator by 7. The accumulator starts at0
. After anacc
instruction, the instruction immediately below it is executed next.jmp
jumps to a new instruction relative to itself. The next instruction to execute is found using the argument as an offset from thejmp
instruction; for example,jmp +2
would skip the next instruction,jmp +1
would continue to the instruction immediately below it, andjmp -20
would cause the instruction 20 lines above to be executed next.nop
stands for No OPeration – it does nothing. The instruction immediately below it is executed next.For example, consider the following program:
nop +0 acc +1 jmp +4 acc +3 jmp -3 acc -99 acc +1 jmp -4 acc +6
These instructions are visited in this order:
nop +0 | 1 acc +1 | 2, 8(!) jmp +4 | 3 acc +3 | 6 jmp -3 | 7 acc -99 | acc +1 | 4 jmp -4 | 5 acc +6 |
First, the
nop +0
does nothing. Then, the accumulator is increased from 0 to 1 (acc +1
) andjmp +4
sets the next instruction to the otheracc +1
near the bottom. After it increases the accumulator from 1 to 2,jmp -4
executes, setting the next instruction to the onlyacc +3
. It sets the accumulator to 5, andjmp -3
causes the program to continue back at the firstacc +1
.This is an infinite loop: with this sequence of jumps, the program will run forever. The moment the program tries to run any instruction a second time, you know it will never terminate.
Immediately before the program would run an instruction a second time, the value in the accumulator is
5
.Run your copy of the boot code. Immediately before any instruction is executed a second time, what value is in the accumulator?
Importing the data
Every Advent of Code participant gets their own set of data. I copied my data and went through my usual process of bringing it into a Jupyter Notebook running a Python kernel.
This involves pasting it into a triple-quoted string and then assigning its value to the variable main_raw_input
:
main_raw_input = """acc +37 acc -4 nop +405 jmp +276 acc +39 acc +40 acc -3 jmp +231 acc +44 acc +12 jmp +505 acc +35 jmp +282 acc +23 jmp +598 nop +392 acc +18 acc +44 acc +18 jmp +297 nop +460 jmp +152 nop +541 acc +33 jmp -11 acc -5 acc +9 jmp +327 acc +30 acc -1 acc -3 jmp +50 acc +22 acc +18 acc +33 acc +37 jmp +57 acc -17 acc -6 acc -2 jmp +535 acc -15 jmp +279 acc +34 acc +44 acc +41 jmp +349 acc +2 acc +6 nop +351 nop +252 jmp +505 jmp +1 jmp +1 nop +61 jmp +524 nop +351 jmp +399 acc +1 nop +397 acc +39 nop +141 jmp +134 acc +46 acc +14 acc +26 jmp +236 acc +7 acc -6 acc +35 jmp +397 acc +15 jmp +140 acc +3 acc -4 acc +37 acc +12 jmp +86 jmp +416 jmp +1 jmp +55 acc -19 jmp +536 jmp +1 acc -11 acc +15 jmp -61 acc +25 jmp -25 acc +50 acc +43 jmp +1 jmp +140 acc +46 nop -53 acc +1 nop +440 jmp +488 jmp +396 nop +443 acc +41 jmp +168 acc +25 nop +383 acc +12 acc -19 jmp +21 acc +29 acc +30 jmp +497 jmp +502 jmp +417 nop +351 acc -15 jmp +243 acc +21 acc +16 jmp +332 acc +28 acc +22 acc +38 jmp +476 acc +8 acc -11 jmp +458 acc +9 jmp +246 acc +40 acc +31 acc +26 jmp +218 acc +27 acc +9 nop +347 jmp +478 nop +28 nop +106 acc +25 acc -15 jmp +397 acc +31 jmp +231 acc -4 nop +136 acc +14 jmp +181 jmp +361 acc +16 acc +11 jmp -108 nop +299 acc +21 acc -2 jmp -106 jmp +246 acc +31 jmp +407 jmp +377 acc +43 acc -12 nop +142 acc +8 jmp -91 jmp +1 acc +34 acc +5 acc +31 jmp +12 acc +34 acc +7 acc +34 acc +20 jmp -45 acc -11 acc +41 acc +10 jmp +310 nop -106 jmp -36 acc +23 acc +46 acc +46 jmp +112 acc +41 nop +179 acc +17 nop +356 jmp +147 acc +42 nop +49 jmp +119 acc +0 acc +7 acc -18 acc -8 jmp +11 acc +12 acc +38 acc +39 jmp +281 nop +186 jmp +162 acc +44 acc +20 jmp +153 jmp +395 acc +49 jmp +1 acc +2 jmp +1 jmp -31 jmp +301 nop +97 jmp -102 jmp +262 acc +28 acc -15 acc +44 acc -13 jmp +191 jmp +281 acc +36 acc +1 nop +15 jmp +211 acc +6 acc -4 jmp +42 acc +34 acc +0 jmp +104 jmp +311 jmp +84 acc +43 acc -8 acc -10 acc +38 jmp -90 acc +49 jmp +303 nop +132 jmp +301 nop +60 acc +37 nop +96 jmp +182 acc +16 acc +18 nop +152 acc +19 jmp +325 jmp -63 acc +28 jmp +56 acc +18 acc +29 acc +33 jmp -115 acc +47 acc +19 jmp +1 nop +41 jmp +1 jmp -207 nop -62 acc -9 acc +42 acc -12 jmp -56 acc +28 jmp -163 acc +25 acc +17 jmp -217 acc +7 jmp +272 acc +43 acc +22 jmp +70 acc -17 jmp -117 acc +24 acc +26 nop -275 jmp -46 nop +87 acc +19 acc +28 jmp -34 acc +4 acc +9 acc +6 jmp +1 jmp +28 acc -6 nop -67 acc -10 jmp +271 acc +40 acc +25 acc -4 jmp -63 acc +46 jmp +78 acc +41 nop -126 nop +70 jmp +1 jmp +172 nop +270 jmp +30 jmp +1 acc +38 nop +68 acc +29 jmp +253 acc -18 jmp -89 acc +18 acc +30 jmp +147 acc +24 acc +11 acc +50 jmp -225 jmp -210 acc -18 acc +1 acc +38 jmp +1 jmp -79 acc +45 acc +12 jmp +209 jmp -207 acc +32 acc +4 acc +32 acc +14 jmp +83 acc +13 acc +1 acc +46 acc +38 jmp +28 nop +153 acc -17 jmp -73 acc +11 jmp +248 acc +29 acc +45 acc +16 jmp +96 jmp -273 acc +34 jmp +87 nop +99 acc -3 jmp -74 acc +12 nop -119 jmp -141 acc -18 nop -79 acc +1 acc +6 jmp +9 acc +3 acc +44 acc +39 jmp -165 acc +6 jmp +44 acc +25 jmp -133 acc +0 jmp +14 jmp +1 acc +1 jmp -223 jmp +71 nop -1 acc +22 acc +11 jmp -274 jmp -330 acc +45 jmp +1 acc +15 jmp -158 jmp -128 acc +50 acc +26 jmp -73 nop +99 jmp +71 acc +35 acc +7 jmp +192 acc +13 jmp +190 acc +4 acc -1 acc +40 acc -15 jmp +50 acc +29 jmp -337 jmp -75 acc +41 jmp +1 jmp -387 acc +28 acc +18 acc +19 jmp -62 nop -196 jmp -410 jmp +1 acc -17 jmp -267 acc +22 jmp -301 nop -98 acc -15 jmp -124 acc +45 acc -18 acc +15 acc +42 jmp -296 nop -10 acc +29 jmp -371 acc +3 jmp +1 nop +61 acc +5 jmp -361 acc -5 nop -326 jmp -379 acc -10 jmp +1 acc +44 jmp -231 acc +3 jmp -94 acc +1 jmp +113 jmp -336 acc +4 jmp -299 acc -13 jmp +1 acc +13 jmp +143 acc -11 acc -19 acc +18 nop -390 jmp -27 acc +42 jmp -232 acc +15 jmp -228 acc +21 acc +39 acc +47 acc +6 jmp +57 acc +28 acc +27 acc +50 jmp -397 acc +12 jmp -445 acc +30 jmp -352 acc -4 acc +26 acc +48 jmp +1 jmp -205 jmp +22 nop -284 acc -1 nop -361 acc +0 jmp -368 acc -17 nop -223 jmp -41 acc +4 acc +46 jmp +79 jmp -370 jmp -260 acc +42 jmp -14 acc +30 acc +50 acc +13 jmp -61 acc +46 jmp -63 nop -55 nop -320 jmp -11 acc +10 jmp -424 jmp -11 acc +3 jmp -71 acc +42 acc -13 jmp +4 nop -155 nop -138 jmp +62 acc +11 acc +19 acc +15 acc +17 jmp -73 acc -11 jmp -273 acc +8 acc +6 acc -7 acc +41 jmp -311 jmp -111 jmp -260 jmp +50 jmp -60 jmp +1 nop -89 acc +36 acc +14 jmp -220 nop -415 acc +28 jmp -402 acc +41 jmp -165 acc +9 acc -13 acc -18 acc +18 jmp -504 acc -9 acc +29 acc +44 jmp -444 acc +5 acc +47 jmp -545 acc +23 acc +7 nop -240 jmp -320 jmp -141 jmp +1 acc +28 nop -287 jmp -118 acc +44 acc -7 jmp -550 acc +10 acc +20 acc -3 jmp -401 acc +45 acc +36 jmp -375 jmp -485 acc +9 jmp -338 jmp -510 jmp -196 acc -16 jmp -372 acc +0 jmp -380 acc -3 nop -473 nop -361 jmp -311 acc +0 nop +20 jmp -436 acc +9 jmp +1 jmp -215 acc +19 jmp -451 jmp -43 acc -13 acc -10 acc -5 jmp -208 acc -11 jmp -156 acc +11 acc -2 nop -357 jmp -73 acc +21 jmp -159 acc +28 acc -16 acc +12 acc +1 jmp -282 jmp -131 acc -11 acc +45 acc +0 acc +28 jmp +1"""
Building the data structure
With the data imported, the next step was to build an appropriate data structure. Since today’s puzzle was based on simplified microprocessor instructions, I thought that the data structure should do the same.
I wanted my data structure to look like the table below, which shows the instructions from extracted from the first five lines of the data given to me:
Index | Opcode | Operand |
---|---|---|
0 | acc | 37 |
1 | acc | -4 |
2 | nop | 405 |
3 | jmp | 276 |
4 | acc | 39 |
Here’s the function that I wrote to convert the input data into the data structure:
def input_to_instructions(input_data): instructions = [] split_input = input_data.splitlines() for item in split_input: instruction = {} opcode_operand = item.split() instruction["opcode"] = opcode_operand[0] instruction["operand"] = int(opcode_operand[1]) instructions.append(instruction) return instructions
With the function defined, here’s how I used it to create the data structure, which I assigned to a variable named instructions
:
>>> instructions = input_to_instructions(main_raw_input) >>> print (instructions) [{'opcode': 'acc', 'operand': 37}, {'opcode': 'acc', 'operand': -4}, {'opcode': 'nop', 'operand': 405}, {'opcode': 'jmp', 'operand': 276}, {'opcode': 'acc', 'operand': 39}, ... ]
I then wrote accumulator_value_at_first_repeat()
, the function that would use the data structure contained within instructions
to solve the first challenge:
def accumulator_value_at_first_repeat(instructions): program_length = len(instructions) program_counter = 0 accumulator = 0 executed_instructions = set() repeat_instruction_encountered = False while 0 <= program_counter < program_length: current_instruction = instructions[program_counter] if program_counter in executed_instructions: repeat_instruction_encountered = True break else: executed_instructions.add(program_counter) if current_instruction["opcode"] == "jmp": program_counter += current_instruction["operand"] continue elif current_instruction["opcode"] == "acc": accumulator += current_instruction["operand"] elif current_instruction["opcode"] == "nop": pass else: print("Something went wrong in accumulator_value_at_first_repeated_instruction().") print(f"pc = {program_counter} acc = {accumulator}") print(f"instruction:\n{instruction}") program_counter += 1 if repeat_instruction_encountered: print(f"The accumulator's contents at the first repeated instruction is: {accumulator}.") else: print("Reached end of instructions without repeating any of them.")
When run, it sets up the following variables:
program_length
: The number of instructions in the data structure.program_counter
: The program’s equivalent of the “program counter (PC)” register in a microprocessor; contains the index the instruction to be executed.accumulator
: The program’s equivalent of an accumulator in a microprocessor. For those of you who aren’t familiar with what happens at the microprocessor level, think of the accumulator as a “scratchpad” variable where you do all the math.executed_instructions
: A set (which means that every value in it is unique) of the indices of all the instructions that have already been executed. We use it to determine if a given instruction has already been run, at which point we should stop the program and see what the value in the accumulator is.repeat_instruction_encountered
: A flag that should be set toTrue
when an instruction is about to be executed a second time.
The function’s main loop performs a greatly simplified version of a microprocessor’s “fetch-decode-execute” cycle:
- Fetch the current instruction, which is the one whose index is specified by
program_counter
. - See if the instruction has been executed before. If this is the case, exit the loop; otherwise, recording this instruction as having been executed.
- Decode the current instruction:
- If the instruction is jmp, add the operand value to
program_counter
and go back to the start of the loop. - If the instruction is acc, add the operand value to
accumulator
. - If the instruction is nop, do nothing.
- If the instruction is anything else, display an error message.
- If the instruction is jmp, add the operand value to
- After the loop is done, if the
repeat_instruction_encountered
flag is set, we’ve found the value we’re looking for — display it! Otherwise, display a message saying that we’ve reached the end of the instructions without ever repeating one.
I ran the function…
>>> accumulator_value_at_first_repeat(instructions) The accumulator's contents at the first repeated instruction is: 1801.
…and got my result: 1801.
The Day 8 challenge, part two
The challenge
After some careful analysis, you believe that exactly one instruction is corrupted.
Somewhere in the program, either a
jmp
is supposed to be anop
, or anop
is supposed to be ajmp
. (Noacc
instructions were harmed in the corruption of this boot code.)The program is supposed to terminate by attempting to execute an instruction immediately after the last instruction in the file. By changing exactly one
jmp
ornop
, you can repair the boot code and make it terminate correctly.For example, consider the same program from above:
nop +0 acc +1 jmp +4 acc +3 jmp -3 acc -99 acc +1 jmp -4 acc +6
If you change the first instruction from
nop +0
tojmp +0
, it would create a single-instruction infinite loop, never leaving that instruction. If you change almost any of thejmp
instructions, the program will still eventually find anotherjmp
instruction and loop forever.However, if you change the second-to-last instruction (from
jmp -4
tonop -4
), the program terminates! The instructions are visited in this order:nop +0 | 1 acc +1 | 2 jmp +4 | 3 acc +3 | jmp -3 | acc -99 | acc +1 | 4 nop -4 | 5 acc +6 | 6
After the last instruction (
acc +6
), the program terminates by attempting to run the instruction below the last instruction in the file. With this change, after the program terminates, the accumulator contains the value8
(acc +1
,acc +1
,acc +6
).Fix the program so that it terminates normally by changing exactly one
jmp
(tonop
) ornop
(tojmp
). What is the value of the accumulator after the program terminates?
Here’s the function I wrote to solve this challenge:
def accumulator_value_and_halt_at_first_repeat(instructions, switch_opcode_address=-1): program_length = len(instructions) program_counter = 0 accumulator = 0 executed_instructions = set() while 0 <= program_counter < program_length: current_instruction = instructions[program_counter] if program_counter in executed_instructions: return { "halted": False, "program_counter": program_counter, "accumulator": accumulator } else: executed_instructions.add(program_counter) opcode = current_instruction["opcode"] operand = current_instruction["operand"] if program_counter == switch_opcode_address: print(f"Changing opcode at address {program_counter}") if opcode == "jmp": print("- Changing jmp to nop") opcode = "nop" elif opcode == "nop": print("- Changing nop to jmp") opcode = "jmp" if opcode == "jmp": program_counter += operand continue elif opcode == "acc": accumulator += operand elif opcode == "nop": pass else: print("Something went wrong in accumulator_value_at_first_repeated_instruction().") print(f"pc = {program_counter} acc = {accumulator}") print(f"instruction:\n{instruction}") program_counter += 1 return { "halted": True, "program_counter": program_counter, "accumulator": accumulator }
The function, accumulator_value_and_halt_at_first_repeat()
, is an expanded version of the function from part one, accumulator_value_at_first_repeat()
.
In addition to a set of instructions, it takes an additional parameter: the address of an instruction that should be changed — either from jmp to nop, or from nop to jmp.
The function still performs the “fetch-decode-execute” loop, and it exits the loop if it’s about to execute an instruction that’s already been executed. The main difference is that if the current instruction is the one flagged for change, it changes the instruction appropriately.
I wrote the accumulator_value_and_halt_at_first_repeat()
function to be used by the function below:
def run_instructions_with_mods(program): for index in range(len(program)): instruction = program[index] if instruction["opcode"] != "acc": print(f"Found jmp or nop at address: {index}") result = accumulator_value_and_halt_at_first_repeat(program, index) if result["halted"]: print(f"Found it! {result}") break else: print(f"Not the correct instruction.")
This function goes through all the instructions in the set, looking for any jmp or nop instructions. When it finds one, it runs the program using accumulator_value_and_halt_at_first_repeat()
, marking the jmp or nop instruction as the one to be changed.
This lets us modify the program, one jmp or nop instruction at a time, in order to find which change to a jmp or nop instruction is the one that allows the program to reach the end of the instructions.
Here’s an abridged version of what happened when I ran the function:
>>> run_instructions_with_mods(instructions) Found jmp or nop at address: 2 Changing opcode at address 2 - Changing nop to jmp Not the correct instruction. Found jmp or nop at address: 3 Changing opcode at address 3 - Changing jmp to nop Not the correct instruction. Found jmp or nop at address: 7 Not the correct instruction. Found jmp or nop at address: 10 Changing opcode at address 10 - Changing jmp to nop Not the correct instruction. ... Found jmp or nop at address: 207 Changing opcode at address 207 - Changing jmp to nop Not the correct instruction. Found jmp or nop at address: 209 Changing opcode at address 209 - Changing jmp to nop Not the correct instruction. Found jmp or nop at address: 210 Changing opcode at address 210 - Changing jmp to nop Found it! {'halted': True, 'program_counter': 623, 'accumulator': 2060}
I entered 2060 as my answer, and step two was complete.
Solutions for other days in Advent of Code 2020
Welcome to another installment in my Advent of Code 2020 series, where I present my solutions to this year’s Advent of Code challenges!
In this installment, I share my Python solution to Day 7 of Advent of Code, titled Handy Haversacks.
The Day 7 challenge, part one
The challenge
Here’s the text from part one of the challenge:
You land at the regional airport in time for your next flight. In fact, it looks like you’ll even have time to grab some food: all flights are currently delayed due to issues in luggage processing.
Due to recent aviation regulations, many rules (your puzzle input) are being enforced about bags and their contents; bags must be color-coded and must contain specific quantities of other color-coded bags. Apparently, nobody responsible for these regulations considered how long they would take to enforce!
For example, consider the following rules:
light red bags contain 1 bright white bag, 2 muted yellow bags. dark orange bags contain 3 bright white bags, 4 muted yellow bags. bright white bags contain 1 shiny gold bag. muted yellow bags contain 2 shiny gold bags, 9 faded blue bags. shiny gold bags contain 1 dark olive bag, 2 vibrant plum bags. dark olive bags contain 3 faded blue bags, 4 dotted black bags. vibrant plum bags contain 5 faded blue bags, 6 dotted black bags. faded blue bags contain no other bags. dotted black bags contain no other bags.
These rules specify the required contents for 9 bag types. In this example, every
faded blue
bag is empty, everyvibrant plum
bag contains 11 bags (5faded blue
and 6dotted black
), and so on.You have a
shiny gold
bag. If you wanted to carry it in at least one other bag, how many different bag colors would be valid for the outermost bag? (In other words: how many colors can, eventually, contain at least oneshiny gold
bag?)In the above rules, the following options would be available to you:
- A
bright white
bag, which can hold yourshiny gold
bag directly.- A
muted yellow
bag, which can hold yourshiny gold
bag directly, plus some other bags.- A
dark orange
bag, which can holdbright white
andmuted yellow
bags, either of which could then hold yourshiny gold
bag.- A
light red
bag, which can holdbright white
andmuted yellow
bags, either of which could then hold yourshiny gold
bag.So, in this example, the number of bag colors that can eventually contain at least one
shiny gold
bag is4
.How many bag colors can eventually contain at least one
shiny gold
bag? (The list of rules is quite long; make sure you get all of it.)
Spoiler alert!
Please be warned: If you want to try solving the challenge on your own and without any help, stop reading now! The remainder of this post will be all about my solution to both parts of the Day 7 challenge.
Importing the data
Every Advent of Code participant gets their own set of data. I copied my data and went through my usual process of bringing it into a Jupyter Notebook running a Python kernel.
This involves pasting it into a triple-quoted string and then using Python’s splitlines()
method to break it up into a list of strings. The result is main_raw_input
:
main_raw_input = """light plum bags contain 1 faded blue bag. muted salmon bags contain 4 faded lavender bags, 4 posh magenta bags. wavy gray bags contain 2 dotted teal bags. wavy tan bags contain 2 plaid aqua bags. wavy purple bags contain 1 drab white bag, 4 muted yellow bags, 2 wavy aqua bags. dull fuchsia bags contain 2 bright indigo bags, 3 plaid cyan bags, 1 light gold bag. striped plum bags contain 1 dull coral bag, 2 drab salmon bags. mirrored gold bags contain 2 faded tan bags, 1 dull aqua bag. dim blue bags contain 3 dotted gray bags, 2 mirrored turquoise bags. dark olive bags contain 2 bright cyan bags. dotted orange bags contain 2 pale lime bags. vibrant aqua bags contain 5 posh plum bags, 5 faded tomato bags, 5 shiny tomato bags, 1 mirrored orange bag. striped gray bags contain 5 drab tomato bags. light beige bags contain 1 drab aqua bag, 5 striped yellow bags, 5 bright indigo bags. dotted brown bags contain 5 dim tan bags, 1 dim violet bag, 2 dull turquoise bags, 3 dark olive bags. dark turquoise bags contain 1 light bronze bag. vibrant beige bags contain 3 wavy indigo bags, 5 striped gray bags. dotted plum bags contain 2 mirrored green bags, 2 dull crimson bags, 2 drab tan bags, 1 vibrant coral bag. dull indigo bags contain 2 vibrant gold bags, 1 dim chartreuse bag, 3 bright brown bags, 2 dim turquoise bags. wavy olive bags contain 2 dotted indigo bags, 4 vibrant beige bags, 1 dotted gray bag. posh olive bags contain 4 muted magenta bags, 5 dim cyan bags, 3 drab bronze bags, 2 pale lime bags. dotted silver bags contain 3 light brown bags. dim purple bags contain 5 clear lavender bags, 4 drab aqua bags, 1 mirrored bronze bag. wavy green bags contain 4 plaid white bags, 3 clear cyan bags, 1 striped gray bag, 4 clear coral bags. dark brown bags contain 4 light brown bags, 2 light magenta bags, 3 dotted gold bags. dark aqua bags contain 1 dull coral bag, 4 shiny coral bags, 3 vibrant crimson bags, 2 muted black bags. shiny gray bags contain 1 dark gray bag, 4 pale purple bags. posh brown bags contain 1 posh magenta bag, 5 wavy bronze bags, 5 posh yellow bags. clear turquoise bags contain 1 shiny tan bag, 1 muted salmon bag. dotted teal bags contain 5 bright tan bags, 5 vibrant crimson bags. drab coral bags contain 1 striped brown bag, 1 light lime bag, 1 faded green bag. dull plum bags contain 5 vibrant silver bags. bright orange bags contain 2 dark yellow bags, 4 mirrored silver bags, 4 mirrored cyan bags, 2 striped tomato bags. drab bronze bags contain 2 drab violet bags, 2 striped bronze bags. dim tan bags contain 1 shiny black bag, 5 posh aqua bags. clear indigo bags contain 4 clear tan bags, 5 vibrant silver bags, 2 striped orange bags, 2 dotted lavender bags. muted violet bags contain 4 mirrored white bags, 1 dim blue bag, 4 faded beige bags. posh aqua bags contain 4 striped fuchsia bags, 4 pale red bags, 5 muted coral bags. mirrored purple bags contain 5 dim beige bags, 5 shiny brown bags, 5 posh indigo bags, 3 clear turquoise bags. vibrant orange bags contain 1 dark turquoise bag, 1 dotted olive bag, 3 dull coral bags, 3 dark chartreuse bags. light tomato bags contain 4 mirrored lime bags, 3 pale beige bags, 4 clear magenta bags. drab indigo bags contain 5 mirrored blue bags, 1 dull salmon bag. bright red bags contain 3 pale gold bags, 5 dim fuchsia bags, 5 mirrored aqua bags, 4 shiny gold bags. clear silver bags contain 3 dotted brown bags, 3 dull olive bags. vibrant salmon bags contain 3 shiny tan bags, 4 dotted gray bags, 3 wavy violet bags, 5 light gray bags. vibrant tan bags contain 1 wavy purple bag, 2 bright plum bags, 3 dim turquoise bags. wavy maroon bags contain 4 striped fuchsia bags. mirrored red bags contain 3 vibrant coral bags, 2 dotted crimson bags, 3 striped orange bags, 2 clear olive bags. shiny tan bags contain 5 striped fuchsia bags, 4 drab chartreuse bags, 2 drab tomato bags, 5 muted crimson bags. dull black bags contain 2 shiny teal bags. shiny coral bags contain 4 posh blue bags, 1 dotted coral bag. mirrored blue bags contain 4 posh chartreuse bags. striped fuchsia bags contain 4 muted lime bags, 2 shiny crimson bags. shiny lavender bags contain 1 vibrant yellow bag, 1 clear turquoise bag. dark tomato bags contain 5 clear brown bags. shiny indigo bags contain 3 pale orange bags. posh fuchsia bags contain 2 vibrant blue bags, 5 striped black bags, 3 dim turquoise bags, 5 pale black bags. muted plum bags contain 5 dim turquoise bags, 1 posh fuchsia bag. posh tomato bags contain 1 faded yellow bag, 1 vibrant blue bag, 1 clear coral bag. dotted gold bags contain 3 dull tomato bags, 5 striped tomato bags, 5 wavy purple bags. striped lime bags contain 3 faded salmon bags, 1 plaid gold bag, 4 wavy aqua bags, 3 bright beige bags. posh violet bags contain 5 dim purple bags. mirrored chartreuse bags contain 1 dark bronze bag. posh purple bags contain 4 posh fuchsia bags, 4 posh magenta bags, 2 mirrored cyan bags. bright indigo bags contain 5 drab white bags, 1 posh tan bag. dark indigo bags contain 1 clear tan bag, 2 wavy teal bags. dark beige bags contain 1 bright olive bag, 5 posh purple bags. clear crimson bags contain 4 muted black bags, 4 posh purple bags, 1 striped black bag, 5 bright black bags. shiny green bags contain 2 dark orange bags, 2 bright silver bags, 3 dim orange bags. plaid crimson bags contain 5 muted cyan bags, 3 striped orange bags, 4 dull lavender bags, 5 wavy magenta bags. clear tomato bags contain 2 posh fuchsia bags, 2 dark orange bags, 3 pale black bags, 2 dull aqua bags. vibrant gold bags contain 1 faded brown bag. pale salmon bags contain 4 dull coral bags, 2 posh fuchsia bags, 2 plaid tan bags. light cyan bags contain 4 plaid magenta bags. dim teal bags contain 1 posh bronze bag, 4 mirrored green bags, 5 dull black bags, 1 clear gray bag. plaid lime bags contain 3 wavy orange bags, 5 pale blue bags, 1 plaid gold bag. light tan bags contain 4 faded crimson bags, 1 plaid fuchsia bag, 1 bright aqua bag, 2 dotted blue bags. shiny brown bags contain 3 mirrored bronze bags, 3 light coral bags. bright plum bags contain 3 posh gray bags, 3 faded brown bags, 3 plaid magenta bags. bright beige bags contain 5 dotted coral bags. drab tomato bags contain no other bags. pale beige bags contain 3 drab bronze bags. dotted aqua bags contain 5 plaid yellow bags. striped yellow bags contain 2 dull tan bags, 2 posh violet bags, 2 pale violet bags, 2 clear lavender bags. vibrant maroon bags contain 4 muted green bags, 1 muted cyan bag, 1 mirrored tomato bag. plaid green bags contain 2 dotted black bags. dotted indigo bags contain 5 mirrored tan bags, 3 dim yellow bags. vibrant coral bags contain 3 drab blue bags, 3 striped gray bags, 1 clear plum bag, 2 faded tomato bags. pale maroon bags contain 5 shiny black bags. posh black bags contain 2 posh green bags, 1 posh tomato bag, 4 dim gold bags, 5 wavy olive bags. wavy aqua bags contain 5 faded green bags, 4 pale lavender bags, 5 plaid aqua bags, 3 mirrored brown bags. clear green bags contain 3 pale lime bags. dim beige bags contain 4 vibrant beige bags, 3 dull aqua bags, 1 mirrored orange bag, 2 dim yellow bags. dim chartreuse bags contain 5 dark maroon bags, 1 dark crimson bag, 5 wavy teal bags, 3 clear aqua bags. bright turquoise bags contain 1 dim turquoise bag, 3 dull turquoise bags. bright magenta bags contain 2 striped fuchsia bags, 5 dim brown bags. light fuchsia bags contain 2 drab tomato bags, 5 dim chartreuse bags. vibrant magenta bags contain 2 pale red bags, 4 dim turquoise bags, 4 drab blue bags, 3 drab aqua bags. muted gold bags contain 3 pale gray bags, 4 dim salmon bags. vibrant violet bags contain 4 mirrored gray bags, 2 wavy aqua bags, 3 drab tan bags. wavy cyan bags contain 3 pale fuchsia bags, 1 mirrored tan bag, 2 dull blue bags, 2 dull cyan bags. light silver bags contain 2 faded brown bags, 3 mirrored white bags, 5 plaid maroon bags, 3 plaid plum bags. mirrored lavender bags contain 1 shiny tan bag, 2 dim turquoise bags, 1 shiny coral bag, 1 striped brown bag. dull teal bags contain 2 striped purple bags, 5 dark plum bags, 5 bright purple bags, 4 light bronze bags. light indigo bags contain no other bags. shiny silver bags contain 2 dim maroon bags. wavy brown bags contain 1 posh lavender bag, 2 dark bronze bags, 4 mirrored chartreuse bags. dull lavender bags contain 3 dull cyan bags, 1 drab lavender bag. posh gold bags contain 1 mirrored cyan bag, 5 bright salmon bags, 4 dotted orange bags. dim yellow bags contain no other bags. vibrant crimson bags contain 1 drab lavender bag, 4 wavy purple bags, 5 clear red bags, 4 posh gray bags. plaid gold bags contain 4 striped fuchsia bags, 5 drab tomato bags, 3 light indigo bags, 3 mirrored bronze bags. vibrant indigo bags contain 4 faded yellow bags, 4 clear salmon bags, 4 plaid lavender bags. dark crimson bags contain 1 posh fuchsia bag, 2 drab silver bags, 5 shiny coral bags. vibrant white bags contain 3 dim orange bags, 2 shiny tomato bags, 5 dark teal bags, 5 faded aqua bags. pale chartreuse bags contain 2 dim cyan bags, 2 faded red bags, 3 light yellow bags, 4 wavy yellow bags. drab chartreuse bags contain 2 pale black bags. drab gray bags contain 4 posh indigo bags, 3 muted maroon bags, 5 striped teal bags, 5 striped lime bags. dim tomato bags contain 4 plaid tan bags, 4 vibrant turquoise bags, 2 mirrored salmon bags, 2 dull magenta bags. plaid purple bags contain 3 posh blue bags. dark lavender bags contain 4 muted green bags, 2 dim crimson bags, 5 dull gray bags. bright maroon bags contain 5 drab tomato bags, 4 vibrant red bags, 5 light lime bags. striped chartreuse bags contain 5 striped black bags. dull salmon bags contain 3 drab lime bags, 5 wavy crimson bags. clear beige bags contain 4 dim orange bags. light orange bags contain 1 plaid gold bag, 5 shiny coral bags. faded red bags contain 3 bright tan bags. wavy violet bags contain 5 plaid chartreuse bags. dim violet bags contain 1 pale lavender bag. posh indigo bags contain 4 muted plum bags, 1 plaid cyan bag, 2 mirrored turquoise bags, 2 light teal bags. muted aqua bags contain 5 striped black bags, 4 wavy purple bags, 4 mirrored silver bags, 4 wavy bronze bags. faded gold bags contain 5 wavy indigo bags, 2 dark olive bags, 5 mirrored orange bags. bright teal bags contain 5 dotted coral bags, 4 clear lavender bags, 1 pale black bag, 5 light indigo bags. dotted green bags contain 3 dotted brown bags, 1 mirrored chartreuse bag, 5 vibrant gray bags, 2 mirrored tan bags. drab yellow bags contain 1 wavy maroon bag, 4 posh chartreuse bags. dull maroon bags contain 1 dotted blue bag, 4 pale chartreuse bags, 5 drab teal bags. clear black bags contain 3 pale magenta bags, 5 vibrant silver bags. dull orange bags contain 4 vibrant lime bags, 4 shiny gold bags, 4 light coral bags, 4 striped brown bags. clear violet bags contain 3 muted plum bags, 3 dim teal bags. muted bronze bags contain 5 mirrored salmon bags, 5 dim tan bags. plaid lavender bags contain 3 posh violet bags. muted brown bags contain 5 striped brown bags, 5 mirrored green bags, 2 light orange bags. clear chartreuse bags contain 2 muted lime bags. shiny chartreuse bags contain 1 wavy coral bag, 4 light salmon bags, 5 plaid cyan bags. clear tan bags contain 4 dotted black bags. dull tan bags contain 1 posh maroon bag, 1 dotted coral bag. wavy black bags contain 1 dull chartreuse bag, 3 drab plum bags. faded fuchsia bags contain 4 mirrored violet bags, 2 dim lavender bags. pale brown bags contain 1 dotted olive bag, 2 bright fuchsia bags. faded green bags contain 5 dim turquoise bags, 2 mirrored blue bags, 1 mirrored tan bag, 5 mirrored silver bags. clear brown bags contain 3 vibrant lime bags, 2 muted maroon bags, 3 dull coral bags, 3 faded plum bags. vibrant silver bags contain 2 clear coral bags, 1 muted yellow bag, 2 drab cyan bags, 4 mirrored orange bags. bright crimson bags contain 1 posh olive bag, 3 faded beige bags, 1 dim black bag, 1 shiny silver bag. dim gold bags contain 2 posh beige bags, 1 dull coral bag, 1 plaid aqua bag. drab white bags contain 1 dim yellow bag, 2 posh gray bags. dim indigo bags contain 3 shiny brown bags, 1 drab red bag, 2 pale aqua bags, 4 plaid lime bags. dull blue bags contain 2 pale fuchsia bags, 1 faded tomato bag, 4 plaid aqua bags. mirrored bronze bags contain 5 bright tan bags, 2 plaid magenta bags. vibrant turquoise bags contain 5 shiny brown bags, 2 vibrant beige bags, 2 dotted magenta bags, 3 dull lavender bags. dull turquoise bags contain 4 clear lavender bags, 3 striped gray bags, 3 posh gray bags. dim lavender bags contain 3 plaid lime bags, 4 mirrored red bags, 3 pale orange bags. clear lime bags contain 3 drab fuchsia bags, 3 plaid gray bags, 1 light beige bag, 3 muted violet bags. wavy fuchsia bags contain 3 bright gray bags, 1 faded purple bag, 4 posh purple bags, 4 light tan bags. plaid beige bags contain 2 drab bronze bags. faded beige bags contain 1 posh bronze bag, 3 mirrored bronze bags, 3 shiny black bags. posh blue bags contain 3 shiny gold bags, 2 shiny black bags. dull silver bags contain 2 wavy crimson bags, 5 faded black bags. pale fuchsia bags contain 5 dull black bags. bright green bags contain 3 bright black bags, 4 drab tan bags. mirrored violet bags contain 4 pale teal bags, 3 dotted crimson bags, 2 posh violet bags, 2 shiny silver bags. pale violet bags contain 4 posh magenta bags, 5 wavy crimson bags, 3 drab aqua bags. faded white bags contain 1 drab purple bag, 5 shiny chartreuse bags. faded tomato bags contain 2 bright teal bags. faded violet bags contain 2 plaid salmon bags. drab turquoise bags contain 1 mirrored green bag. mirrored silver bags contain 5 dull aqua bags, 1 dark orange bag, 3 pale red bags, 4 dim yellow bags. dotted violet bags contain 5 plaid chartreuse bags, 1 mirrored tan bag, 5 dotted lavender bags. plaid olive bags contain 1 mirrored cyan bag, 2 muted orange bags, 2 posh maroon bags. pale silver bags contain 3 dull lavender bags, 4 mirrored olive bags, 4 muted coral bags. mirrored coral bags contain 1 pale fuchsia bag, 1 dull turquoise bag. drab crimson bags contain 1 wavy purple bag, 1 wavy violet bag, 2 vibrant gold bags, 3 bright salmon bags. dull chartreuse bags contain 4 faded salmon bags, 3 light lime bags, 1 mirrored brown bag. bright purple bags contain 2 light cyan bags. dull brown bags contain 3 bright white bags. muted magenta bags contain 3 shiny gold bags, 4 muted plum bags, 5 pale lime bags, 2 light cyan bags. pale aqua bags contain 4 drab blue bags, 1 bright lavender bag. drab purple bags contain 2 mirrored bronze bags, 1 drab violet bag. dotted chartreuse bags contain 2 pale chartreuse bags, 5 clear beige bags. shiny purple bags contain 5 clear black bags. muted blue bags contain 4 dotted indigo bags. striped blue bags contain 4 vibrant beige bags, 3 plaid lime bags. dull gold bags contain 4 drab violet bags, 3 pale aqua bags, 3 mirrored cyan bags. plaid tan bags contain 5 shiny gold bags. mirrored brown bags contain 3 pale lime bags, 2 dull coral bags. mirrored white bags contain 5 muted black bags, 1 dark yellow bag, 4 drab blue bags, 4 clear bronze bags. pale yellow bags contain 4 clear tomato bags, 1 drab salmon bag, 1 plaid crimson bag. faded silver bags contain 5 dotted indigo bags, 3 posh chartreuse bags. mirrored orange bags contain 4 drab tomato bags. dotted lime bags contain 3 faded tomato bags, 4 vibrant beige bags, 5 posh chartreuse bags. muted coral bags contain 1 muted plum bag. bright tomato bags contain 1 posh red bag, 4 light red bags, 1 dotted fuchsia bag, 4 dull turquoise bags. plaid orange bags contain 4 shiny salmon bags, 4 muted tomato bags, 4 dull gold bags, 3 clear green bags. plaid teal bags contain 1 shiny black bag, 4 wavy purple bags, 3 dark plum bags, 4 pale silver bags. muted tan bags contain 5 faded salmon bags, 4 dotted magenta bags, 3 clear gold bags, 3 dotted tan bags. faded olive bags contain 1 clear lavender bag. muted olive bags contain 4 drab coral bags, 5 light yellow bags. posh salmon bags contain 3 dim turquoise bags, 1 vibrant purple bag, 2 bright maroon bags, 2 drab lime bags. dim crimson bags contain 5 dull white bags, 1 dim yellow bag, 5 dark green bags. light brown bags contain 1 drab tan bag. light bronze bags contain 2 vibrant silver bags, 1 muted plum bag, 3 drab blue bags, 5 dull yellow bags. faded lime bags contain 3 bright teal bags, 2 light aqua bags. clear gold bags contain 1 dim cyan bag, 3 striped brown bags. clear coral bags contain 4 mirrored bronze bags, 5 posh magenta bags, 5 striped purple bags. striped cyan bags contain 1 wavy violet bag, 4 drab yellow bags. bright coral bags contain 4 dotted lime bags, 3 striped chartreuse bags. faded bronze bags contain 1 vibrant beige bag, 4 dotted green bags, 4 dotted gold bags, 1 shiny turquoise bag. dark red bags contain 3 pale salmon bags, 5 bright green bags. posh cyan bags contain 3 plaid fuchsia bags. clear teal bags contain 5 plaid aqua bags, 1 posh tomato bag, 2 shiny olive bags, 4 shiny turquoise bags. dotted turquoise bags contain 5 dim blue bags, 5 bright teal bags, 2 dull coral bags. wavy silver bags contain 5 posh aqua bags. shiny cyan bags contain 5 clear crimson bags, 4 vibrant purple bags, 3 mirrored turquoise bags, 5 plaid aqua bags. mirrored beige bags contain 2 dim green bags, 1 dull teal bag. plaid turquoise bags contain 1 dark yellow bag. dim white bags contain 5 posh indigo bags, 4 bright cyan bags, 5 dim orange bags, 2 dim teal bags. faded tan bags contain 4 dim salmon bags, 2 plaid blue bags. faded yellow bags contain 1 posh gray bag, 4 dim beige bags. dull tomato bags contain 2 pale indigo bags, 2 striped bronze bags, 1 wavy maroon bag, 5 posh tomato bags. posh lavender bags contain 4 faded blue bags, 4 striped teal bags, 5 plaid chartreuse bags. mirrored magenta bags contain 2 dim magenta bags. drab violet bags contain 3 shiny black bags, 1 mirrored silver bag. pale coral bags contain 5 dim gold bags. clear red bags contain 4 muted maroon bags. dark yellow bags contain 5 striped black bags, 2 clear plum bags. dull coral bags contain 5 bright teal bags, 2 shiny black bags, 3 drab tomato bags, 4 dotted coral bags. dotted bronze bags contain 3 bright black bags, 3 dull orange bags, 3 mirrored indigo bags. dull green bags contain 4 clear teal bags, 5 muted silver bags, 2 pale blue bags, 2 light plum bags. wavy gold bags contain 5 pale red bags, 3 dim salmon bags, 2 striped orange bags, 4 bright beige bags. plaid aqua bags contain 4 pale black bags, 2 clear tomato bags, 1 faded beige bag. wavy tomato bags contain 5 posh turquoise bags. wavy white bags contain 2 dim maroon bags. dull beige bags contain 3 wavy brown bags. light olive bags contain 5 dim white bags, 4 dark fuchsia bags, 4 dull magenta bags, 5 light lavender bags. mirrored lime bags contain 5 vibrant coral bags. light black bags contain 2 dark salmon bags. bright gold bags contain 3 dark orange bags, 5 shiny black bags, 2 bright silver bags, 3 pale black bags. dull lime bags contain 2 posh bronze bags, 2 mirrored blue bags. posh chartreuse bags contain 3 light lime bags, 3 bright lavender bags, 3 posh fuchsia bags. clear orange bags contain 1 dull maroon bag, 1 faded yellow bag. striped red bags contain 2 dotted cyan bags, 3 dull silver bags, 2 light blue bags. pale turquoise bags contain 4 wavy silver bags, 3 dotted teal bags, 4 light green bags. wavy crimson bags contain 1 light cyan bag, 2 posh beige bags. light turquoise bags contain 1 dull orange bag. dotted coral bags contain 1 drab tomato bag, 5 dim yellow bags, 5 bright lavender bags. dotted tan bags contain 4 light coral bags, 4 dim cyan bags, 3 vibrant beige bags. drab blue bags contain 1 dim turquoise bag. pale white bags contain 3 clear olive bags, 2 clear coral bags, 5 dark olive bags, 2 wavy white bags. muted orange bags contain 2 dim gold bags. faded black bags contain 2 wavy aqua bags, 5 vibrant bronze bags, 5 mirrored blue bags. posh lime bags contain 2 dim salmon bags, 2 pale orange bags, 4 wavy maroon bags, 1 dim coral bag. wavy indigo bags contain 2 muted lime bags. faded orange bags contain 1 light green bag, 5 plaid turquoise bags, 4 posh turquoise bags. light blue bags contain 1 plaid fuchsia bag, 4 mirrored salmon bags, 1 muted chartreuse bag. light violet bags contain 3 dotted black bags, 3 posh black bags. posh bronze bags contain 3 striped purple bags, 5 posh purple bags, 2 plaid magenta bags, 3 dull aqua bags. shiny fuchsia bags contain 5 dim olive bags, 2 plaid silver bags, 1 dark cyan bag, 1 pale red bag. vibrant gray bags contain 2 drab blue bags. faded salmon bags contain 1 drab aqua bag, 1 mirrored blue bag. dark white bags contain 4 dim orange bags, 4 plaid magenta bags, 2 clear tomato bags. muted indigo bags contain 4 dotted violet bags. dull white bags contain 2 shiny cyan bags, 3 shiny orange bags. faded plum bags contain 3 dim cyan bags, 2 dark yellow bags. muted silver bags contain 2 drab red bags, 3 dark gray bags, 4 striped teal bags. wavy lavender bags contain 1 drab turquoise bag. striped beige bags contain 2 dim turquoise bags, 1 muted plum bag, 4 posh violet bags. dark gray bags contain 3 posh fuchsia bags, 2 striped brown bags. plaid yellow bags contain 3 vibrant red bags, 5 dark gold bags. dark violet bags contain 2 mirrored orange bags, 2 muted crimson bags, 1 pale white bag, 1 pale chartreuse bag. shiny maroon bags contain 4 dim tan bags. dotted fuchsia bags contain 4 bright lime bags, 3 dotted lime bags, 2 bright maroon bags, 5 drab yellow bags. light yellow bags contain 1 dotted coral bag, 1 bright lavender bag, 3 pale violet bags. shiny blue bags contain 1 shiny crimson bag. dotted black bags contain 4 muted aqua bags, 2 light lime bags, 3 posh turquoise bags, 1 light silver bag. pale purple bags contain 2 striped violet bags, 5 clear lavender bags. pale red bags contain 4 bright tan bags, 4 pale black bags, 4 mirrored cyan bags, 3 dotted coral bags. dim gray bags contain 3 dull cyan bags, 3 dotted purple bags, 2 shiny brown bags, 2 plaid tan bags. posh tan bags contain 2 light coral bags, 2 bright black bags, 2 dim yellow bags. vibrant black bags contain 4 pale crimson bags, 2 mirrored brown bags, 4 plaid violet bags, 3 muted yellow bags. dark salmon bags contain 2 mirrored brown bags, 5 clear salmon bags, 5 drab yellow bags. dim green bags contain 5 pale indigo bags, 5 pale coral bags, 5 plaid lavender bags. plaid fuchsia bags contain 2 muted maroon bags, 3 muted crimson bags, 3 dim black bags. faded maroon bags contain 3 mirrored purple bags, 5 faded tan bags. dark maroon bags contain 5 dull lavender bags, 4 clear plum bags, 3 shiny silver bags. pale magenta bags contain 1 light indigo bag. dim salmon bags contain 2 vibrant red bags, 1 light lime bag. dotted lavender bags contain 4 drab tan bags, 1 mirrored olive bag, 5 plaid gold bags. faded aqua bags contain 5 dim purple bags. plaid brown bags contain 2 shiny green bags, 3 faded tomato bags, 4 wavy orange bags. striped purple bags contain 4 posh gray bags, 1 light lime bag. muted yellow bags contain 2 pale indigo bags, 3 vibrant blue bags, 2 muted coral bags. dark gold bags contain 4 striped teal bags, 4 bright maroon bags. mirrored indigo bags contain 5 dim white bags, 4 wavy white bags, 4 bright purple bags. mirrored tomato bags contain 1 drab turquoise bag, 1 drab cyan bag, 1 dotted teal bag. striped white bags contain 1 shiny silver bag, 1 faded gold bag. pale plum bags contain 2 shiny brown bags, 1 posh fuchsia bag. bright gray bags contain 4 posh chartreuse bags, 4 dull turquoise bags. shiny olive bags contain 3 plaid yellow bags, 4 dotted fuchsia bags, 2 bright beige bags. faded crimson bags contain 4 faded blue bags, 5 faded gray bags, 1 dotted lime bag, 1 wavy magenta bag. striped coral bags contain 1 dull fuchsia bag, 4 striped fuchsia bags, 1 dull gold bag, 5 posh lime bags. posh orange bags contain 4 dim yellow bags, 2 posh tan bags. striped tan bags contain 5 vibrant coral bags, 5 posh violet bags, 4 plaid aqua bags, 4 dark crimson bags. shiny yellow bags contain 3 dull silver bags, 3 dim purple bags, 3 vibrant violet bags. shiny black bags contain 3 mirrored cyan bags, 1 clear gray bag, 2 light cyan bags. posh silver bags contain 1 posh blue bag. mirrored cyan bags contain 5 pale lime bags, 1 drab aqua bag, 4 muted lime bags. dark plum bags contain 3 muted green bags. clear white bags contain 5 wavy crimson bags, 3 plaid salmon bags, 4 plaid silver bags, 3 faded beige bags. plaid plum bags contain 2 dim salmon bags, 1 faded black bag, 2 plaid purple bags, 5 dull lavender bags. dim turquoise bags contain 2 pale indigo bags, 4 striped black bags. vibrant green bags contain 5 clear purple bags, 4 pale brown bags, 2 drab olive bags, 3 dotted brown bags. dark lime bags contain 4 dull blue bags, 4 wavy chartreuse bags, 1 bright olive bag. shiny white bags contain 2 muted magenta bags, 4 clear gray bags, 1 mirrored bronze bag, 3 mirrored green bags. dark orange bags contain 5 clear gray bags, 1 posh maroon bag, 1 vibrant blue bag. light crimson bags contain 2 drab tomato bags, 5 bright tan bags, 5 striped gray bags. clear yellow bags contain 2 muted salmon bags, 1 mirrored magenta bag. plaid salmon bags contain 3 drab tan bags, 4 dark yellow bags, 5 dim yellow bags. faded chartreuse bags contain 1 dull black bag, 5 pale lime bags, 2 wavy olive bags, 4 shiny green bags. plaid bronze bags contain 2 vibrant maroon bags. striped crimson bags contain 1 shiny beige bag. clear magenta bags contain 3 muted olive bags, 4 bright olive bags, 5 pale purple bags, 3 dark aqua bags. muted lime bags contain no other bags. dull yellow bags contain 3 dark black bags, 1 wavy orange bag, 5 posh fuchsia bags. shiny teal bags contain 5 posh bronze bags, 1 striped tomato bag, 2 dim gold bags, 2 posh chartreuse bags. plaid violet bags contain 5 mirrored bronze bags, 5 shiny crimson bags, 5 vibrant blue bags. posh coral bags contain 5 bright silver bags, 2 bright lime bags. dim magenta bags contain 5 drab white bags, 1 faded blue bag, 1 drab red bag, 5 light brown bags. muted turquoise bags contain 4 shiny beige bags. posh maroon bags contain 2 light lime bags. posh crimson bags contain 5 wavy lavender bags, 3 pale orange bags, 3 plaid magenta bags. striped black bags contain no other bags. drab teal bags contain 5 light olive bags, 3 clear teal bags, 2 posh magenta bags. plaid white bags contain 1 shiny tan bag, 3 dotted lavender bags, 5 wavy olive bags, 4 clear black bags. pale olive bags contain 4 vibrant beige bags. shiny tomato bags contain 5 pale lavender bags, 3 muted fuchsia bags, 5 drab white bags. dim coral bags contain 3 dotted fuchsia bags. faded blue bags contain 4 dim maroon bags, 3 vibrant blue bags, 4 clear gray bags. plaid maroon bags contain 3 dotted indigo bags, 1 mirrored olive bag. mirrored teal bags contain 3 dim olive bags, 5 posh white bags, 4 faded plum bags. mirrored olive bags contain 5 light indigo bags, 5 muted lime bags, 4 wavy indigo bags. drab aqua bags contain 4 drab tan bags, 2 striped gray bags, 1 pale lime bag. posh plum bags contain 5 dim magenta bags, 5 clear gray bags. dull olive bags contain 1 clear black bag, 3 dim brown bags. bright chartreuse bags contain 5 vibrant violet bags, 4 posh green bags, 5 pale coral bags. dull bronze bags contain 3 dark green bags. plaid silver bags contain 4 striped lavender bags, 3 mirrored orange bags, 5 muted coral bags. mirrored fuchsia bags contain 1 vibrant crimson bag. drab beige bags contain 4 light indigo bags, 1 shiny green bag. plaid chartreuse bags contain 2 dark bronze bags, 5 drab chartreuse bags. drab magenta bags contain 3 plaid chartreuse bags. pale black bags contain no other bags. dark fuchsia bags contain 1 dim yellow bag, 5 dim salmon bags. clear gray bags contain 3 bright tan bags. dark purple bags contain 4 plaid purple bags, 1 dark gold bag. bright tan bags contain no other bags. clear plum bags contain 1 posh blue bag, 4 bright teal bags. striped brown bags contain 5 clear tomato bags, 1 dotted indigo bag, 2 clear coral bags. drab silver bags contain 3 clear lavender bags, 3 shiny gold bags, 5 dotted coral bags, 5 wavy indigo bags. dotted purple bags contain 2 mirrored bronze bags, 4 light red bags, 4 dim teal bags, 3 muted indigo bags. dotted red bags contain 2 shiny brown bags, 2 dull tan bags, 3 wavy coral bags, 2 pale lime bags. posh magenta bags contain 3 clear gray bags. dim olive bags contain 4 muted cyan bags, 2 mirrored brown bags, 3 dim orange bags. dotted tomato bags contain 2 bright fuchsia bags, 5 dull silver bags, 2 dim lime bags. striped magenta bags contain 3 mirrored red bags, 1 muted magenta bag, 3 wavy white bags. posh red bags contain 3 bright orange bags, 4 clear olive bags, 5 faded violet bags, 3 plaid coral bags. muted crimson bags contain 5 light indigo bags. drab fuchsia bags contain 3 shiny coral bags. light lime bags contain 4 bright lavender bags, 2 light crimson bags, 5 vibrant blue bags. dotted yellow bags contain 4 pale fuchsia bags. bright lavender bags contain no other bags. dull aqua bags contain 4 posh gray bags, 2 light indigo bags, 5 light crimson bags. shiny aqua bags contain 2 pale orange bags, 3 drab gray bags. drab red bags contain 5 striped tomato bags. bright salmon bags contain 3 light indigo bags. faded turquoise bags contain 5 clear beige bags. shiny gold bags contain 1 mirrored bronze bag, 4 dull aqua bags, 2 dotted indigo bags, 1 light indigo bag. clear fuchsia bags contain 5 dotted indigo bags. dark bronze bags contain 4 shiny black bags. dotted olive bags contain 4 bright cyan bags. vibrant purple bags contain 3 striped gray bags. dull purple bags contain 5 wavy orange bags, 5 faded black bags, 2 plaid violet bags, 2 vibrant lavender bags. shiny lime bags contain 1 light purple bag. pale cyan bags contain 3 vibrant red bags, 5 dark white bags, 4 mirrored red bags, 3 vibrant brown bags. dark cyan bags contain 5 clear olive bags, 4 plaid purple bags, 5 striped teal bags, 3 bright magenta bags. dim lime bags contain 3 muted tomato bags. drab olive bags contain 1 dotted blue bag, 2 dull lavender bags. faded gray bags contain 5 mirrored tan bags, 1 muted orange bag, 3 posh purple bags. muted gray bags contain 5 pale white bags. mirrored yellow bags contain 5 bright black bags, 1 plaid turquoise bag. wavy lime bags contain 5 plaid bronze bags, 4 mirrored green bags, 5 pale lavender bags, 3 wavy tan bags. wavy orange bags contain 3 dotted lime bags, 1 dull crimson bag, 2 mirrored turquoise bags. dotted cyan bags contain 4 dotted lime bags, 2 striped teal bags. light green bags contain 3 muted indigo bags, 3 pale fuchsia bags. drab cyan bags contain 3 posh bronze bags, 5 drab white bags, 3 drab tomato bags, 1 light indigo bag. faded brown bags contain 3 bright tan bags, 4 striped gray bags, 5 drab cyan bags, 3 mirrored tan bags. light purple bags contain 3 pale aqua bags, 1 dim olive bag, 2 dim tan bags. vibrant lavender bags contain 2 faded lavender bags. vibrant brown bags contain 4 striped black bags, 1 faded yellow bag. dull crimson bags contain 2 mirrored white bags, 2 clear tomato bags. drab green bags contain 2 drab beige bags, 1 vibrant crimson bag, 2 vibrant purple bags, 1 faded black bag. shiny bronze bags contain 3 dark fuchsia bags, 3 dark bronze bags, 2 striped brown bags, 4 shiny brown bags. plaid blue bags contain 5 faded green bags. light white bags contain 3 wavy brown bags, 3 dark violet bags, 2 muted coral bags, 5 plaid chartreuse bags. bright violet bags contain 1 faded violet bag, 2 muted maroon bags, 3 posh gray bags, 2 dark salmon bags. striped turquoise bags contain 5 bright salmon bags, 1 bright lavender bag, 1 wavy maroon bag, 4 light turquoise bags. clear cyan bags contain 5 posh magenta bags, 4 striped plum bags, 5 light turquoise bags. bright silver bags contain 4 dotted indigo bags, 1 drab tomato bag, 1 muted salmon bag. mirrored plum bags contain 5 bright white bags, 1 vibrant brown bag. mirrored aqua bags contain 5 drab bronze bags, 3 mirrored salmon bags, 3 posh lavender bags, 3 bright crimson bags. muted lavender bags contain 4 posh bronze bags, 3 striped lime bags, 5 striped chartreuse bags, 5 plaid plum bags. dim orange bags contain 3 muted magenta bags, 2 pale magenta bags. faded teal bags contain 5 wavy coral bags, 3 posh blue bags. dotted magenta bags contain 5 faded purple bags, 5 posh fuchsia bags, 1 drab white bag. drab brown bags contain 4 light red bags, 4 muted chartreuse bags. striped indigo bags contain 3 light maroon bags, 2 pale gray bags, 2 faded magenta bags, 1 vibrant teal bag. dull gray bags contain 3 clear olive bags. clear blue bags contain 2 clear tomato bags, 4 faded purple bags, 1 wavy lavender bag. posh green bags contain 5 clear aqua bags, 4 bright orange bags, 2 bright cyan bags, 4 dim fuchsia bags. muted fuchsia bags contain 5 dull lavender bags, 2 drab violet bags, 4 dotted magenta bags, 2 wavy yellow bags. posh turquoise bags contain 2 dotted lavender bags. bright blue bags contain 1 pale lavender bag, 5 dark yellow bags, 5 bright beige bags. bright bronze bags contain 2 bright gold bags, 4 shiny turquoise bags. muted chartreuse bags contain 1 vibrant tomato bag, 1 bright lavender bag, 1 vibrant blue bag, 1 dim black bag. dim bronze bags contain 2 light lavender bags, 2 striped plum bags, 3 dotted gold bags. pale crimson bags contain 5 dotted lavender bags, 2 clear crimson bags, 4 bright lime bags. clear bronze bags contain 2 drab tomato bags, 3 vibrant red bags. pale lime bags contain 4 pale indigo bags, 3 striped black bags. light red bags contain 4 bright salmon bags, 1 bright gold bag. pale orange bags contain 5 drab blue bags. shiny crimson bags contain 3 light crimson bags. dotted beige bags contain 5 bright turquoise bags, 3 dotted turquoise bags, 4 muted green bags, 4 light black bags. light gray bags contain 4 faded green bags, 5 wavy gold bags, 4 dim olive bags. light coral bags contain 2 muted plum bags. light magenta bags contain 1 dim maroon bag, 5 clear chartreuse bags, 1 vibrant lavender bag, 2 plaid beige bags. striped violet bags contain 1 vibrant beige bag. bright aqua bags contain 1 dark crimson bag, 4 dark bronze bags. dotted maroon bags contain 5 light silver bags, 5 dark maroon bags. drab plum bags contain 1 dotted yellow bag, 1 bright green bag, 4 vibrant brown bags. posh gray bags contain 2 light crimson bags. dotted blue bags contain 2 posh tan bags. vibrant olive bags contain 3 faded yellow bags. posh white bags contain 1 faded tomato bag, 2 dim violet bags. drab lavender bags contain 3 light brown bags. dark blue bags contain 5 vibrant lavender bags, 4 posh plum bags, 5 pale violet bags, 1 pale beige bag. muted beige bags contain 1 striped lime bag, 2 clear purple bags, 1 vibrant brown bag, 2 mirrored bronze bags. dim maroon bags contain 5 dim beige bags, 1 dull coral bag. wavy teal bags contain 1 drab yellow bag, 2 muted magenta bags, 4 wavy gold bags, 2 vibrant cyan bags. shiny salmon bags contain 2 light red bags, 3 bright fuchsia bags. light salmon bags contain 3 vibrant purple bags, 3 drab blue bags, 3 faded black bags, 2 bright white bags. shiny magenta bags contain 5 light fuchsia bags, 3 drab indigo bags, 3 mirrored yellow bags, 4 dim purple bags. plaid black bags contain 3 light bronze bags, 4 mirrored tan bags, 4 muted lime bags, 5 mirrored white bags. wavy red bags contain 4 clear lavender bags, 4 dull chartreuse bags. posh beige bags contain 4 wavy maroon bags, 4 clear plum bags. wavy bronze bags contain 1 wavy purple bag. dotted gray bags contain 3 striped black bags, 1 wavy maroon bag, 5 pale indigo bags. bright white bags contain 3 pale indigo bags, 2 drab white bags. mirrored black bags contain 2 striped plum bags, 5 wavy brown bags, 1 wavy crimson bag. light gold bags contain 3 posh plum bags, 1 vibrant crimson bag. bright fuchsia bags contain 3 light cyan bags, 1 drab turquoise bag, 3 dim orange bags, 1 dull chartreuse bag. striped gold bags contain 3 muted violet bags, 2 clear teal bags, 2 posh brown bags, 3 dim tan bags. striped orange bags contain 1 pale fuchsia bag. drab gold bags contain 4 shiny teal bags, 5 muted aqua bags, 3 wavy lavender bags. light chartreuse bags contain 2 bright gold bags, 5 striped turquoise bags, 5 light gray bags, 3 wavy aqua bags. vibrant chartreuse bags contain 2 dotted yellow bags, 5 bright fuchsia bags, 1 striped chartreuse bag, 1 dim salmon bag. pale indigo bags contain no other bags. drab lime bags contain 2 mirrored turquoise bags. vibrant plum bags contain 3 dotted turquoise bags. pale teal bags contain 5 striped lime bags, 3 faded salmon bags, 4 bright indigo bags. dark tan bags contain 2 drab lavender bags. faded lavender bags contain 1 vibrant blue bag. drab orange bags contain 1 muted turquoise bag, 3 pale indigo bags. dim fuchsia bags contain 1 drab silver bag. vibrant lime bags contain 1 posh purple bag, 3 light coral bags, 3 light lime bags, 4 light indigo bags. clear salmon bags contain 2 light indigo bags, 2 striped plum bags. dark black bags contain 2 striped fuchsia bags, 4 wavy white bags, 2 wavy maroon bags. muted white bags contain 2 pale indigo bags, 5 light plum bags. pale gray bags contain 4 light yellow bags, 2 striped olive bags, 4 clear black bags. dull cyan bags contain 2 vibrant red bags, 3 drab tan bags. striped silver bags contain 3 mirrored green bags, 2 wavy purple bags, 3 posh aqua bags. wavy magenta bags contain 4 dim purple bags, 2 dark aqua bags. drab black bags contain 2 light plum bags. drab maroon bags contain 2 vibrant lime bags, 4 dull purple bags, 2 mirrored salmon bags, 3 vibrant aqua bags. shiny orange bags contain 5 wavy coral bags, 1 pale violet bag. plaid coral bags contain 2 mirrored cyan bags. plaid cyan bags contain 4 pale indigo bags. dotted crimson bags contain 2 dim teal bags. mirrored tan bags contain 1 pale red bag, 1 light cyan bag, 1 clear gray bag, 3 striped gray bags. light maroon bags contain 2 vibrant bronze bags. bright brown bags contain 2 wavy yellow bags. muted tomato bags contain 5 clear gold bags, 5 plaid coral bags. dotted white bags contain 4 dotted purple bags, 1 posh chartreuse bag, 5 dark gold bags, 1 vibrant gold bag. muted red bags contain 4 clear crimson bags, 4 posh magenta bags, 3 plaid cyan bags, 5 pale crimson bags. wavy yellow bags contain 3 muted magenta bags. muted purple bags contain 1 dull chartreuse bag. striped olive bags contain 5 faded tomato bags. light aqua bags contain 1 vibrant tomato bag, 4 posh lavender bags. vibrant blue bags contain 2 muted lime bags. pale lavender bags contain 4 shiny coral bags, 5 muted crimson bags. mirrored turquoise bags contain 5 posh blue bags. pale gold bags contain 3 plaid chartreuse bags, 2 pale red bags, 5 clear aqua bags. wavy salmon bags contain 4 dotted yellow bags. shiny beige bags contain 1 bright magenta bag, 1 muted fuchsia bag. striped bronze bags contain 5 bright turquoise bags, 5 dull black bags. dark magenta bags contain 5 drab lime bags. dark coral bags contain 3 plaid bronze bags, 3 posh green bags, 4 muted violet bags, 3 plaid purple bags. mirrored green bags contain 4 posh purple bags, 2 dotted blue bags, 1 dull turquoise bag, 2 plaid purple bags. striped tomato bags contain 5 drab white bags. muted teal bags contain 5 shiny lime bags. vibrant bronze bags contain 3 shiny gold bags, 5 striped fuchsia bags, 5 mirrored orange bags, 2 bright green bags. clear olive bags contain 3 posh violet bags, 1 bright beige bag. clear maroon bags contain 1 vibrant lime bag, 2 muted coral bags. faded coral bags contain 4 dim beige bags, 4 bright magenta bags, 3 vibrant magenta bags, 1 bright silver bag. pale bronze bags contain 1 dark teal bag, 4 dotted aqua bags. striped aqua bags contain 3 faded aqua bags. vibrant cyan bags contain 2 mirrored blue bags, 4 striped black bags, 4 clear black bags. wavy coral bags contain 4 drab salmon bags, 3 light orange bags, 3 posh aqua bags. mirrored salmon bags contain 4 pale lime bags. plaid magenta bags contain 1 dim yellow bag, 1 light indigo bag. dim brown bags contain 3 vibrant purple bags, 2 striped gray bags, 4 mirrored salmon bags, 2 muted maroon bags. dull magenta bags contain 1 mirrored green bag, 4 dull coral bags. dark silver bags contain 5 dotted gray bags. pale tomato bags contain 1 vibrant blue bag, 4 shiny green bags. plaid tomato bags contain 4 mirrored chartreuse bags, 1 plaid white bag, 4 wavy magenta bags. faded magenta bags contain 4 dull yellow bags, 3 wavy silver bags. mirrored crimson bags contain 3 muted tan bags, 5 posh beige bags. muted green bags contain 4 dim black bags. wavy chartreuse bags contain 1 plaid tan bag, 5 bright tan bags, 2 posh beige bags. wavy plum bags contain 2 clear purple bags, 5 dotted violet bags. plaid indigo bags contain 1 dull brown bag, 3 clear chartreuse bags, 5 posh gold bags, 1 pale teal bag. posh teal bags contain 3 light magenta bags, 3 muted white bags, 3 dim blue bags. striped salmon bags contain 4 shiny coral bags. pale green bags contain 4 dark gold bags, 4 striped teal bags. vibrant yellow bags contain 4 faded salmon bags, 1 drab beige bag, 1 muted black bag, 5 clear lavender bags. dim cyan bags contain 2 mirrored turquoise bags. wavy turquoise bags contain 4 dark turquoise bags, 3 bright tan bags, 4 muted tomato bags. bright cyan bags contain 5 wavy indigo bags. plaid red bags contain 1 mirrored coral bag, 2 dull plum bags, 4 vibrant coral bags, 4 vibrant lavender bags. dark chartreuse bags contain 5 mirrored salmon bags, 5 posh salmon bags, 2 faded turquoise bags. plaid gray bags contain 1 dim gold bag, 4 faded olive bags. vibrant tomato bags contain 5 wavy maroon bags, 1 pale red bag. faded purple bags contain 1 faded tomato bag, 1 striped black bag, 5 vibrant purple bags. dotted salmon bags contain 3 bright gold bags, 5 dull gray bags, 3 dim blue bags. drab salmon bags contain 3 mirrored green bags, 1 mirrored tan bag. pale blue bags contain 4 dotted fuchsia bags. faded cyan bags contain 2 striped orange bags, 1 vibrant gold bag, 2 bright orange bags, 1 muted gray bag. dull red bags contain 2 drab teal bags, 2 light bronze bags. wavy beige bags contain 1 plaid tan bag, 5 dotted indigo bags, 2 dotted gold bags. dim red bags contain 5 pale magenta bags. dark green bags contain 5 muted cyan bags, 3 faded brown bags. muted cyan bags contain 3 drab tomato bags, 4 drab white bags. mirrored maroon bags contain 5 wavy tomato bags, 2 vibrant white bags. faded indigo bags contain 5 dim olive bags, 5 drab tan bags, 3 light orange bags. light lavender bags contain 1 faded salmon bag, 5 pale lime bags, 4 dark maroon bags. dim aqua bags contain 4 faded gold bags, 1 striped fuchsia bag. shiny violet bags contain 1 pale yellow bag, 4 mirrored aqua bags. wavy blue bags contain 1 dim fuchsia bag, 3 clear gold bags, 1 faded aqua bag, 1 light red bag. striped teal bags contain 3 mirrored silver bags. striped green bags contain 1 muted teal bag. vibrant teal bags contain 3 muted indigo bags. shiny turquoise bags contain 3 dull chartreuse bags. bright lime bags contain 5 bright magenta bags, 1 dull orange bag. shiny red bags contain 4 drab tan bags, 4 posh turquoise bags. dull violet bags contain 4 shiny silver bags, 3 striped crimson bags, 1 mirrored plum bag. dim black bags contain 1 posh magenta bag, 3 mirrored turquoise bags, 2 faded tomato bags, 4 dim turquoise bags. muted maroon bags contain 2 mirrored tan bags, 3 clear coral bags. posh yellow bags contain 1 bright tan bag, 5 mirrored bronze bags. clear purple bags contain 5 shiny black bags. dim silver bags contain 4 clear brown bags. bright black bags contain 4 posh fuchsia bags. shiny plum bags contain 1 mirrored cyan bag. striped lavender bags contain 3 pale lavender bags, 4 muted cyan bags. drab tan bags contain no other bags. bright olive bags contain 3 muted coral bags. dim plum bags contain 3 drab tan bags, 5 pale indigo bags. light teal bags contain 2 dotted blue bags, 5 muted salmon bags, 2 bright purple bags. clear lavender bags contain 2 muted lime bags, 5 plaid magenta bags, 3 pale lime bags, 1 drab aqua bag. muted black bags contain 3 light crimson bags, 4 mirrored blue bags. clear aqua bags contain 5 plaid gold bags. dark teal bags contain 1 bright purple bag, 1 dotted coral bag, 5 plaid aqua bags, 5 posh maroon bags. mirrored gray bags contain 3 dim turquoise bags, 4 bright black bags, 1 drab lavender bag. vibrant fuchsia bags contain 1 vibrant magenta bag. bright yellow bags contain 1 mirrored cyan bag, 1 clear olive bag. vibrant red bags contain 1 dotted indigo bag, 2 faded beige bags, 1 drab tomato bag. striped maroon bags contain 3 plaid aqua bags, 2 dim maroon bags, 4 plaid chartreuse bags. pale tan bags contain 5 posh gray bags, 3 wavy violet bags.""" main_raw_input = main_raw_input.splitlines()
Creating the data structure
I feel that I can never stress this enough: A key part of coming up with solutions to Advent of Code challenges is to come up with good structures for the input data.
Here’s my function that takes the initial, somewhat-massaged input data, currently living in main_raw_input
, and turns it into a data structure that I could do some problem-solving with:
import re def create_data_structure(initial_data): result = {} for item in initial_data: bag_and_contents_regex = r"^(\w+ \w+) bags contain (.*)" bag_and_contents = re.search(bag_and_contents_regex, item) bag_type = bag_and_contents[1] contents_string = bag_and_contents[2][:-1] # [:-1] removes trailing period contents_regex = r"([0-9] )*(\w+ \w+) bag" contents_tuples = re.findall(contents_regex, contents_string) bag_contents = [] for contents_tuple in contents_tuples: if contents_tuple[1] != "no other": bag_contents.append({ "count": int(contents_tuple[0]), "type": contents_tuple[1] }) result[bag_type] = bag_contents return result
The create_data_structure()
function creates a table that makes it easy to look up a given bag and see what bags it contains.
It takes each line in the input, which follows this general form:
[adjective and color] bags contain [one or more of
([number][adjective and color]bag(s)).
It first makes use of this regular expression…
^(\w+ \w+) bags contain (.*)
…to separate the line into two parts:
- The containing bag, which is captured by the
(\w+ \w+)
group, and - The contained bag(s), which are captured by the
(.*)
group.
The contained bag(s) are further parsed using this regular expression…
([0-9] )*(\w+ \w+) bag
…to create a list of tuples of the form:
(number, adjective_and_color)
Here’s how I used create_data_structure()
to create the data structure:
bags = create_data_structure(main_raw_input)
Here’s a sample of the what the structure looked like for my data:
{ "light plum":[ { "count":1, "type":"faded blue" } ], "muted salmon":[ { "count":4, "type":"faded lavender" }, { "count":4, "type":"posh magenta" } ], "wavy gray":[ { "count":2, "type":"dotted teal" } ], "wavy tan":[ { "count":2, "type":"plaid aqua" } ], "wavy purple":[ { "count":1, "type":"drab white" }, { "count":4, "type":"muted yellow" }, { "count":2, "type":"wavy aqua" } ], "dull fuchsia":[ { "count":2, "type":"bright indigo" }, { "count":3, "type":"plaid cyan" }, { "count":1, "type":"light gold" } ] # ... and the rest of it is here ... }
With the data structure built, it was now possible to write a function to determine how many shiny gold bags a given bag would contain:
def shiny_gold_bag_count(bag_collection, bag_name): count = 0 bag = bag_collection[bag_name] if len(bag) == 0: return count else: for sub_bag in bag: if sub_bag["type"] == "shiny gold": count += 1 count += shiny_gold_bag_count(bag_collection, sub_bag["type"]) return count
It’s the return of our friend:
This function checks the contents of the given bag. If there are bags in the given bag, it checks the contents of those bags and counts the shiny gold ones. If there are bags in those bags, it checks the contents of those bags and counts the shiny gold ones. And so on…
Now that I had the shiny_gold_bag_count()
function, I could write another function — bags_containing_at_least_one_shiny_gold_bag()
— that would apply the shiny_gold_bag_count()
function to all the bags in the collection, giving me the answer to the part one:
def bags_containing_at_least_one_shiny_gold_bag(bag_collection): count = 0 for bag_name in bag_collection.keys(): if shiny_gold_bag_count(bag_collection, bag_name) > 0: print(f"{bag_name} bags contain at least one shiny gold bag!") count += 1 return count
In my case, the count was 326.
The Day 7 challenge, part two
The challenge
Here’s the text of part two:
It’s getting pretty expensive to fly these days – not because of ticket prices, but because of the ridiculous number of bags you need to buy!
Consider again your
shiny gold
bag and the rules from the above example:
faded blue
bags contain0
other bags.dotted black
bags contain0
other bags.vibrant plum
bags contain11
other bags: 5faded blue
bags and 6dotted black
bags.dark olive
bags contain7
other bags: 3faded blue
bags and 4dotted black
bags.So, a single
shiny gold
bag must contain 1dark olive
bag (and the 7 bags within it) plus 2vibrant plum
bags (and the 11 bags within each of those):1 + 1*7 + 2 + 2*11
=32
bags!Of course, the actual rules have a small chance of going several levels deeper than this example; be sure to count all of the bags, even if the nesting becomes topologically impractical!
Here’s another example:
shiny gold bags contain 2 dark red bags. dark red bags contain 2 dark orange bags. dark orange bags contain 2 dark yellow bags. dark yellow bags contain 2 dark green bags. dark green bags contain 2 dark blue bags. dark blue bags contain 2 dark violet bags. dark violet bags contain no other bags.
In this example, a single
shiny gold
bag must contain126
other bags.How many individual bags are required inside your single
shiny gold
bag?
My solution was the following function:
def bag_count(bag_collection, bag_name): count = 0 top_level_bag = bag_collection[bag_name] print(f"Currently counting bags inside {bag_name}.") if len(top_level_bag) == 0: return count else: for current_bag in top_level_bag: print(f"There are {current_bag['count']} of {current_bag['type']} inside {bag_name}.") # Add the number of bags of the current type # to the count. current_bag_type_count = current_bag['count'] count += current_bag_type_count # Count the bags inside each bag of the current type, # multiply it by the number of the current type, # then add it to the count. bags_inside_current_bag_type_count = bag_count(bag_collection, current_bag["type"]) count += bags_inside_current_bag_type_count * current_bag_type_count return count
Once again, my solution was a recursive one. This function checks the contents of the given bag. If there are bags in the given bag, it counts them and then checks their contents. If there are bags in those bags, it counts them and checks their contents. And so on…
Getting the solution was a matter of calling the function:
bag_count(bags, "shiny gold")
And for my data, the answer was 5635.
Solutions for previous days in Advent of Code 2020
Here’s your chance to get to know the Auth0 Developer Relations team — they’re holding an online meet-and-greet this Monday, December 14th at noon Eastern / 9:00 a.m. Pacific!
Here’s the description of the event:
Dev Rel, Developer Relations, Developer Advocacy, Developer avocado… What does it all mean? In this episode you will have the chance to connect and ask your questions about all of this to the very own Auth0 Dev Rel team. Maybe you just want to know what we do, or how we got here. Maybe you want to learn how to get into Dev Rel. Or maybe you just want to meet us and say hi! Whatever your reason, don’t miss this episode where we will also be hosting a secret santa live! Why? Well, that way you can also get to know us better by seeing what we would buy each other this season.
Here’s who you’ll meet…
James Quick, Senior Developer Advocate
James is a developer, speaker, and teacher with a passion for web development, design, and developer tools. He is a Senior Developer Advocate at Auth0 and has over 7 years of experience in Advocacy and Software Development. In his spare time, he runs a YouTube channel, plays co-ed soccer with his wife, spends time with his dogs, and can solve a Rubik’s cube in under two minutes.
Sam Bellen, Senior Developer Advocate
I’m a Google Developer Expert who works as a Senior Developer Advocate Engineer at Auth0. At Auth0 we’re trying to make authentication and identification as easy as possible, while still keeping it secure. After office hours I like to play around with the web-audio API, and other “exotic” browser APIs. One of my side projects is a library to add audio effects to an audio input using JavaScript.
Ana Cidre, Senior Developer Advocate
Ana is a Developer Advocate at Auth0. She has a degree in Fine Arts and a Master in International Business Economics and Management, so she is not your usual software developer. She loves to code and she especially likes Angular. As a very active member of the community, she regularly organises meetups and conferences, like the amazing ngSpain. In Spain, where she’s currently based, she’s an organiser of GDG Vigo and the founder of GalsTech, a group for women in tech from Galicia. Because she is so passionate about diversity, she is also a Women Techmaker Ambassador.
Sam Julien, Senior Developer Advocate
Sam Julien is a Sr. Developer Advocate Engineer at Auth0 and a Google Developer Expert for Angular and Web Technologies. He’s also an instructor for egghead and the author of Getting Started in Developer Relations and the Developer Microskills newsletter. His favorite thing in the world is sitting outside drinking good scotch next to a fire he built himself. You can find more of Sam’s work at samjulien.com.
Tyler Clark, Senior Developer Advocate
Tyler is a developer advocate engineer at Auth0, an egghead.io instructor, and a conference speaker. He’s worked primarily as a software engineer for the past seven years and loves getting his hands-on coding projects. His passion is in the frontend, but he also enjoys working on backend tasks. If he’s not in his office working, he’s either with his family or out playing some kind of sport.
Kristy Gutierrez, Project Management Consultant
Kristy is a Project Manager at Auth0. New to working in the tech world, Kristy’s background is rooted in outdoor education and international adventure travel. While working at Auth0 may sound like an odd fit at first, Kristy thrives on managing complex logistics, organizing information, and solving problems. She finds the behind-the-scenes work of building more efficient processes for things like our ambassador program and events very familiar turf. When she’s not tidying up her to-do list, she loves to cook, kayak, and mountain bike.
Once again, you can catch the Auth0 Developer Relations meet-and-greet on Twitch.
This is just one of many Avocado Labs productions!
This meet-and-greet is just one production of Avocado Labs, and I’ll let them describe themselves in their own words:
What is Avocado Labs?
Avocado Labs is a platform where we share expert content about web technologies. Our first approach is through online meetups. We will be hosting bi-weekly meetups which consist of two talks per meetup and each edition will be focussed on one technology. Our first episode was about Angular and more specifically Ivy, the Angular compiler. We had two incredible speakers who are renowned specialists in their fields and Google Developer Experts for Angular: Manfred Steyer and Martina Kraus.
In the future, we want to explore other ways of delivering content and figure out what the community is hungry for! We also want to bring communities closer together and find ways of doing it virtually! If you have any suggestions, please feel free to reach out to us on Twitter.
Why Avocado Labs?
This question is probably the most important. At Auth0, one of our core values is that “We give a sh^* t” and we really do! The technological community is important to us and we know that it isn’t always easy to go to a conference or a meetup, no matter what the reason might be. We believe that anyone and everyone should be able to have access to quality content and to be able to be part of a community.
We also know that right now the majority of the world is on lockdown which means that people cannot go to physical events, speakers cannot deliver amazing content, and communities cannot gather. We want to help in these times by providing at least some of this. But like mentioned above, this is an ongoing initiative. We won’t stop once things go back to “normal” – Whatever that new normal might be.
So, What Now?
Why not join us? To follow up on what we’re up to, you can follow us on Twitter. If you’re interested in attending our online events, we suggest that you join our meetup group. And if you would like to speak at one of our events, please fill out our call for papers. Also, any suggestions are more than welcome! Just send us a direct message on Twitter.
Once again, here’s the weekly list of events for events for Tampa Bay techies, entrepreneurs, and nerds. Every week, on GlobalNerdy.com and on the mailing list, I scour the announcements for events that are interesting to or useful for those of you who are building the future here in “The Other Bay Area, on The Other West Coast”.
This list covers events from Monday, December 14 through Sunday, December 20, 2020.
Events — especially virtual, online ones — can pop up at the last minute. I add them to the list as I find out about them. Come back and check this article from time to time, as you might find a new listing that wasn’t there before!
This week’s events
Monday, December 14
- Tampa Bay Tech Career Advice Forum — Job Seeker Coffee Talk @ 9:00 AM to 10:00 AM EST
- Professional Business Networking with RGAnetwork.net — Tampa Bay Virtual Networking Lunch All Welcome JOIN us @ 11:30 AM to 1:00 PM EST
- Young Professionals of Tampa Bay Networking Group — South Tampa Referrals @ 11:30 AM to 1:00 PM EST
- We Write Here Black and Women of Color Writing Group — Virtual Writing Get Downs @ 6:00 PM to 8:30 PM EST
- Toastmasters District 48 — North Port Toastmasters Meets Online!! @ 6:30 PM to 8:00 PM EST
- Thinkful Tampa | Careers in Tech — Thinkful Webinar | UX/UI Design: Wireframes and Prototypes @ 8:00 PM to 10:00 PM EST
Tuesday, December 15
- Professional Business Networking with RGAnetwork.net — Power Partner Breakfast Virtually! @ 7:30 AM to 9:00 AM EST
- Pinellas/Pasco/Hillsborough/Polk/Manatee Business Meetups — Business over Breakfast Largo/Seminole Virtually @ 7:30 AM to 9:00 AM EST
- Professional Business Networking with RGAnetwork.net — Downtown St Pete Networking Virtually JOIN us @ 7:30 AM to 9:00 AM EST
- Toastmasters District 48 — Venice Area Toastmasters Club #5486 @ 7:30 AM to 9:00 AM EST
- Bootstrappers Breakfast® – Tampa Bay Area — East Coast Virtual Bootstrappers Breakfast® @ 8:30 AM to 10:00 AM EST
- LWR Exclusive — LWR EXCLUSIVE @ 9:00 AM to 10:00 AM EST
- Tampa Bay ServiceNow Developer Meetup — Developer Meetup – Process Automation Design, GRC / IRM, NowLearning and MORE! @ 11:45 AM to 1:15 PM EST
- Toastmasters District 48 — Clearwater Renaissance Speakers Toastmasters @ 12:00 PM to 1:00 PM EST
- Tampa Hackerspace — Online Weekly Open Make Night @ 6:00 PM to 10:00 PM EST
- Tampa SQL User Groups — Pinellas – Monthly Meeting @ 6:00 PM to 9:00 PM EST
- West Pasco Toastmasters Club #2824 — Weekly Meeting @ 6:30 PM to 8:00 PM EST
- Nerdbrew Events — Tampa Board Games Online @ 8:00 PM to 10:00 PM EST
Wednesday, December 16
- North Tampa Networking Group — Business networking @ 9:00 AM to 10:00 AM EST
- Young Professionals of Tampa Bay Networking Group — Wesley Chapel Networking Lunch Virtual @ 11:30 AM to 1:00 PM EST
- Professional Business Networking with RGAnetwork.net — RGA Top Professional Business Networking Tampa Bay & surrounding areas~ @ 11:30 AM to 1:00 PM EST
- LGBTQ+ Professional Alliance — LGBTQ+ Workplace Challenges Discussion @ 12:00 PM to 1:00 PM EST
- Heart of Agile St. Pete – Tampa – Orlando — Heart of Agile Weekly Coffee Corner @ 12:30 PM to 1:45 PM EST
- Divi Tampa — December 2020 Divi Holiday Meetup In Tampa…or Virtually Anywhere! @ 1:00 PM to 2:30 PM EST
- Tech4Good Tampa — Virtual Holiday Hangout & Tech4good Help for Nonprofits @ 6:00 PM to 7:30 PM EST
- Blacks In Technology – Central Florida — Project Management – Iron Triangle vs Agile @ 6:00 PM to 7:30 PM EST
- Tampa Hackerspace — Girls Who Code Club @ 6:00 PM to 8:00 PM EST
- Tampa Bay AWS User Group — Tampa Bay Christmas Meetup & Quiz – prizes to be won! @ 6:00 PM to 8:00 PM EST
- Tampa Bay Azure User Group — Tampa Bay Christmas Meetup & Quiz – prizes to be won! @ 6:00 PM to 8:00 PM EST
- Women In Linux — Understanding Linux @ 7:00 PM to 9:00 PM EST
- Toastmasters District 48 — Carrollwood Toastmasters Meetings now conducted Online using Zoom @ 7:00 PM to 8:30 PM EST
Thursday, December 17
- Tampa Bay Connections — Business over Breakfast Tampa Bay @ 7:30 AM to 9:00 AM EST
- Professional Business Networking with RGAnetwork.net — Downtown St Pete Networking Virtually JOIN us @ 7:30 AM to 9:00 AM EST
- CRUSH Networking Clearwater, Palm Harbor, Dunedin, Oldsmar — Next Level Networking – Crush Seat Specific Thursday Morning Group @ 7:30 AM to 8:30 AM EST
- Tampa Tech and Beer — Community Connect | Episode #17 Smarter Marketing in 2021 @ 12:00 PM to 1:00 PM EST
- Toastmasters District 48 — Sarasota Speakers Exchange Toastmasters @ 12:00 PM to 1:00 PM EST
- Toastmasters District 48 — Telecom Park Toastmasters #6745 @ 12:00 PM to 1:00 PM EST
- Tampa Bay Tech Career Advice Forum — The Job Seekers Lunch Hour @ 12:00 PM to 1:30 PM EST
- Wesley Chapel, Trinity, New Tampa Business Professionals — Virtual Speed Networking Mixer Thursday’s 5pm to 7pm EST @ 5:00 PM to 7:00 PM EST
- Tampa SEO & Internet Marketing Meetup with Steve Scott — Where To Focus Your Search Efforts In 2021! @ 6:00 PM to 8:00 PM EST
- We Write Here Black and Women of Color Writing Group — Virtual Writing Get Downs @ 6:00 PM to 8:30 PM EST
- Toastmasters District 48 — Clearwater Community Toastmasters @ 6:00 PM to 7:00 PM EST
- Tampa Bay Writers Meetup Group — Tampa Bay Writers Meetup @ 6:30 PM to 10:30 PM EST
- Toastmasters District 48 — St Pete Beach Toastmasters Zoom Group – Improve Your Public Speaking! @ 6:30 PM to 8:00 PM EST
- Toastmasters District 48 — GREY MATTERS: The Forum For Open Minds @ 6:30 PM to 8:30 PM EST
- Tampa Hackerspace — Online 3D Printer Deltamaker Orientation (members only) @ 7:00 PM to 8:30 PM EST
- Tampa Bay Coalition of Reason — The Infodemic: Debunking Works (Let’s Get To It!) @ 7:00 PM to 8:30 PM EST
- The New Tampa/ Wesley Chapel Book Club — Where the Crawdads Sing by Delia Owens @ 7:00 PM to 9:00 PM EST
- cYbor Security Meetup — Breaking BLE with Kelly Albrink (Live Stream & In Person) @ 7:00 PM to 9:00 PM EST
- Women Who Code Tampa — Ladies Night Virtual Hangout with Tampa Bay Women’s Tech Network @ 8:30 PM to 10:00 PM EST
- Thinkful Tampa | Careers in Tech — Thinkful Webinar | Intro to Data Science: Python Fundamentals @ 9:00 PM to 11:00 PM EST
Friday, December 18
- Young Professionals of Tampa Bay Networking Group — Friday Business Introductions JOIN us Virtually All Welcome @ 11:30 AM to 1:00 PM EST
- South Fl Public Relations and Marketing — Friday Business Introductions @ 11:30 AM to 1:00 PM EST
- Professional Business Networking with RGAnetwork.net — RGA Top Professional Business Networking Tampa Bay & surrounding areas~ @ 11:30 AM to 1:00 PM EST
- Wesley Chapel, Trinity, New Tampa Business Professionals — Odessa Networking Lunch Virtually @ 11:30 AM to 1:00 PM EST
- Professional Business Networking with RGAnetwork.net — Tampa Bay Virtual Networking Lunch All Welcome JOIN us @ 11:30 AM to 1:00 PM EST
- Tampa Bay Connections — Tampa International Networking Lunch Virtual @ 11:30 AM to 1:00 PM EST
- Tampa Bay Connections — Tampa Bay Networking Friday Lunch~ @ 11:30 AM to 1:00 PM EST
- Professional Business Networking with RGAnetwork.net — Friday Virtual Networking Lunch @ 11:30 AM to 1:00 PM EST
- IIBA Tampa Bay — Lunch & Learn Series #19: Machine LearningEZ: Unsupervised & Supervised Learning @ 12:00 PM to 1:00 PM EST
- Suncoast Audiophile Society — Annual Holiday Party- Virtual This Year! @ 7:00 PM to 9:00 PM EST
Saturday, December 19
- Tampa Hackerspace — Online Microcontroller Monthly Meetup (M3) @ 3:00 PM to 5:00 PM EST
- Kitchen Table Book Club: Year of International Voices — “Homegoing” by Yaa Gyasi @ 6:00 PM to 8:00 PM EST
- Tampa Hackerspace — Tampa Hackerspace Monthly Board Game Night (Online) @ 7:00 PM to 11:00 PM EST
Sunday, December 20
Do you have any events or announcements that you’d like to see on this list?
Let me know at joey@joeydevilla.com!
Join the mailing list!
If you’d like to get this list in your email inbox every week, enter your email address below. You’ll only be emailed once a week, and the email will contain this list, plus links to any interesting news, upcoming events, and tech articles.
Join the Tampa Bay Tech Events list and always be informed of what’s coming up in Tampa Bay!
Welcome to another installment in my Advent of Code 2020 series, where I present my solutions to this year’s Advent of Code challenges!
In this installment, I share my Python solution to Day 6 of Advent of Code, titled Custom Customs.
Spoiler alert!
Please be warned: If you want to try solving the challenge on your own and without any help, stop reading now! The remainder of this post will be all about my solution to both parts of the Day 6 challenge.
The Day 6 challenge, part one
The challenge
Here’s the text from part one of the challenge:
As your flight approaches the regional airport where you’ll switch to a much larger plane, customs declaration forms are distributed to the passengers.
The form asks a series of 26 yes-or-no questions marked
a
throughz
. All you need to do is identify the questions for which anyone in your group answers “yes”. Since your group is just you, this doesn’t take very long.However, the person sitting next to you seems to be experiencing a language barrier and asks if you can help. For each of the people in their group, you write down the questions for which they answer “yes”, one per line. For example:
abcx abcy abcz
In this group, there are
6
questions to which anyone answered “yes”:a
,b
,c
,x
,y
, andz
. (Duplicate answers to the same question don’t count extra; each question counts at most once.)Another group asks for your help, then another, and eventually you’ve collected answers from every group on the plane (your puzzle input). Each group’s answers are separated by a blank line, and within each group, each person’s answers are on a single line. For example:
abc a b c ab ac a a a a b
This list represents answers from five groups:
- The first group contains one person who answered “yes” to
3
questions:a
,b
, andc
.- The second group contains three people; combined, they answered “yes” to
3
questions:a
,b
, andc
.- The third group contains two people; combined, they answered “yes” to
3
questions:a
,b
, andc
.- The fourth group contains four people; combined, they answered “yes” to only
1
question,a
.- The last group contains one person who answered “yes” to only
1
question,b
.In this example, the sum of these counts is
3 + 3 + 3 + 1 + 1
=11
.For each group, count the number of questions to which anyone answered “yes”. What is the sum of those counts?
Importing the data
Every Advent of Code participant gets their own set of data. I copied my data and went through my usual process of bringing it into a Jupyter Notebook running a Python kernel.
This involves pasting it into a triple-quoted string and assigning it to the variable raw_input
, and then splitting it using two newline characters in a row as a delimiter, producing a list named split_input
:
raw_input = """wdcmlzfnugqtvjbsahi easrkmocxbpjgi xrpnegqlcsyodhjfutzakmiwvb mgilapxjtrndbheyqzckfouwsv scynhfozmlvbqkarwj qhvjkmbyxcfonlazdw vjhzfnapwclkqiomyb bpourq ujpmoqs obqup v v v v v hwjlda thkdjo mlhdjw edyfjvh djh xvjadplfcwmkeriug adgtscyjipewvulr hmkipduz mdzkupi vtyizwcdm zdvtcyiwm mfzcywvtid iydclntzvmw ps pm pm p pm nglatdiw twialgd igsadtwl iadgtwl igawltd jqoxkavs askoxvqj aqjvxskho javqkxso kaxjoqsv ltkjfoxes aifogkepx ufcekybmzx tigxeahnkf xzfqbsnhmrviju rmfvsbihpujq hstfumvgrobijq bga ye sg gs sg gs sg knipbjmtrqoawe rtaebqkmopjiwn ewbuqcaijonmrpk trnmpeqkobjiwa puifme ufb fvp rntzlyxwokfcg nufjzpyawbqsdgi ogcmpsdqaxvnzwetklh qmdxnfrjobatzwgcyse rdxtqseawzobygcmfjn dbot dwetlp odtr utbqx bxuqt xtbqu quxbit rvthuiqbljzaofgwy ldftrsjvwoiayzuekcg dtxmalyuifznvprkcwgoj twc w pwg rmzaoylipcwkvuqesbhn kpuvhqlwyrabmszecnoi cwaylknbrhvzmiupseqo qlwiyczkevsnarhbpumo cgr grch cgsr rgce eso ose soe swimuzq zqwsmliu iqzurwsmh iswqzum wzhumsqi amolqcs sqoayj sjazqxyo aqhxsot ozsajqkx qbkyhzfspewgrtlv pyeqtcbskf jxbsonqtaykpef tqskfmyboeup bdjtfqypokse yrtwqacluozbg vwtfgzmcqobraj opctryzqawbg v v v nv dclgejbqrwtkvsxfa ovgkhjyiqwbmefc vpkx jmydw fxa xa gwtocmzslfqk olkgwzcftsmq ogmsfzlwqckt uwxdl wdux oxuwdt dxwu ab smej t iwhlqdermv menrvqd jemdqvr n n a n jqcvetapkbsyu twndyfrixzhvmsogu xsz zxs zxs szx sxz fsatbzpvqjknlrm pbnljkratfzvsmq qtrasmjnlkfvbpz bsjavlmpqktrnzf qajlbkzvmtsnfrp utlchvariswzqjmx almujswrcthzvfqix p j p n cgsxwk uwkcxj xpwethnkcyb gywc wcgy ctyugw gwcy wgyc afmtuw muatfw ujwmnirvkdygtqcabh takwqdjgzcuivrhnom cawvrnxfjmghdtkiuq srgt ma urnymxabthi rtxnailuqvoyph duytknrwiehaxz rhaumscngtyix gawbhtkqruyjel rlcqbuhawkmyfgjte jhbyqgkraetwlou gxbtrnadlejwhyquks ujfkleagybrtwhq dctkngohsxaljfrbvmey mlbvxaksifyneodgjctrh lmkfobtyxngsjvrdahec srkyveohxfmcjdlbtnag lbguestydkjxfopnvmhcar pjrhgzdwcmxq cgwhmqpjdrxz meipjv mivpje jevmip peimjv vmpeji zkcavufyr fyzuarckv fvnacqgksry yvcrfak crfvyka pqynikfxd dynxqlifpk laozucfdek kpeauocdlz uoldfsekzac dmekaclyhnuzo hwubponvt vwytnphobu vpnbgtwuoh wpouhvbtn wcxlspod fmedwbtjops pwnoscid ufenjp ngfxpe njbpfc vqnthfazdp pmfjng qrphaykit qkysrta jbwdtqrxzav wjqfz jqfaz meuxikpsdw kjimpsdwxu dmxpwikujs fjbsnmcgxz bpfimjnzduh urtkjpo cthod voclmdguaw oczdlntgmeir zipf fipz nbwcexytjzripskmo kwpzrmtxiosejcb tsrcoebzpiwjmxk jafcwtsukrodynhvqge pubrlchazvetosyigqjdk qminshlycutrdwx vigzpqbmunacrjftokl hweisfpycjdzouvmbnkq nqjxscbvmuwhzfakdo qtndfjcglrkoyux jqtrlgfkducxnomy tqnrjxckgfaupdoly pbe b n n n n n nsc ns nse qzkxif vkfqizx kfzqix zixkfq ifzxkq nvshwafe vbewacnh nvwmeah ziafwxcnmebko cdfrxmk fkmpxc y y y y y yauxbwtcvgoq ywcvotagxbqiu gqwyvbacouxtn uobqrcgwtvayx qcgwoytbxuav r nr a r xjrkwdnbyuscfgqtphiov brshqnjcoukxitvywfdpg vrxlptbcyfdwhgkouqijns fqcvwudyiotjblzpxshgnmkrae ouhrqwtgnjeyxiamfzpdscbkl lnch nhclmg ldhzcny uzfeomrwi ydgkhjbx qcylp hagpbecorwyvfdz rstplobhmfnxvykdewc hfruowdvyjgbpzce rgdiznuxa dragzniue jzysdgpuvkowqin lugrndiz nbdcfugzi eqponlctfbwgk kyjniulbegpdchtwoaq onczetbplkwqg thevzsrc zcewrsv vczueosky wmzlcsve sxeqojwkarhyutcdnzp rjnuwzxpmeysdoctlaq pzqxeratsdnkuovcwjy qexjbo cqunbaprhwyjfe ilvegkbszdt efbmqj wm wm hm wm m texosjaiycpqn mntxspgikeldwycjarq nysqtaceipjux phiqznsyxjcvoabet neqytxcuipsajvf z nozy ydfcsvgbikjphamr wskfdahgpvmrcjby kpsirchfmjavbdgy pslxjrugtzydaokemvbcfqh t pyt fu fu d yj fnl qxkevrhpna kmvyorduqe sfnmyevqwka fvmyieawqks kvfhmctdqjaslywe ywfkvqeanms kufwyqmaesvh ulvtwepimynb ehmpnylubtvwi wplevtunmyib lpbwnvtuyeim unvpbgtjiaylmcwes zfxkceynsu xdfzysnuie efzgxunsy nzydesxfu jneurlkfzxbq xekznblfurqj rbzljfkqnxeu zueknrbxjfylq xzferlbjqnku tr f egtr jmu s aeq qae eqa aeq bsgjrilayoezwndvtq giadlcryjwobhznqesvft guxfyzespj zusejpfgxy zxygjuefps xvmlgpzjdrubqa jfmbdvzeyrlup ruzchykmbpwdvloj vhmuebldrjzpo bhvcmrypulzjiwds cfsjzamyhtoxq xoysjqfzmhtac qocxatmfshjzy vdhsifmynta nsmfhdtya tsnfhamdy dafyqtsnmh rfybkqmh qoumrd l y l y w vlmerz mlvrze zvrmle zelrvm mzlrve rnb gdcb pbtergc tecfjgr ogzsajwvdiplrtxbhfcnky btjzlswhikyofgcpvrnda tbwinagrhfyscvlejkdop dakhrbipqglmovjyncswtf bhyljrdpsktgfiancwov qolmnyvhtwe uwkecxshldmoy zwblsockyumh miywfgjhaopr u u q zdxynqmev bdexmzyiqcn bwtqagf tnmwfaqbj p p p p p yjgicnxerbsu xpzfqirsjh exswmarikbj mjxgrsi tvzkbxugmcnshproiw czxtirownbmpksuvgh cnofirbgmhzuspvtxwk gmctsrohkxwzupvbni vsgbzcmktxihonwupr dyaoim aiom ozimual oxaim biyotma saliju evzhxcobk lj txhebw etwhbx uhwxtbe eyaixfrdhoqksc eakiqsrocxyhd vkr kvr kvr surjoh ubh ubmahe uh vhkcawrno vowahrnkc oknarvwhc cnkhvwoar wvhkanrco ntpfemsvialxgrwqzc kcwegrtispxnyd phstgwixebnucr xpwjtenscoigr sfanq xgtzfrn ulfinpkv kdwnyjuzctiqpgf ngtcrjipqfyh ypfvcqntirgjh urmtsh svihtu utmph juthydwafcqx uthve sk ks sk zxbvcrgyqfjtoeiudwpkhsm igkswrpohqudcfjxzmvytb cpatkzfuoyqgvrsmibhxjdw kvgumiabnoh bvaiomgnukhc mkhnvusbagio hamiobunkgv umsgovkahbin yrceuq rmdbpa nkvxjslwg lkt fl vil whn hn hn gvebcszypdlkqm zcyhdlpqgsvke cdzbylqkpsuveg pzsyxlgdaiofcqwvek gmcpvyqzeskld ryzfspdtbwxiomhkjnlu tqihvployrmksbunzfwc dualjxigyrzb durysxjlgzaib srgxulazbjyid lrgaubjydzxi azritbxdpljyg cfahxspjelitdnobuvqywk vwmkoxulnypfiatgjbhrcsq f f f f f grbmahpise mbireyxhalgs bcrkvuwqt trubckq rbuqtkc trkbcuq rubtqkc zxpbejmvhrutwlkq gtvrzphoqcbnmju pjazbvqurgmysht fhsptiumrvjqbz kpszjieflb blsijkefzp zksjiefpbgl ilbzrksajpfe sglzbepfjik nxwohsipd zitjrlvfgsoym bqsiopuc aoisd wj j fzpglynjeu jk ikj abzftcqvgsrnexpmho pxvlybndrtqimzhosacgef nocqfzerjaubxthgmwspv psauzryot vmdhbwe lfc gsri sqya lkjudnqterhyscgx eckqhlxybrngudstj wotecvlyrpgqmijxkhsd htpc caph hpustjc nyhcedmgp ezaljkfpiyvroud hbiwxfstmldkecnvpgqo kiqvzyjrthmblu ahszlduemxcij wirunkh hwqdknyirul kxwuhirn hkirwnu ierwunkh vcgno snmicvo ncomjisv coynuv lconfdvpz tgqkhowsyfbzpcur zcqsugtwhrpfy fgydqpcjswrlzeuth thgpcfyzqeursw rwpci cipwr ptrlaqebo pebtlaqor qboxepatr epbartoq fypd dpyf ypfd fdpy c c c d c gxysqiamkpc mpiacyqxkgs mvqbskuzefy zcsqebma ztbnlhe snx xsn nkxs snx joyblxztkswmvnec gdcrhykmfseqapibzu oqzmprikt fhlgxucda ygrjkfazu kjiagrzyfu btg o v oc bnqyz ebdfls vjhocqkamygbplu dbwsyefuxzntijrc kmlb kqsbl vhjsdxrfpokyznibwgtmu syvkmzfjgpdwixrnbutoh uzbjgvhdkpynmtfoxsrlwi jpkxwvyrgftzioubhsmnd ykjmzvsqnhxwgbrutoipdf hwby yvbmhl echgiyabjpf krbouyh hrynotb tobipzwfxy pfxwytizob hsfwzpbotiyax znrgilpcfse seinczlpgrf nircgepszfl rcegzsiflpn lzgrcpensfi tupvbxcgfnmh fpqntvibgxhmc npbtvxghfm tvxfhmbnipg rnvxmhfjgpbt inysghdka wbc noktsjqvmzxheplrcfgiuwda dlogmasfzwhupjrkcntixqev zhwfbs bzcwh igqkpctmafr jietalnfksqp ewlanjvgdbpm lpjangwvem vpngjwmeal glvwnpejam enlgwjmvpa niocufzwrk kirmuzfocvw juqervaxni cudjqavnix iuvjndcaxq xvniqajugd vxunjiaq lmayozkep koazylep aeykzlop ejgotzhrxbsnqimu lrspkgobcaywmjfvhd uazxfrony uoaxynzrf yunaorxfz lowmgiuxpnakzsq qwaomukglnx ubgkoyqanwlvmx lowaqgyxunkhm alfoj floj yglkurfahidmoxtvz muykfdrzivlothga devylsarcupgoihkmftz rmtgkalydnhvozubfi ahrzqodkgxyuitvmfl gmdoshlaixnc xhmicdgosanl hiqgvbulakdmoxcpn hoiamdsngcxtl egnprq ash oabx abxfo vomitazdbflqhkue lvemipubdafohztkq dkabtiylqgzuovehmf euanfbq skufxtami nefauc fadpbjxvzeghqkriy xpaqfzjvybdhrkieg jeqghzxrdyvakpfbwi ygvakzbdpqrxjfeiht dhvmgjoqzknbwyl hvnlobmydwzqkjg vbzljhdqgnmwoyk s k sk d svzubcigpeqdthfmxnj djogszbcnvefqthiuxmp vgkpjwymduqfxcztoasne swgapuymcvqnjodtkfzxe stgv yvbts iokqv h h h ujxw uz uz uz cdh lhg mkh quroafxhipsev d d dg lbrsefwhxagdmpqjiocuvyn uobfgnhvsqwzlkjyraicdpm uwnvthio yudxpkhrngb selctamwozqvf ueiypcnoa nidaehvt akencir ozcru uoflar pwoxuyvm nrgaujbldiwxvq sdvuirgaynbj synqkzdlpebticorvwxmaug ekyatuvbpohmxnfdgczirwql ztvwupairdeqmckgbnylxo alngerwtckpvmioxbduzyq dqygzrkuowejsm zyikwtjsver yzjrsvawceik lqduw iudw wdrue zxnrflac lx lvx otlwkx wxyl q q q q q aigmyqxscvhde csegmkqdnvyahix gvqixcdheysam dsmyaexgivqhc shiqmxgdeycva nbmovulhpai yfcobuiaetpdvmln mnopuvlbia wviopnmluabk uvamohipklnb cibznrjtsgoafdlkx cethszlarinx xcsztairehnlp szhnatlxicr mpselnxatyzric qxdzauyvbc qxzvabdcuy zyxabucqsdv uzxvatmprofyjcliwgbdsqnek kynesjvmoifucbpqwxlzrdtga mepouwaj cutjoxvpa apojcvftd opwdaj njhzgqrikyapslo efqisyl elfqsiy sfiqley if wvzghe xn dnxu afuolgsxdckypbenqjhmr euqojgbfzphxmnrysda xsbwrdmnfqyphaegjuo xsfuhpgnbjmwqoaeryd xjyizvdsbkfmhenwop mueiojtyqnag bjlvkzugwqspcihmxr mlugrxwjqsvibczhkp vikuscpzwqhmgjxrbl pxzbksqmjlcgihurvw payfmlnhgtzsrxke yeknlfshmrgztx p p p p gnmcwdtquesz ztdscnkg zdancosjgt cdntzsg zcjgbpstrnd ugxawjehznr gujxqzrwhnea rewagunjzhx krvmqtuiwsezbjcdhployaxngf xkwsubhjlfvparcgomyenidzqt jrglbkzcwtuayno iwydqmzt tdwfeyz jnvchaxzotqd jdaohpexnt yifrdlua asridu rchuily brliyc icyl nclfjxiytvs hiycrl fj fj jf jf hncwvidj ncijh qjhrin zsxiheynj jvihaqnc zkraj zkjrl akjzr zsvjrk culpozwn copkslvruwt fhwlecupo cuibdzoagynvrkw dobjkzuxvrcyinag ipsduzkvybnoacrmeqg gjwfeblzasoirpvhcqtxu dcfqurpiaxslgjhbyzwmeno agi sa vuhaksj zatyex xponks ojnkpsx cqeiyuforpx bxfnzrs xhfnvdr rfx tqowdj dw diwfu dfewgi wd dyvjwabnuzgx bjdyglxvzonw dxbwnyvagjz zyiwdcgrbjexvn xjngvztwbdy ob ob bo ob cp cp cg cnwlshdkyboxmpvtz ndswvmyzjeuprbgchl ayzkbswhlnfptcvdqm cmfyketonuixwdgpav xeyngtvuwfcdik xdufiwcnekvtgy zuvyixgbsdhwnjkelcf xwdfvucyinekgr vwznkidlhxuaosfr rhakozvwgfisdunl korahvzwdsyilnuf fhniwvurokxszald rlhewm whpr wraqfh szpvechrdnybfjmog vgptfyjmbdcxzshe zhsfqepvtygnbjmdc yzhjalgcusdpfbmveik xapwbucizkl qgs yoehs jrsge vjgdtm vxyuftcbpl uycftxlbpv vtxflpbycu pbcxfvtlyu xylavcftupb yhbadxqs hqdxsay zphxtaqsd asdoeqxhfnj tlmrid osmrjwlvge hfprkgzljcs slghpczfjrk flcjzshpgrk hzfcjsgklpr rgphlfjkzcs jizfvmyocxq kogmzyjiqv ujnqwpaszvhymro gxomvzjcqy ie ie piec ei tvaxzm txamv puqcatmbe bcuqto ubsiqhzgc vkqogu oqfhigvudm voqubg zlfapsjxtm umalzjpfosxt jplsftaxzm tafzxlpqsbjm zicyojr ilzcyr hzcrtleyvipf zicypr yicezur ehigkrowmvjylnxb tihkwoxbjelnmrvy nkjbmxwhoelrviy vnojlkwxrmhbeiy lvkhxnowmjeyrib bpzgcrtoisywvned acdwbrytesguv b qb ba bh b hntmvbilk tnmbzvl vbfnmt yvnomuxbtw ib ib lib jefqbsd iyhzrvcngl zaeqfuhynlbxipwvgotkd kagozfcnbirmpuesywdv wfulhibnvtapkyrq ibleqfykavprunmxwth raulpqfwbhvintyk vnwrklhufytbapiq bknqpvrytfuhlwai wtgqajfmk mwbfcjukqga fmghkjwaq gfawqmjk fjwmkgaq lxk t w w mf mnzbcw rad ejpxykvhu zslo fatkelbspwjyhoqrdui qsngucrzamvx ldwhapn wnma awn wnau naw fnrgykvulp vyrlupngk kynprgualvq oz oz oz zo dehqmlkfyxpvujagbtcwio huapickwemyblxodftjvgq pagblyvnjotwekuhcfxiqm qjythibopgxaeckmwvluf huclkitbnrad uhdoictnrklba tlcbauhdinrk pamdyrxtj pktnmarybxjd tr drt rkt tor rt gjrclwxyuk isqmdbf eoivmdfpt qvg i ui j l u lu osd zmdknlf nzlfmdk dmznfkl dzlnkfm ozdievpxm mzoxdiepv idpzexovm ovdemzxpi cbyrndpwk kozyrncdp ujcksndxphyf dnbpkyc e e e w tpndq igpajc gihvnzfacujpoelxqkr mqfjnrodzkuvxaipel okwanixqlpjufevr rxipfjtasnekyulqvob jmgeixvhaoknq qloihgekvjxman ajoghikvmpxnqe ingovjkaehqmx szualfd zsulfaw osajgkmyfvri hwmisgbaqf bvzm izwrn zsfd mz kixhabnoqpzsg gpnxaikqobzsh argcboiqznkxsph oaqgicsndhkbzxp jzxhpstoinqbkga fkisv fvisdrk vkmisf ksifqv ifspvk ovwqbshjirpg iohbgfjqcrvt efsqtnoywmkzrv gwsotczmkdyqlrve zmverktswfynqo rwtuihvjqofszxaykn riqntxydpcakjbgo mzkndrhabvj gywofampnlxbhsi hbtenma rcamubhn bmndhkja afsnkue pfcvirzydqbetlk zftwoivcr rtvzwix kzjwtrgi hitwzor harkxeinjtgpy tprbwighzeksymcv qecrsugzdho uwdxocqyftnbzhl dcrzqhuso sdchqozu cu u u u whlfczpqa yfzhpqc zpfobxkhqc cfzhqp fcozqhp erbnkjqouhg qsthnrjiwxvzkaf yncqejdukrh klqubphrnj ikvyfmlpacez mzeiplkacvfy lyfzipvcmeqak qo h neuzqjk ixqhknj pvbrygdacs xf ef f f t t j z ybx a ewbmvucapsxkig ksiprxbvagwfme agdmiwexvsbpk egisawxkpmbv dykmbtv dtjkmyv mvkdtyc ydkmtv zw o i oi r hjybnqczotxgeiaup cpygejxuzhonitqab jnauyiohtcepqbzgx uaqtnyicgezoxjpbh nptbcijxzuoeayqgh owynpg wpyn pnwy ywpn fqoishlxzarmkc dstzjmxrvfckuoi xsmozrfcik zmgsrcwiofxpku igrkebsfoxcmdz moas xdcfmoa xltpwzrf erbhflxwzntp tnsrbxlawpzf rtzwuoxipfl yesonitqag etigoaqmynshc tpneigasoqy pnmvfgwyierqukct tcnuigmqpeyrwvk qza zaqr zqa qza qza dyphutng ghntydup thpudywng tpudyhgn gofac homgpwae govmnaw azsgo apgmyuo bsvqmnidyogzuewtk qitsokmnewdbuy iqskwxyonmuetdb kbmsundoywiqte uoqj jvs yjazt j r o nv oy r u ru avofjnwdehrpyklqugzimtx gfjlwkrahzqvneodmutpyxi mgpjlfuxoyvzwqtdhaeknir ryfqedjgpnikawmtxhvuloz gidrokyntxavfwpmqelhzujc k mzp jfpow jfop pfjo qokte eno woef qnart utaqr ajqivchfpem upvqhcjmafe pvewjfhmcqa vmjpecaqhf cahpfemjvq ayw kp rixwjogsfhuyvebnp vexwuhjyogrfisnbp psyfwhrxeogjubnvi yjvswhnrogixbufpe eylbtgqvronjfzphw brhqvoptnjeygwflz rwhlpzbgjvoneyqtf hcvlnbegyrfwtpozjq ynwefqphlvrotbjzg xyu xy bj j j j kocgiwr ibksgowc ijkcwog wiegjcaok rlt ltr lrt rlt lrt xjoc jcoxz cxjo r r amrtqgfw udr sderl vonauts atxsyvco psroawlevbjdgk smvzhqoya ubwotjecsqhadvkf ufqkjtesadhvcbow pbqsuatrzk rsquzpobk pqsrbzkdu zqcusrkpvb spbkqrzu vqwcinpb aiejfduvpht zowvpinrxqml zufk kwe k mk wko lydtzkhwajf xrphuebsogm nsucmhgqpx mwhlnfotz shvfwmanl xfywodzc fyoxchw howycfx owyhfxc xwocyf hri rv lzr r nrfc mkd yvjkoguaxip nwkz bcktdsmqf sznkw flhbygto ftbylhoa otbyflh yhbtfol rnphowmiy hpwrmoyis iunworypmh diyrwhnmpo qlhfdcg plju rl nalk lep xwcropjbzkdegnufsqiht rcidlowgxnsktqpbheyzfju ctfxzgvprnhbqeodkwjisu wgzu fkbuxrwg gwjyuhzn nhjyzuwg rwbm wmkrs itzekynp dkepiunyt vmwlbgkcipnseqr xlkbgo kgz kag i x htq sot f kuqperwixsgvbctyjfdn qjcdstpxvyuwifnbre atqumpwrefdxvoijcznys rfxdcuispnewjtkyqv imdwuntbahxvj daniwhemzxtjb nhmajglidtxvwb tbjinhxwymad csaqnhdtfrmjobwkix esjkcgpf gmfszpk pfgksj i i i i alnj zucmhenrtoq bkn nifp nvi mjkagdfsilctvpwhuq wufhtjlgpaivcqdsmk qutsghdvkmcwfaijlp vutlpwschfkamqjdgi isjwtmqkvfgalupcdh ynsgxmfoelkd yxmvgkd vgmykxd gmyhkdx ygxmkdz vldyroebks osverdjlyb eszyrudvblo rvdqomlcbtygse oredlbvsy o o o o jvmo jbkpwnc dtwrpiqbsf vlayehgxmozu khc crkylh ewticaxphkd fhncmk khcf ofvtnbpayduik ufbiatxvpdoyn oibfupdrtvyna favdotpyixuqnb ywatimcefbgvpsoundz ismcgzfqbxdlv zlwdsivqcbgmf szcbqidfgvlm fgjx xjf fxpjm xjf etuipyaxvmjszkf aeyjvuwzspkim pajvmizekyus nmbyxzehsagcdfjvt hzbaxdfyjevntgc dvthajbznegxfcy ftwqrgzohp hexzqdjsrfwmu eubmrcntqyxpsjozvilgadhkfw zjfrdtwiuyoaepcnmkslqvgxbh keiurfhgmzovydqapcxjswntbl umkocxlwagfbzepjyirtvdsnhq kngzxjrshovmdbtclwfiqepyua lyomqhdu mylowqh chlwr rhwcl crlhw wcplrfh tamkofzcpq tomgsjqca bj vfwbi gb gbz njaecfkliuwm cnvkfwualmij iaunwmfelckj hjifcqxumnkalw iht orlie afsxupiz nocfkzrdstjqwu ehisrtpqnwgaymbuc qxgt gtoxcj txgr hoxsgkdiqtfz gtfisxozhvdk gofksdtxihz izghftsdokx i x a i i knqftuisvegdjw ymogrc yacpbrog gxlp sa k k w b speodbqvngkjrl nfslobmegdpkjvqr rpgbneasdkljqvo dnvklcgjiorqpubse y y y y y pahzx axpz axzp ya a ay ta haposzk lromwgtifpz xobjpszq pujonz ndopyqvz wqfl kwuqelft lfbvwq cqgefyksvhwpalxdbrimoznu spvyfeucqnigwxbkzrmadl sxlwrdbyvgzpqmnuacfejti ou uo uo ou uo oridzvksnfuep vsrpfexizdoq nxo qgx xybutqfszdhl ybsdlqfxutz zlxuydqbtsf tl tbla rtel jtgxlohyc w vrgofi kcjt xkqnrf pxqnr xrqn qrxnp qxrn pabnotufrs bornptsda sptobanru mjzonarsplybgt uranspoqbtx gncfptk qyodies tiln lt lt lt ecbxuofajgshqk crehbqksaoifjux klibxfuhqejocaws csbxhojuatefkq gjaqcexhkofbus egjflivrcywdtu gyiedbfovxt qsviadhygtef gihexypfdvnt niotdwkarb jbimonfkl j z yfob bymsrul byqu dsycgzhtioxrpwvlen edskiwvnhozrcypglt ygcjblprwkiehz esfjghqbliczwpuk ieghcjlpzkwmb mcephzsxawni imazphsnexw mxezwnhysipa wsheabqmnipxzd pcmwhysneazxi yovtlfcuiwxmskzjqeghr gbcvlityzjxqmfoswkue mqlgfwkvysjuzntieoxc hivam amfuvi aemv mxahvg lze le lze lepd jwpm wjmc gcmjw mjdaw jwm s sxuq su ns uqs csqmipzdnhxkvfgt hxdfqvptigsmcn snhpfmtgqivcxd scihxqwpmdntfvg nrsmoa rsnma sramn nasmr msnar yihjeplactzrdfb ztfekaljidry qwhty gweh zksdnuipmhal oxtwrhcbjq qhcvb ybemxa jseoixkvc ugdxepl tofhpsgaul lqushgofp lfphogsu goplhsuf lhsugpof gdwzk xqw wmiagjvocxrzkhdtfu xhwscvljdqryibpgofma rgacswftbpxydum rsmtxdypgofuacwb rwqkufstdjxmnalgbpyc thzabcdwprgyxmsfu caywrpsduftgxbvm dujpzvsb jusdvpabr odvjbsup budpvjs kpujbsvd gfpncwmjrdlx rwmcfnbdplgj djw jdw wjd diwvjn jwdb h k z k v al lpa la chinjymkwe vnwgcemkp kvcemyxnj enkcm krlceuqnfom glewafm ngqawfvul fia rup j rmp ju dgvtfbxow wvtjgbdxf gxtbwvd tbndgxzqvw kuycgeanqwh unkhyceqgaw aykcweqguhn ceqhwkunyag vcighoudqlamkrt dnyhemguilvqtao hxzoubfvgiqajtlwm ovqepnmgladtihu oatnlremuvsigqh nd wdn xnea ribpvsfynoctmqh n rpflnskacoq laqojrp liprwqao aojlprq oarqipl jvk zwmvj jv vj vydxlwk vxywd xdyzurw lqghripoewbjdvy qbpcdjlwhovrey pledvrqbwhsojanf hjqdbptlmwzeogvr rqjwohdipuvble h h ot t t fyxkdhnwalez weakhydnlxzf xhqawsrol guxblwar lvkjrydiwxmptea wfaxnrgl famd xmd md fmd damj istm smbj mwbs msw ms raszvfpwdmeich awfmvlizcperdh pjviuhacmzfwdryqe t t t t t b b uemjsklzft teukljfmzs ztfjulsemk jkfesztmlu jlumszeftk toczuxmkslrhpvijeg mopultekcxzv xukmoedpltczva kpolveuzxmtc pktdovemcxzul agvfm jvogqfiau vdaogf c gqd sgfpy sgfbpl jretxvqmfghp tureqgfvjm ijtyqezrgvnfml mergqtjfv ubzsrptcgxwdoe tebrzfpwuxgds wbdrxtfpgsuez gvnuhzpdebwaxtrs gdqmje gqtcpdmfe rxqyiehnogmsbdv fqwzlinbormheg mjorlniezb ia ai ia ai xghswfuabdlqicnyekmt bgetcxwalnkdiysfuh sigwankrfuhtcxedlby nlwxfucbhgtdseikya khawdecfngultbyixs cwzgvbuqlsyetoiajnpm asjpbudkhoinqgtzryfwevxc zbpfxictqy udpyqtxizcgef zptxicfhqy hpqcfbzixyt zxhqpyftic oirypkjhxfcwdqeagu hwoqyupdrjigbmvxsa kxdhpangqieuroyjw fegnzr rzfgne erfnzg znfreg pvuafthmr dvpmwcyg""" split_input = raw_input.split("\n\n")
Each item in the split_input
list represents the collected answers for a group. If a group has more than one person in it, a newline character separates each person’s answers.
In the sample of split_input
shown below:
- The first line shows the answers for the first group, which is made up of two people.
- The fifth line shows the answers for the fifth group, which is made up of five people. All of them answered yes to only one question: Question v.
['wdcmlzfnugqtvjbsahi\neasrkmocxbpjgi', 'xrpnegqlcsyodhjfutzakmiwvb\nmgilapxjtrndbheyqzckfouwsv', 'scynhfozmlvbqkarwj\nqhvjkmbyxcfonlazdw\nvjhzfnapwclkqiomyb', 'bpourq\nujpmoqs\nobqup', 'v\nv\nv\nv\nv', ... ]
Finally, I split each item in split_items
, using the newline character as the separator:
groups = [line.splitlines() for line in split_input]
The result was a list that I named groups
, where:
- Each item in
groups
represents a group of passengers - Each group is a list, where each item in the list represents the answers for one passenger in that group.
Here’s a sample of groups
:
[['wdcmlzfnugqtvjbsahi', 'easrkmocxbpjgi'], ['xrpnegqlcsyodhjfutzakmiwvb', 'mgilapxjtrndbheyqzckfouwsv'], ['scynhfozmlvbqkarwj', 'qhvjkmbyxcfonlazdw', 'vjhzfnapwclkqiomyb'], ['bpourq', 'ujpmoqs', 'obqup'], ['v', 'v', 'v', 'v', 'v'], ... ]
With the input data massaged into something that could easily be processed in Python, it was time to get to work.
Strategy
The goal was to get the total of all the “yes” answers for all the groups, keeping in mind that if any person in the group answers “yes” to a given question, the group is considered to have answered “yes” to that question.
Consider a group of three people. If:
- the first person in the group answered “yes” to questions a, b, and c,
- the second person in the group answered “yes” to questions d, e, and f,
- and the third person in the group answered “yes” to questions g, h, and i…
…the the group is considered to have answered yes to questions a though i.
To put it mathematically, a group’s answers was the union of the answers of everyone in the group.
With that in mind, I wrote this function:
def count_union_group_answers(groups): count = 0 for group in groups: if len(group) == 1: # If there’s only one person in the group, # the group’s “yes” answers are that person’s “yes” answers. count += len(group[0]) else: # If there’s more than one person in the group, # the group’s “yes” answers are the union # of everyone’s yes answers. union_of_answers = set(group[0]).union(*group[1:]) count += len(union_of_answers) return count
This function takes advantage of the fact that while Python’s union()
is a set
method, it can take one or more non-set
arguments, as long as it can convert the arguments into a set.
For example, this code:
set(['a', 'b', 'c']).union("def", "ghi")
results in this set:
{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'}
I rearranged the set so that its items would appear in alphabetical order so that it would be easier to read. This is fine, because with sets, there is no order.
Now that I had count_union_group_answers()
, I could apply it to groups
…
count_union_group_answers(groups)
…and get the answer for part one: 6504.
The Day 6 challenge, part two
The challenge
Here’s the text of part two:
As you finish the last group’s customs declaration, you notice that you misread one word in the instructions:
You don’t need to identify the questions to which anyone answered “yes”; you need to identify the questions to which everyone answered “yes”!
Using the same example as above:
abc a b c ab ac a a a a b
This list represents answers from five groups:
- In the first group, everyone (all 1 person) answered “yes” to
3
questions:a
,b
, andc
.- In the second group, there is no question to which everyone answered “yes”.
- In the third group, everyone answered yes to only
1
question,a
. Since some people did not answer “yes” tob
orc
, they don’t count.- In the fourth group, everyone answered yes to only
1
question,a
.- In the fifth group, everyone (all 1 person) answered “yes” to
1
question,b
.In this example, the sum of these counts is
3 + 0 + 1 + 1 + 1
=6
.For each group, count the number of questions to which everyone answered “yes”. What is the sum of those counts?
Strategy
This time, the goal was to get the total of all the “yes” answers for all the groups, keeping in mind that the group is only considered to have answered “yes” to a given question if every person in the group answered “yes” to that question.
Consider a group of three people. If:
- the first person in the group answered “yes” to questions a, b, and c,
- the second person in the group answered “yes” to questions a, e, and f,
- and the third person in the group answered “yes” to questions a, h, and i…
…the the group is considered to have answered yes to question a, and nothing else.
To put it mathematically, a group’s answers was the intersection of the answers of everyone in the group.
All I had to do was tweak the count_union_group_answers()
function from part one to find the intersection of group members’ answers…
def count_intersection_group_answers(groups): count = 0 for group in groups: if len(group) == 1: # If there’s only one person in the group, # all the answers count. count += len(group[0]) else: # If there’s more than one person in the group, # only answers common to all people count. intersection_of_answers = set(group[0]).intersection(*group[1:]) count += len(intersection_of_answers) return count
…and then apply count_intersection_group_answers()
to groups
…
count_intersection_group_answers(groups)
This gave me the answer for part two: 3351.
Recommended reading
- GeeksForGeeks: Sets in Python
- Real Python: Sets in Python
- The official Python documentation: Sets
Solutions for other days in Advent of Code 2020
One of the silver linings of my job evaporating due to the pandemic is that I suddenly had a lot of free time to try some new things. The best of those new things by far was my five weeks in The Undercroft’s inaugural UC Baseline cybersecurity course.
What is The Undercroft?
The Undercroft was recently featured in the Tampa Magazine article, The Latest on Tampa’s Tech Scene. Here’s the relevant excerpt:
Over the past year, a number of notable out-of-state tech companies have chosen to open offices in or relocate to Tampa. Last December, Tampa beat out other up-and-coming tech hubs like Denver and Atlanta as the new home of Boston-based Drift, a marketing technology platform. Information technology training franchiser New Horizons moved its headquarters from Pennsylvania to Tampa in January. And that same month, D.C.-based technology company TheIncLab expanded to Ybor City. TheIncLab opened an “Artificial Intelligence Experience Lab” in The Undercroft, a cybersecurity incubator that launched last summer with the hopes of turning the historic Ybor into a tech industry hotspot.
“At The Undercroft, we’re focusing on the supply side of cybersecurity,” says CEO Adam Sheffield. “How do we support more talent in this community and more people who have passion for the field?”
Initially conceived as a co-working type space where startups and members could connect, The Undercroft launched a training program, UC Baseline, in response to layoffs during the coronavirus shutdown. The UC Baseline program is designed to help educate people moving into the cybersecurity workforce or transitioning from traditional IT roles. Ten participants have signed up for the six-week program that offers courses in networking, software, and hardware, according to Sheffield Incubators and accelerators are behind much of Tampa’s recent tech growth, as nonprofits like the Tampa Bay Wave and Embarc Collective offer resources and networking opportunities for local startups, including two recent programs that focus on boosting the representation of women and diversity in the tech industry.
To describe The Undercroft as Tampa Bay’s security guild and cybersecurity coworking space is fair, but that description doesn’t capture the spirit of the place.
A better way to paint the picture would be to call it the 21st-century cybersecurity counterpart of coffeehouses in 17th- and 18th-century England. Like those coffeehouses of old, The Undercroft is a place in a beautiful old building that functions as the home for the (often boisterous) exchange of ideas, the advancement of specialized fields of knowledge, a little deal-making, and if you pay attention, a great place to learn.
(Thankfully, The Undercroft departs from those old coffeehouses in one important way: Women are welcome in The Undercroft.)
How I ended up in UC Baseline
Back in mid-July, I’d heard about scholarships for The Undercoft’s then-upcoming cybersecurity class. I posted an article about it, which ended with this quip:
(I’ll admit it: Although I’m not likely to qualify, I applied.)
I applied, and to my surprise, I qualified, which meant that I was in this classroom a couple of weeks later:
What I did in UC Baseline
And thus began five intense weeks, which comprised the following…
Hardware 101 — Gain a thorough understanding about the devices on which all our software runs and through which all our information flows:
Networking 101 — Learn how our systems are connected and the ways in which they communicate through these connections:
Linux 101 — Covers the foundations of security in Linux environments, the OS on which the internet runs:
Windows 101 — Here’s a big challenge — learn the foundations of security for Windows environments:
Information Security 101 — Covers everything from core IT concepts, to cybersecurity principles, methods, and practices:
Python 101 — If you’re doing security, you should have some coding skills to automate your work and build tooling, and Python’s an excellent language for that task:
This is not for someone who’s casually curious about cybersecurity. It’s a lot of work. As I wrote midway through the course:
If you take The Undercroft’s five-week cybersecurity course, UC Baseline, you will have to absorb a lot of material.
After one particular day, I felt like the cat in this video:
The course was taught by a team of instructors who work in the security industry when they’re not teaching. They’re also a personable bunch, and all of them went above and beyond in their efforts to ensure that we students were getting the most out of our classes.
The course ended with a career fair featuring presenters and recruiters from local and national cybersecurity organizations…
and then a Capture the Flag competition and socially-distanced barbecue:
The payoff
Did it pay off to devote 5 weeks, 5 days a week, 8 hours a day, to attend UC Baseline? I think it did.
I’m really a programmer and developer evangelist by training and experience. There’s a tendency in both these lines of work to think of security as an afterthought. Attending UC Baseline, learning from actual security professionals, getting my hands on the actual hardware and software used by the pros, and even just being in The Undercroft helped me refine my security mindset.
That in turn helped me bring my A-game when it was time to apply for a job at Auth0 and then go through their rigorous interview process (which I wrote about here).
I’m not alone — 8 out of 10 of the inaugural UC Baseline class got work around a month or so after completing the program.
My thanks to the instructors for the excellent courses: Gabrial Hartnett , Koby Bryan , Michael Dorsey , George Bilbrey , Jon B , Zoran Jovic, as well as my fellow students, who made the classes more enjoyable: Hawley , Danielle True , Daniel Jimenez , Melissa Bloomer , Alyssa Kennedy , Nicolas Claude, Maria Laura Tarabillo , Ryan Butler, and Anthony Davis!
And of course, special thanks to Team Undercroft, for making such a special place — the Tampa tech scene just wouldn’t be same without you: Joy Randels, Adam Sheffield, and Chris Machowski!
Another UC Baseline in 2021!
If UC Baseline sounds interesting to you, and if you think you’re up to the challenge, there’s another one taking place in early 2021. Visit the UC Baseline page to find out more!