;;; solver.el --- Day 09 -*- lexical-binding: t; -*- ;; ;; Copyright (C) 2022 Óscar Nájera ;; ;; Author: Óscar Nájera ;; Maintainer: Óscar Nájera ;; 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))))