aboutsummaryrefslogtreecommitdiffstats
path: root/AoC2022/09/solver.el
diff options
context:
space:
mode:
Diffstat (limited to 'AoC2022/09/solver.el')
-rw-r--r--AoC2022/09/solver.el78
1 files changed, 78 insertions, 0 deletions
diff --git a/AoC2022/09/solver.el b/AoC2022/09/solver.el
new file mode 100644
index 0000000..d1eac37
--- /dev/null
+++ b/AoC2022/09/solver.el
@@ -0,0 +1,78 @@
+;;; solver.el --- Day 09 -*- lexical-binding: t; -*-
+;;
+;; Copyright (C) 2022 Óscar Nájera
+;;
+;; Author: Óscar Nájera <hi@oscarnajera.com>
+;; Maintainer: Óscar Nájera <hi@oscarnajera.com>
+;; Created: December 09, 2022
+;; Modified: December 09, 2022
+;;
+;; This file is not part of GNU Emacs.
+;;
+;;; Commentary:
+;;
+;; Day 09
+;;
+;;; Code:
+
+(defsubst solver-diff (head tail)
+ (cons (- (car head) (car tail)) (- (cdr head) (cdr tail))))
+
+(defsubst solver-distance-1 (vec)
+ "Norm 1 distance."
+ (+ (abs (car vec)) (abs (cdr vec))))
+
+(defsubst solver-diagonal (vec)
+ (and (= 1 (abs (car vec))) (= 1 (abs (cdr vec)))))
+
+
+(defun solver-move (direction)
+ (cl-ecase direction
+ ('R (lambda (x) (cl-incf (car x))))
+ ('L (lambda (x) (cl-decf (car x))))
+ ('U (lambda (x) (cl-incf (cdr x))))
+ ('D (lambda (x) (cl-decf (cdr x))))))
+;; WARN This need to be bytecompiled otherwise the lambda is not capturing diff-v in the closure
+(defun solver-puller (diff-v)
+ (let ((distance (solver-distance-1 diff-v)))
+ (cond
+ ((or (<= distance 1)
+ (solver-diagonal diff-v)) #'identity)
+ ((= distance 2)
+ (pcase diff-v
+ (`(0 . ,d) (solver-move (if (= d 2) 'U 'D)))
+ (`(,d . 0) (solver-move (if (= d 2) 'R 'L)))))
+ ((= distance 3)
+ (lambda (x)
+ (funcall (solver-move (if (< 0 (car diff-v)) 'R 'L)) x)
+ (funcall (solver-move (if (< 0 (cdr diff-v)) 'U 'D)) x)))
+ (t (error "Head moved too far")))))
+
+(with-temp-buffer
+ (insert-file-contents "input")
+;; (insert "R 4
+;; U 4
+;; L 3
+;; D 1
+;; R 4
+;; D 1
+;; L 5
+;; R 2")
+ (let (path
+ (head (cons 0 0))
+ (tail (cons 0 0))
+ (moves
+ (thread-last
+ (split-string (buffer-string) "\n" t)
+ (mapcar (lambda (inst) (let ((move (split-string inst)))
+ (cons (intern (car move))
+ (string-to-number (cadr move))))))
+ )))
+ (dolist (move moves)
+ (dotimes (_ (cdr move))
+ (funcall (solver-move (car move)) head)
+ (funcall (solver-puller (solver-diff head tail)) tail)
+ (push (cons (car tail) (cdr tail)) path)))
+ (= 6384 (length (cl-remove-duplicates path :test #'equal))))
+
+