It’s Christmas time, which means once more, its time for Advent of Code (AoC). If you’re not familiar with AoC, you’re honestly missing out. I discovered it a few years ago, and have been hooked. In short, its 25 days of coding challenges. Each day there is a two part problem that follows a general story theme for the year. The objective is simple….answer the problem. You can use any technique or language you like. People use from C, to Rust, to Excel spreadsheets. I’ve even seen some people who make their best to use Splunk to solve it (works decently enough for some problems, not so much for others). I personally use Python generally.
There is a global leaders board that I will likely never make it on to because it’s generally filled in the first 30 minutes or sooner and I’m just not that fast. For me, its a challenge to get better at Python and programming in general. Over the years, I’ve learned a ton of new things just doing research trying to solve the problem. There is a sub reddit that people can use to post solutions, ask for help or ideas, or just generally screw around. This year, I discovered that my office actually has a dedicated effort with their actual developers to go through and complete AoC as part of their Dev-Cember activities. They have hosted a few workshops to talk about a particular problem, or just trade ideas. It’s pretty cool.
I will say as a rule, I try not to “cheat”. My goal is always to solve the problem without help however I will say that there are some asterisks with that statement. There are occasions when I will look at Reddit just to understand what the hell the problem is asking. Even though the problems are thoroughly described, sometimes its not always clear what is meant. When I submit an answer and I’ve troubleshot and debugged my code and it’s still wrong, I will occasionally find a working solution and run my input through it to see what the answer is to hopefully find a better reference to debug against. Finally, if I’m just stuck I will sometimes get ideas about the technique that other people are using, and try to translate it into something that is within my comprehension (or use it as a forcing function to learn something new). I don’t program for time, speed, or efficiency. I try to make it work although sometimes, I will figure out ways to optimize and will try to clean it up.
At the request of the person that runs AoC (Eric Wastl) I won’t copy/paste the day’s prompts, although I will summarize the general idea of the problem
Day 1: Historian Hysteria
For Day 1, our input is a line separated list. Each line has two integer numbers separated by spaces. The problems asks us to sort out each list (left and right lists) by value, and for each corresponding number in the sorted lists, figure out the difference, and then sum the differences.
This first part was pretty straight forward (honestly the only reason I’m writing about it is for completeness). I parsed the input into two lists
def get_data(): from os import path left = [] right = [] with open(path.join(path.dirname(__file__), 'input.txt'), 'r') as f: for line in f: line = line.strip().split() left.append(int(line[0])) right.append(int(line[1])) return left, right
And then sorted them. Then I just iterated through, and summed the differences.
def part1(left, right): answer = 0 left.sort() right.sort() for i in range(len(left)): answer += abs(left[i] - right[i])
Part 2
For the 2nd part, we need to change it a little bit. We need to iterate through the left list, and for each value that we find, figure out the number of times that value appears in the right list. Then we need to sum the product of the value * the number of times it’s in the right list. For example if the current value I am working on in the left list is 4, and it appears in the right list 3 times, then I would add a total of 12 to my running total.
def part2(left, right): answer = 0 for i in range(len(left)): found = right.count(left[i]) answer += left[i] * found
There are a few ways that I could tackle this problem. The first choice is to iterate through the right list for each value in the left list and count the number of times we find that value that we’re looking for. While it will absolutely work, there’s a lot of unneeded cycles involved. Instead, I used the list.count() function for each value I was looking for. One thing I could do to increase efficiency (at least I think it would) would be to find the unique values in the left list and use count on those as well and include that number in the product. That way I was only looking for each value once. I’d have to play with it and check the timing to see which one is faster (again not something I really care about though). You can see my complete code on my Github.