simshadows

Advent of Code 2024 Solutions

All solutions on this page were written by me without reading any hints or solutions.

My solutions aren’t necessarily great, but they did the job and got me the answers.

My suggestion to run these solutions:

$ cat input.txt | ./solution.py

Links to the full challenge specifications are included throughout this document. The original specifications aren’t allowed to be reproduced, so I can’t repost them here.


Day 1 [Spec]

Part 1 Solution

#!/usr/bin/env python3

from sys import stdin

pairs = [tuple(map(int, s.split())) for s in stdin.readlines()]

(a, b) = (sorted([x[0] for x in pairs]), sorted([x[1] for x in pairs]))
print(sum(abs(x - y) for (x, y) in zip(a, b)))

Part 2 Solution

#!/usr/bin/env python3

from sys import stdin
from collections import Counter

pairs = [tuple(map(int, s.split())) for s in stdin.readlines()]

cnt = Counter(x[1] for x in pairs)
print(sum(x[0] * cnt[x[0]] for x in pairs))

Day 2 [Spec]

Part 1 Solution

#!/usr/bin/env python3

from sys import stdin
from itertools import pairwise

reports = [[int(x) for x in s.split()] for s in stdin.readlines()]
reports = [r for r in reports if (r == sorted(r) or r == sorted(r, reverse=True))]
print(sum(all(0 < abs(a - b) < 4 for a, b in pairwise(r)) for r in reports))

Part 2 Solution

My first solution:

In an attempt to make a more compact solution, I reimplemented with a lambda:

#!/usr/bin/env python3

from sys import stdin
from itertools import pairwise

is_safe = lambda r: (r == sorted(r) or r == sorted(r, reverse=True)) \
    and all(0 < abs(a - b) < 4 for a, b in pairwise(r))

reports = [[int(x) for x in s.split()] for s in stdin.readlines()]
print(sum(any(is_safe(r[:i] + r[i+1:]) for i in range(len(r) + 1)) for r in reports))

Day 3 [Spec]

Part 1 Solution

I cheated by using eval() rather than parsing out the mul() myself:

#!/usr/bin/env python3

from sys import stdin
from re import findall
from operator import mul

lines = "".join(stdin.readlines())
print(sum(eval(s) for s in findall(r"mul\([0-9]{1,3},[0-9]{1,3}\)", lines)))

Part 2 Solution

My first solution, retaining the use of eval():

My attempt at making a more compact solution:

#!/usr/bin/env python3

from sys import stdin
from re import findall
from operator import mul

lines = "".join(stdin.readlines())

solution = 0
do_mul = True
for s, do, _ in findall(r"(mul\([0-9]{1,3},[0-9]{1,3}\))|(do\(\))|(don't\(\))", lines):
    if not s:
        do_mul = do
    elif do_mul:
        solution += eval(a)
print(solution)

Day 4 [Spec]

Part 1 Solution

My first attempt gets the right solution, but the approach is quite ugly:

#!/usr/bin/env python3

from sys import stdin

arr1 = [s.strip() for s in stdin.readlines()]
arr2 = ["".join(arr1[i][j] for i in range(len(arr1))) for j in range(len(arr1[0]))]
if len(arr2) > len(arr1):
    (arr1, arr2) = (arr2, arr1)
(len1, len2) = (len(arr1), len(arr1[0]))

arr1b = [" "*len2]*len1 + arr1 + [" "*len2] + list(reversed(arr1)) + [" "*len2]*len1
arr3 = ["".join(arr1b[x + i][i] for i in range(len2)) for x in range((len1 * 3) + 1)]
print(sum(s.count("XMAS") + s.count("SAMX") for s in arr1 + arr2 + arr3))

(Yes, I’m just trying to make meme solutions. That’s why it’s so ugly lol.)

Alternative, nicer solution that just indexes into the existing graph:

#!/usr/bin/env python3

from sys import stdin
from itertools import product

arr = [s.strip() + "." for s in stdin.readlines()]
arr.append("."*len(arr[0]))

def found(i, j, di, dj, pos):
    return (pos == 4) or ((arr[i][j] == "XMAS"[pos]) and found(i+di, j+dj, di, dj, pos+1))

it = product(range(len(arr)), range(len(arr[0])), [-1, 0, 1], [-1, 0, 1])
print(sum(found(i, j, di, dj, 0) for i, j, di, dj in it if (di != 0 or dj != 0)))

Part 2 Solution

#!/usr/bin/env python3

from sys import stdin
from itertools import product

arr = [s.strip() for s in stdin.readlines()]

def found(i, j):
    return arr[i+1][j+1] == "A" \
        and "SSMMSSM".count(arr[i][j] + arr[i+2][j] + arr[i+2][j+2] + arr[i][j+2])
print(sum(found(i, j) for i, j in product(range(len(arr) - 2), range(len(arr[0]) - 2))))

Day 5 [Spec]

Part 1 Solution

Things are getting a bit tough to make meme solutions, so I went for whatever works this time around. This got me the right answer quickly:

But its runtime was pretty terrible. Doesn’t matter though since solutions aren’t timed. It only took a couple seconds anyway.

In preparation for Part 2, I converted the rules to a dict:

More-compact solution:

#!/usr/bin/env python3

from sys import stdin
from itertools import product, combinations

rules, updates = "".join(stdin.readlines()).strip().split("\n\n")
rules = [s.split("|") for s in rules.split()]
updates = [s.split(",") for s in updates.split()]
print(sum(
    int(update[len(update) >> 1]) for update in updates
    if not any((x, y) == (b, a) for (x, y), (a, b) in product(rules, combinations(update, 2)))
))

Part 2 Solution

Naive topological sort since it’s easier and it ran fast enough for this problem anyway:

More-compact (and honestly more-readable) solution that takes advantage of built-in sort:

#!/usr/bin/env python3

from sys import stdin
from itertools import combinations
from functools import cmp_to_key
from collections import defaultdict

_rules, updates = "".join(stdin.readlines()).strip().split("\n\n")
rules = defaultdict(set)
for a, b in (s.split("|") for s in _rules.split()):
    rules[int(a)].add(int(b))
updates = [[int(x) for x in s.split(",")] for s in updates.split()]

key_fn = cmp_to_key(lambda a, b: 1 if (a in rules[b]) else -1)
print(sum(
    sorted(update, key=key_fn)[len(update) >> 1] for update in updates
    if any((a in rules[b]) for a, b in combinations(update, 2))
))