about summary refs log tree commit diff
path: root/users/tazjin/aoc2023
diff options
context:
space:
mode:
Diffstat (limited to 'users/tazjin/aoc2023')
-rw-r--r--users/tazjin/aoc2023/day1.el52
-rw-r--r--users/tazjin/aoc2023/day2.el64
-rw-r--r--users/tazjin/aoc2023/day3.el110
3 files changed, 226 insertions, 0 deletions
diff --git a/users/tazjin/aoc2023/day1.el b/users/tazjin/aoc2023/day1.el
new file mode 100644
index 0000000000..b1a7faff02
--- /dev/null
+++ b/users/tazjin/aoc2023/day1.el
@@ -0,0 +1,52 @@
+(require 's)
+(require 'f)
+
+;; task 1
+
+(defun digit-p (c)
+  (and (> c ?0)
+       (<= c ?9)))
+
+(defun aocd1-sum-values (lines)
+  (-sum
+   (-map (lambda (line)
+           (let ((digits (-filter #'digit-p (string-to-list line))))
+             (string-to-number (string (-first-item digits) (-last-item digits)))))
+         lines)))
+
+(let ((lines (s-lines (s-trim (f-read "~/Downloads/input.txt")))))
+  (aocd1-sum-values lines))
+
+;; task 2
+
+(defun replace-written-numbers (input)
+  (with-temp-buffer
+    (insert input)
+    (let ((start 1))
+      (while (< start (point-max))
+        (format-replace-strings
+         '(("oneight" . "18")
+           ("twone" . "21")
+           ("threeight" . "38")
+           ("fiveight" . "58")
+           ("sevenine" . "79")
+           ("eightwo" . "82")
+           ("eighthree" . "83")
+           ("nineight" . "98"))
+         nil start (min (+ 10 start) (point-max)))
+        (format-replace-strings
+         '(("one" . "1")
+           ("two" . "2")
+           ("three" . "3")
+           ("four" . "4")
+           ("five" . "5")
+           ("six" . "6")
+           ("seven" . "7")
+           ("eight" . "8")
+           ("nine" . "9"))
+         nil start (min (+ 5 start) (point-max)))
+        (setq start (1+ start))))
+    (buffer-string)))
+
+(let ((lines (s-lines (s-trim (f-read "~/Downloads/input.txt")))))
+  (aocd1-sum-values (-map #'replace-written-numbers lines)))
diff --git a/users/tazjin/aoc2023/day2.el b/users/tazjin/aoc2023/day2.el
new file mode 100644
index 0000000000..9374d7862c
--- /dev/null
+++ b/users/tazjin/aoc2023/day2.el
@@ -0,0 +1,64 @@
+(require 'dash)
+(require 's)
+(require 'f)
+
+(defvar aoc23-day2-example
+
+  "Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
+Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
+Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
+Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
+Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green")
+
+;; part 1
+
+(cl-defstruct aoc23d2-set red green blue)
+
+(defun aoc23d2-parse-set (input)
+  (let ((set (make-aoc23d2-set :red 0 :green 0 :blue 0))
+        (colours (-map #'s-trim (s-split "," input))))
+    (cl-loop for colour in colours
+             do (pcase (s-split " " colour t)
+                  (`(,num "red") (setf (aoc23d2-set-red set) (string-to-number num)))
+                  (`(,num "green") (setf (aoc23d2-set-green set) (string-to-number num)))
+                  (`(,num "blue") (setf (aoc23d2-set-blue set) (string-to-number num)))))
+    set))
+
+(cl-defstruct aoc23d2-game id sets)
+
+(defun aoc23d2-parse-game (input)
+  (pcase-let* ((`(,id-str ,sets-str) (s-split-up-to ":" input 1 t))
+               (game-id (string-to-number (s-chop-left (length "Game ") id-str)))
+               (sets (-map #'aoc23d2-parse-set (s-split ";" sets-str t))))
+    (make-aoc23d2-game :id game-id :sets sets)))
+
+(defun aoc23d2-game-possible-p (game r g b)
+  (cl-every (lambda (set)
+              (and (<= (aoc23d2-set-red set) r)
+                   (<= (aoc23d2-set-green set) g)
+                   (<= (aoc23d2-set-blue set) b)))
+            (aoc23d2-game-sets game)))
+
+(let ((input (f-read "~/Downloads/input.txt")))
+  (-sum
+   (-map #'aoc23d2-game-id
+         (-filter (lambda (g) (aoc23d2-game-possible-p g 12 13 14))
+                  (-map #'aoc23d2-parse-game (s-lines (s-trim input)))))))
+
+;; part 2
+
+(defun aoc23d2-game-min-cubes-power (game)
+  (let ((r 0)
+        (g 0)
+        (b 0))
+    (-each (aoc23d2-game-sets game)
+      (lambda (set)
+        (setq r (max r (aoc23d2-set-red set)))
+        (setq g (max g (aoc23d2-set-green set)))
+        (setq b (max b (aoc23d2-set-blue set)))))
+    (* (max 1 r) (max 1 g) (max 1 b))))
+
+(let ((input (f-read "~/Downloads/input.txt")))
+  (-sum
+   (-map #'aoc23d2-game-min-cubes-power
+         (-map #'aoc23d2-parse-game (s-lines (s-trim input))))))
diff --git a/users/tazjin/aoc2023/day3.el b/users/tazjin/aoc2023/day3.el
new file mode 100644
index 0000000000..dd39c1b836
--- /dev/null
+++ b/users/tazjin/aoc2023/day3.el
@@ -0,0 +1,110 @@
+(defun aoc23d3-symbol-p (c)
+  (not (or (= c ? )
+           (and (>= c ?0)
+                (<= c ?9)))))
+
+(defun rectangle-for-bounds (bounds)
+  (let* ((start (save-excursion
+                     (goto-char (car bounds))
+                     (let ((col (current-column)))
+                       (forward-line -1)
+                       (move-to-column (max 0 (1- col))))
+                     (point)))
+         (end (save-excursion
+                (goto-char (cdr bounds))
+                (let ((col (current-column)))
+                  (forward-line 1)
+                  (move-to-column (1+ col)))
+                (point))))
+    (list start end)))
+
+(defun get-machine-part ()
+  (interactive)
+  (when-let* ((num-raw (number-at-point))
+              (num (abs num-raw))
+              ;; handles negative number edge case (bounds contain the `-')
+              (bounds-raw (bounds-of-thing-at-point 'number))
+              (bounds (if (< num-raw 0)
+                          (cons (1- (car bounds-raw)) (cdr bounds-raw))
+                        bounds-raw))
+              (rectangle (rectangle-for-bounds bounds))
+              (neighbours (apply #'concat
+                                 (apply #'extract-rectangle rectangle))))
+    (if (-any #'aoc23d3-symbol-p (string-to-list neighbours))
+        (cons num rectangle)
+      (cons nil rectangle))))
+
+
+(defun find-machine-parts (input)
+  (with-temp-buffer
+    (insert input)
+    (goto-char (point-min))
+    (save-excursion
+      (replace-string "." " "))
+
+    (cl-loop while (forward-word)
+             for result = (get-machine-part)
+             when (car result) collect (car result))))
+
+
+;; debugging
+
+(defvar aoc23d3-example "467..114..
+...*......
+..35..633.
+......#...
+617*......
+.....+.58.
+..592.....
+......755.
+...$.*....
+.664.598..")
+
+(defvar aoc23d3-example2 "12.......*..
++.........34
+.......-12..
+..78........
+..*....60...
+78..........
+.......23...
+....90*12...
+............
+2.2......12.
+.*.........*
+1.1.......56")
+
+(defvar aoc23d3-example3 "243.
+..*.
+....")
+
+(defun aoc23d3-debug (p)
+  "Interactive debugger for the solution, can be bound to a key in
+an input buffer. Dots should already have been replaced with
+spaces."
+  (interactive "P")
+  (unless p
+    (goto-char aoc23d3-last))
+  (rectangle-mark-mode 1)
+  (forward-word)
+  (setq aoc23d3-last (point))
+  (pcase (get-machine-part)
+    (`(nil ,b ,e) (progn (set-mark b)
+                          (goto-char e)
+                          (set-face-attribute 'region nil :background "#FAA0A0")))
+    (`(,num ,b ,e) (progn (set-mark b)
+                          (goto-char e)
+                          (set-face-attribute 'region nil :background "#d1ffbd")))
+    (other (deactivate-mark))))
+
+(cl-assert (= 4361 (-sum (find-machine-parts aoc23d3-example))) nil
+           "example from website is working")
+
+(cl-assert (= 413 (-sum (find-machine-parts aoc23d3-example2))) nil
+           "example from subreddit is working")
+
+(cl-assert (= 243 (-sum (find-machine-parts aoc23d3-example3))) nil
+           "example from telegram is working")
+
+;; day 1 (incomplete)
+
+(-sum (find-machine-parts (s-trim (f-read "~/Downloads/input.txt"))))