- Published on
Advent of Code 2023: Day 4 Solution
- Authors
- Name
- Tinker Assist
Advent of Code 2023 - Day 4 - Scratchcards
Table of Contents
Part 1 Solution
We'll need to begin by reading the puzzle input
Read the Puzzle Input File
We will save our puzzle input in "day4_input.txt" and then read from that file.
file = open("day4_input.txt", "r")
input = file.read()
We will then break up the input by line:
input_list = input.split('\n')
Create Solution structure
points = 0
for card in input_list:
# We will add to our points here
print(points)
Get Winning Numbers and Numbers You Have
To retrieve all of the winning values from our input line, we need to do the following:
- Get all characters to the right of the
:
card.split(':')[1]
- Get all remaining characters to the left of the
|
card.split(':')[1].split('|')[0]
- Seperate values using space characters as the delimeter
card.split(':')[1].split('|')[0].split(' ')
- Turn each value from the list into an integer
[int(i) for i in card.split(':')[1].split('|')[0].split(' ')]
- Remove all stray spaces and null values in our list
[int(i) for i in card.split(':')[1].split('|')[0].split(' ') if i.isdigit()]
We can use the same methodology for the Numbers You Have, but instead read all values after the |
by indexing 1 instead of 0.
[int(i) for i in card.split(':')[1].split('|')[1].split(' ') if i.isdigit()]
It is messy, but it works :)
So now, our code looks as follows
points = 0
for card in input_list:
winning_nums = [int(i) for i in card.split(':')[1].split('|')[0].split(' ') if i.isdigit()]
your_nums = [int(i) for i in card.split(':')[1].split('|')[1].split(' ') if i.isdigit()]
print(points)
Compare Your Numbers to Winning Numbers
Now we will loop through each number in the list of Your Numbers and identify those that are in the Winning Numbers. If the number at any given index is in the Winning Numbers, we will increment a variable winners
winners = 0
for your_num in your_nums:
winners += 1 if your_num in winning_nums else 0
Count the Points:
Now, we need to add to our points variable based on how many winners were found on our card. We can do this as follows
points += 2**(winners-1) if winners > 0 else 0
And that's it!
The Code
points = 0
for card in input_list:
winning_nums = [int(i) for i in card.split(':')[1].split('|')[0].split(' ') if i.isdigit()]
your_nums = [int(i) for i in card.split(':')[1].split('|')[1].split(' ') if i.isdigit()]
winners = 0
for your_num in your_nums:
winners += 1 if your_num in winning_nums else 0
points += 2**(winners-1) if winners > 0 else 0
print(points)
Part 2 Solution
Create Solution Structure
We can Recycle much of the code from our part 1 solution. Let's start with the following and build from there
for card in input_list:
winning_nums = [int(i) for i in card.split(':')[1].split('|')[0].split(' ') if i.isdigit()]
your_nums = [int(i) for i in card.split(':')[1].split('|')[1].split(' ') if i.isdigit()]
winners = 0
for your_num in your_nums:
winners += 1 if your_num in winning_nums else 0
In this part, we will need to reference the index of a given input line. We can update our input read for loop as follows to get the index
for ind_card, card in enumerate(input_list):
Additionally, let's add a list that we can use to track how many copies of each scratchcard we have at any given time. We can do this above our for loop
cards = [1]*len(input_list)
Counting Card copies
After we have collected the number of winners on a given card, we can go through each subsequent card and distribute copies. Remember, we must distribute one copy for every copy of the card we just scratched.
for i in range(0,winners):
cards[ind_card+i+1] += cards[ind_card]
However, we must be sure not to distribute copies for indexes beyond the length of our input. Thus, we need to modify as follows
for i in range(0,winners):
if ind_card+i+1 < len(input_list):
cards[ind_card+i+1] += cards[ind_card]
That's it! Now we can print the sum of all of our cards. The full solution is below.
The Code
# part 2
cards = [1]*len(input_list)
for ind_card, card in enumerate(input_list):
winning_nums = [int(i) for i in card.split(':')[1].split('|')[0].split(' ') if i.isdigit()]
your_nums = [int(i) for i in card.split(':')[1].split('|')[1].split(' ') if i.isdigit()]
winners = 0
for your_num in your_nums:
winners += 1 if your_num in winning_nums else 0
for i in range(0,winners):
if ind_card+i+1 < len(input_list):
cards[ind_card+i+1] += cards[ind_card]
print(sum(cards))
Full code
Get the full code here.