Day 3: Mull It Over
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
Uiua
Regex my beloved <3
Run with example input here
FindMul β regex "mul\\((\\d+),(\\d+)\\)"
PartOne β (
&rs β &fo "input-3.txt"
FindMul
/+β‘(ΓΒ°βββ1_2)
)
IdDont β ββ‘"don't()"β
PartTwo β (
&rs β &fo "input-3.txt"
regex "mul\\(\\d+,\\d+\\)|do\\(\\)|don't\\(\\)"
β’(IdDont.
β1βββ
ββ‘"do()"β.
ββ1β
| IdDont.
β ⧻,
)
β½β=0ββ‘"do()".
β‘(ΓΒ°βββ1_2βFindMul)β
/+
)
&p "Day 3:"
&pf "Part 1: "
&p PartOne
&pf "Part 2: "
&p PartTwo
Lisp
Just did some basic regex stuff.
Part 1 and 2
(defun p1-mult (str)
"pulls out numbers and multiplies them, assumes already filtered by size"
(let ((vals (ppcre:all-matches-as-strings "\\d+" str)))
(apply #'* (or (mapcar #'parse-integer vals) '(0)))))
(defun p1-process-line (line)
"look for mul, do the mul, and sum"
(let ((ptrn "mul\\(\\d?\\d?\\d,\\d?\\d?\\d\\)"))
(apply #'+ (mapcar #'p1-mult (ppcre:all-matches-as-strings ptrn line)))))
(defun run-p1 (file)
(let ((data (read-file file #'p1-process-line)))
(apply #'+ data)))
(defun p2-process-line (line)
"looks for mul, do, and don't"
(let ((ptrn "(mul\\(\\d?\\d?\\d,\\d?\\d?\\d\\))|(do\\(\\))|(don't\\(\\))"))
(ppcre:all-matches-as-strings ptrn line)))
(defun p2-filter (data)
"expects list containing the string tokens (mul, do, don't) from the file"
(let ((process t))
(loop for x in data
when (string= "don't()" x)
do (setf process nil)
when (string= "do()" x)
do (setf process t)
when process
sum (p1-mult x))))
(defun run-p2 (file)
(let ((data (read-file file #'p2-process-line)))
;; treat the input as one line to make processing the do's and don't's easier
(p2-filter (flatten data))))
Elixir
defmodule AdventOfCode.Solution.Year2024.Day03 do
def part1(input) do
Regex.scan(~r/mul\((?<l>\d+),(?<r>\d+)\)/, input, capture: ["l", "r"])
|> Stream.map(fn l -> Enum.reduce(l, 1, &(&2 * String.to_integer(&1))) end)
|> Enum.sum()
end
def part2(input) do
input |> String.replace(~r/don't\(\).*(do\(\)|$)/Us, "") |> part1
end
end
Python
After a bunch of fiddling yesterday and today I finally managed to arrive at a regex-only solution for part 2. That re.DOTALL
is crucial here.
import re
from pathlib import Path
def parse_input_one(input: str) -> list[tuple[int]]:
p = re.compile(r"mul\((\d{1,3}),(\d{1,3})\)")
return [(int(m[0]), int(m[1])) for m in p.findall(input)]
def parse_input_two(input: str) -> list[tuple[int]]:
p = re.compile(r"don't\(\).*?do\(\)|mul\((\d{1,3}),(\d{1,3})\)", re.DOTALL)
return [(int(m[0]), int(m[1])) for m in p.findall(input) if m[0] and m[1]]
def part_one(input: str) -> int:
pairs = parse_input_one(input)
return sum(map(lambda v: v[0] * v[1], pairs))
def part_two(input: str) -> int:
pairs = parse_input_two(input)
return sum(map(lambda v: v[0] * v[1], pairs))
if __name__ == "__main__":
input = Path("input").read_text("utf-8")
print(part_one(input))
print(part_two(input))
Smalltalk
I wrote matchesActual
cause all of smalltalkβsstupid matchesDo:
or whatever donβt give you the actual match with captures, only substrings (that wasted a good 40 minutes).
Also smalltalk really needs an index operator
day3p1: input
| reg sum |
reg := 'mul\((\d\d?\d?),(\d\d?\d?)\)' asRegex.
sum := 0.
reg matchesActual: input do: [ :m | " + sum at end cause operator precedence"
sum := (m subexpression: 2) asInteger * (m subexpression: 3) asInteger + sum
].
^ sum.
day3p2: input
| reg sum do val |
reg := 'do(\:?n''t)?\(\)|mul\((\d{1,3}),(\d{1,3})\)' asRegex.
sum := 0.
do := true.
reg matchesActual: input do: [ :m |
val := m subexpression: 1.
(val at: 1) = $d ifTrue: [ do := (val size < 5) ]
ifFalse: [
do ifTrue: [
sum := (m subexpression: 2) asInteger * (m subexpression: 3) asInteger + sum.
]. ].
].
^ sum.