Advent of Code '23 - day 13

Table of Contents

Part one and two are practically equals, except for a custom predicate for comparing lists. The lists in part two are considered equal if there is exactly one character that in the entire list that does not match its counterpart.

Input

Example

#.##..##.
..#.##.#.
##......#
##......#
..#.##.#.
..##..##.
#.#.##.#.

#...##..#
#....#..#
..##..###
#####.##.
#####.##.
..##..###
#....#..#

Part 1

(defun aoc23/rotate-map (lines)
  (let ((length lines)
        (buf '())
        (out '())
        (lines (reverse lines)))
    (dotimes (i (length (car lines)))
      (dolist (l lines)
        (setq buf (append buf (list (elt l i)))))
      (setq out (append out (list (concat  buf))))
      (setq buf '()))
    out))



  (defun aoc23/find-symmetry (input)
    (let ((buf nil)
        (res nil)
        (i 0))
      (while (and input (not res))
                                      ;(message "+ %S" buf)
                                      ;(message "- %S" input)

      (if (and (length> buf 0)
               (eq (take (length buf) input)
                      (take (length input) buf)))
          (setq res i)
        (progn
          (setq buf (cons (car input) buf))
          (setq input (cdr input))
          (setq i (1+ i))
          )))
      (or res 0)))

  (defun aoc23/part-1 (input)
    (let ((lines (string-split input "\n" t)))
      (+ (* 100 (aoc23/find-symmetry lines))
       (aoc23/find-symmetry (aoc23/rotate-map lines)))))

  (apply '+ (mapcar 'aoc23/part-1 (string-split input "\n\n" t)))


Part 2

  (defun aoc23/rotate-map (lines)
  (let ((length lines)
        (buf '())
        (out '())
        (lines (reverse lines)))
    (dotimes (i (length (car lines)))
      (dolist (l lines)
        (setq buf (append buf (list (elt l i)))))
      (setq out (append out (list (concat  buf))))
      (setq buf '()))
    out))

(defun aoc23/find-symmetry (input)
  (let ((buf nil)
        (res nil)
        (i 0))
    (while (and input (not res))
      ;(message "+ %S" buf)
      ;(message "- %S" input)

      (if (and (length> buf 0)
             (aoc23/eqish (take (length buf) input)
                          (take (length input) buf)))
        (setq res i)
      (progn
        (setq buf (cons (car input) buf))
        (setq input (cdr input))
        (setq i (1+ i))
        )))
  (or res 0)))


(defun aoc23/eqish (a b)
  (let ((diff 0))
    (while (and a b
              (<= diff 1))
      (let ((aa (car a))
          (bb (car b)))
      (dotimes (i (length aa))
        (unless (= (elt aa i)
                   (elt bb i))
          (setq diff (1+ diff)))))
      (setq a (cdr a))
      (setq b (cdr b)))
    (= diff 1)))

(defun aoc23/part-2 (input)
  (let* ((lines (string-split input "\n" t))
       (hsym (aoc23/find-symmetry lines))
       (vsym (aoc23/find-symmetry (aoc23/rotate-map lines))))
    (+ (* 100 hsym)
       vsym)))

(apply '+ (mapcar 'aoc23/part-2 (string-split input "\n\n" t)))