Elisp programming is fun :)

i just wrote a solution for adventofcode 2018 day 10 (Day 10 - Advent of Code 2018) in emacs lisp. it was really fun writing the iterations to another buffer :slight_smile: in case anybody’s interested, here’s my (not particularly emacs-like) code. if anybody has any suggestions for improvement, please let me know!

;; -*- lexical-binding: t; -*-

(setq lexical-binding t)

(require 'dash)
(require 's)
(require 'f)


(defun day10--parse-line (line)
  (cl-labels ((parse-pair (str)
		(->> str
		     (s-split ",")
		     (-map #'string-to-number))))
    (->> line
	 (s-split ">")
	 (-take 2)
	 (-map (lambda (p) (s-split "<" p)))
	 (-map #'cl-second)
	 (-map #'parse-pair))))

(defun day10--advance-coord (coord)
  (cl-destructuring-bind ((x y) (vx vy)) coord
    (list (list (+ x vx) (+ y vy)) (list vx vy))))

(defun day10--loop (coords)
  (-map #'day10--advance-coord coords))

(defun day10--print (elems)
  (let* ((coords (-map #'car elems))
	 (max-x (->> coords
		     (-map #'car)
		    (-max)))
	 (min-x (->> coords
		     (-map #'car)
		    (-min)))
	 (max-y (->> coords
		     (-map #'cl-second)
		     (-max)))
	 (min-y (->> coords
		     (-map #'cl-second)
		     (-min)))
	 (height (1+ (- max-y min-y)))
	 (width (1+ (- max-x min-x)))
	 (buf (get-buffer-create "*display*")))
    (if (or (> height 100) (> width 100))
	nil
      (cl-labels ((get-coord (p)
		    (list (- (car p) min-x)
			  (- (cl-second p) min-y))))
	(with-current-buffer buf
	  (erase-buffer)
	  (dotimes (j height)
	    (dotimes (i width)
	      (insert ","))
	    (insert "\n"))
	  (dolist (coord coords)
	    (cl-destructuring-bind (x y) (get-coord coord)
	      (goto-line (1+ y))
	      (move-to-column x)
	      (delete-char 1)
	      (insert "X")
	      )))
	'done
	))))

(defun day10-part1and2 (filename)
  (let ((coords (->> filename
		     (f-read)
		     (s-trim)
		     (s-lines)
		     (-map #'day10--parse-line))))
    (named-let my-loop ((coords coords) (i 0))
      (if (not (day10--print coords))
	  (message "too big")
	(progn
	  (message "loop: %d" i)
	  (read-char)))
      (my-loop (day10--loop coords) (1+ i)))))

(day10-part1and2 "input.txt")
4 Likes

Just came across this one, pretty neat, I might have to try it out. The only feedback I have for you is the structure:

(if (or (...) (...)) 
    nil 
  (cl-labels ...))

might be more clearly written as:

(unless (or (...) (...)) 
  (cl-labels ...)

YMMV. It just seems odd to have the positive match be nil and the else condition be actual code that needs to run, but that may just be me. Lots of fun though.

Gavin Freeborn did something like this https://youtu.be/N1PAC5vs15Y?si=dTxVbYuhebb52MQy

1 Like