Some younger elf entered a bunch of silly product IDs and we have to identify them and total them up. This is really to ensure we’ve found them all.
Invalid product IDs can be found by finding numbers that are made up of repeating sequences. Examples provided by the puzzle are as follows: 55 (5 twice), 6464 (64 twice), and 123123 (123 twice).
Copied day1 into a day2 folder and update the example and input text files to the new puzzle. Instead of multiple lines this puzzle has a comma delimited list so I needed to use .split(",") on the string to create an array of ranges.
Each range then needed to be split into the beginning and ending value using .split("-"). Now we iterate through the range with a for loop.
id_range = i.split("-")
for n in range(int(id_range[0]), int(id_range[1])+1):
Now that we can see all the IDs it’s time to do some comparisons.
Part 1
For this part the sillyness made up half of the ID like the examples before. I checked if the ID was even and then compared one half to the other. If the ID was invalid I added it to an array and after all ranges and IDs were checked I summed all entries in the array. Completing the example portion was enough to parse the entire input text file.
Part 2
Instead of being able to break an ID into half this part expands the scope to include IDs that are the result of a repeating sequence of numbers. Examples are 12341234 (1234 two times), 123123123 (123 three times), 1212121212 (12 five times), and 1111111 (1 seven times).
Immediately I knew I wanted to check segments of each ID that went into the array a whole number of times. The below loop goes through every number from 1 to the length of the ID.
id_len = len(i)
for x in range(1, id_len):
if id_len % x == 0:
If id_len % x returns 0 there is no remainder and we can check if each of the sections of the ID are the same. So 123123123 has 2 numbers that divide into the length(9) evenly (1, 3).
The pattern has to repeat so we can ignore any x value greater than half of the length of the ID. I could speed this whole thing up by making that change.
I tried and failed for a while to create dynamic indexes for parts of the string. I could get it to work partially but it was too complicated and didn’t work for all cases.
if id[s:s+segment_length] == id[s+segment_length:s+segment_length+segment_length]:
This actually worked fine but writing a condition to ensure it stopped before the end of the array was tripping me up. After a while I decided to look into breaking a string into defined lengths.
from textwrap import wrap
x = 3
i_arr = wrap(id, x)
The above will split a string into an array of three equal pieces. This wrap() function applied to the ID results in an array we can iterate through more easily.
Look at how much simpler this is:
if i_arr[s] == i_arr[s+1]:
if s+1 >= len(i_arr)-1:
return True
This code is part of a for loop that goes through all segments of the id array and checks that they’re the same. If we’ve reached the end of the array and all segments are equal then we have found a silly ID.
This is one of those situations where I spent too much time doing something the wrong way only to do a quick search and find a better function.
Again once the example could be completed using this method the import text file went smoothly.
Listening to: Leon Bridges - Outta Line
Interactions
Comments
This blog uses a Mastodon and webmentions for comments. You can comment by replying on Mastodon/ActivityPub/Fediverse account or webmention.