diff options
Diffstat (limited to 'AoC2022/09/solver.el')
-rw-r--r-- | AoC2022/09/solver.el | 78 |
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)))) + + |