Advent of Code '23 - day 3
This might be one of the last days I'll be using elisp. The puzzles are taking longer to solve and I don't really forsee lots of free time in the coming week. The first part went pretty quickly. The second deserved a completely new approach, where I'd search for all stars first, and (rather ugly) look for neighboring numbers.
Input
Example
467..114.. ...*...... ..35..633. ......#... 617*...... .....+.58. ..592..... ......755. ...$.*.... .664.598..
Part 1
This solution scans the input row by row, character by character. If the current character is a number, it looks around for a special symbol. When done parsing, and it did see a special symbol, the number gets added to a list.
(defun string-numberp(s) (condition-case invalid-read-syntax (numberp(read s)) (error nil))) (defun aoc23/scan-point (point field) (let ((offsets '((-1 -1) (0 -1) (1 -1) (-1 0) (1 0) (-1 1) (0 1) (1 1))) (found nil)) (dolist (o offsets) (let ((point (list (+ (car point) (car o)) (+ (cadr point) (cadr o))))) (unless (or (< (car point) 0) (>= (car point) (length (car field))) (< (cadr point) 0) (>= (cadr point) (length field))) (let ((char (substring (nth (cadr point) field) (car point) (+ 1 (car point))))) (message "%s" char) (when (not (or (string= "." char) (string-numberp char))) (setq found t)))))) found)) (let ((field (string-split input)) (numbers '()) (current "") (eligable nil)) (dotimes (y (length field)) (let ((row (nth y field))) (dotimes (i (length row)) (let ((c (substring row i (+ 1 i)))) (if (string-numberp c) (progn (setq current (concat current c)) (when (aoc23/scan-point (list i y) field) (setq eligable t))) (unless (string= "" current) (when (eq eligable t) (setq numbers (append numbers (list (string-to-number current))))) (setq current "") (setq eligable nil))))) (unless (string= "" current) (when (eq eligable t) (setq numbers (append numbers (list (string-to-number current))))) (setq current "") (setq eligable nil)))) (apply '+ numbers))
Part 2
This
(defun string-numberp(s) (condition-case invalid-read-syntax (numberp(read s)) (error nil))) (defun aoc23/parse (i field) (when (and (>= i 0) (< i (length field))) (when (string-numberp (substring field i (1+ i))) (let ((start i) (end i)) (while (and (>= (1- start) 0) (string-numberp (substring field (1- start) start))) (setq start (1- start))) (while (and (< (1+ end) (length field)) (string-numberp (substring field end (1+ end)))) (setq end (1+ end))) (string-to-number (substring field start end)) )))) (defun aoc23/scan-pairs (offset input length) (let ((numbers '())) (when (aoc23/parse (1- offset) input) (setq numbers (append numbers (list (aoc23/parse (1- offset) input))))) (when (aoc23/parse (1+ offset) input) (setq numbers (append numbers (list (aoc23/parse (1+ offset) input))))) (let ((up (- offset (1+ length))) (down (+ offset (1+ length)))) (if (aoc23/parse up input) (setq numbers (append numbers (list (aoc23/parse up input)))) (progn (when (aoc23/parse (1- up) input) (setq numbers (append numbers (list (aoc23/parse (1- up) input))))) (when (aoc23/parse (1+ up) input) (setq numbers (append numbers (list (aoc23/parse (1+ up) input))))))) (if (aoc23/parse down input) (setq numbers (append numbers (list (aoc23/parse down input)))) (progn (when (aoc23/parse (1- down) input) (setq numbers (append numbers (list (aoc23/parse (1- down) input))))) (when (aoc23/parse (1+ down) input) (setq numbers (append numbers (list (aoc23/parse (1+ down) input)))))))) (when (eq 2 (length numbers)) (message "pair %S @ %d" numbers offset) (apply '* numbers)))) (let ((i 0) (l (length (car (string-split input)))) (ratios '())) (while (setq i (string-search "*" input i)) (let ((r (aoc23/scan-pairs i input l))) (when r (setq ratios (append ratios (list r))))) (setq i (1+ i))) (apply '+ ratios)) ;; (let* ((input "467..114.. ;; ...*...... ;; ..35..633.") ;; (s (string-search "*" input)) ;; (l (string-search "\n" input))) ;; (aoc23/scan-pairs s input (1+ l)))