#+title: A collection of helper functions for Advent of Code #+property: header-args :results none * Input manipulation #+begin_src emacs-lisp (require 'dash) (defun advent/replace-multiple-regex-buffer (regex-list) "Takes REGEX-LIST as an alist ( regex . replacement ) and applies each substitiution to the current buffer" (save-excursion (-each regex-list (lambda (x) (goto-char (point-min)) (replace-regexp (car x) (cdr x)))))) #+end_src * Maze processing #+begin_src emacs-lisp (defun advent/split-string-into-char-list (str) "Split the string into a list of chars" (--map (string-to-char it) (split-string str "\\|.+" t))) #+end_src #+begin_src emacs-lisp (defun advent/char-at (p l) "return the char at position P in the 2D list l" (nth (car p) (nth (cadr p) l))) #+end_src #+begin_src emacs-lisp (defun advent/coordinates-of (e li) "This takes a 2D list (a list of lists) of chars LI and an element E and returns a list of positions in LI that contain the element E. " (-map #'cadr (--filter (eq (car it) e) (-mapcat #'identity (-map-indexed (lambda (y l) (-map-indexed (lambda (x el) (list el (list x y))) l)) li))))) #+end_src * 2D geometry auxiliary functions Here a vector is just a list with two components; the "dot" function is a bit of an overkill tbh #+begin_src emacs-lisp :results none (defun advent/dot (a b) "Return the dot product of the two vectors" (-sum (-map (lambda (x) (* (car x) (cdr x))) (-zip-pair a b)))) (defun advent/neighbour (p dir) "Returns the neighbour to P in the direction DIR" (list (+ (car p) (car dir)) (+ (cadr p) (cadr dir)))) (defun advent/taxicab-distance (p q) "Returns the taxicab distance from P to Q" (+ (abs (- (car p) (car q))) (abs (- (cadr p) (cadr q))))) #+end_src These are two-dimensional equivalent of -map and -map-indexed #+begin_src emacs-lisp (defun -2map (fun li) (--map (-map fun it) li)) (defmacro --2map (form list) `(-2map (lambda (it) ,form) ,list)) (defun -2map-indexed (fun li) (-map-indexed (lambda (j row) (-map-indexed (lambda (i it) (funcall fun i j it)) row)) li)) (defmacro --2map-indexed (form li) `(-2map-indexed (lambda (it-index-1 it-index-2 it) ,form) ,li)) #+end_src * general purpose caching Add this function as an ~:around~ advice to any function to have its results cached in ~cache~. The symbol ~cache~ should be already bound #+begin_src emacs-lisp (defun cache-result (fun &rest r) (let ((c (assoc (cons fun r) cache))) (if c (cdr c) (let ((res (apply fun r))) (push (cons (cons fun r) res) cache) res )))) (defun memoize (fun) (setq cache nil) (advice-add fun :around 'cache-result)) #+end_src