You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

53 KiB

Solution to p10

This problem is pretty hard. I have not yet completely understood the linear algebra behind it.

  (with-temp-buffer
    (insert-file-contents "input")
    (advent/replace-multiple-regex-buffer
     '(("," . " ")
       ("^" . "(")
       ("$" . ")")
       ("\\[" . "\"")
       ("\\]" . "\"")
       ("{" . "(")
       ("}" . ")")
       ))
    (goto-char (point-min))
    (insert "(setq data '(")
    (goto-char (point-max))
    (insert "))")
    (eval-buffer))

For part 1 we do not need the last item This is a linear algebra problem in characteristic 2; we are essentially bruteforcing the vector space; we easily succeed.

For part 2, the same approach blows the stack even for the test input

  (setq machines (--map (-rotate 1 (cdr it)) data))

  (defun apply-button (joltage button)
    (--map-indexed (if (-contains-p button it-index) (- it 1) it) joltage))

  (defun good-buttons (machine)
    (-filter (lambda (button) (--every (< 0 (nth it (car machine))) button)) (cdr machine)))

  (defun solve-machines (machines)
    (-mapcat (lambda (machine)
  	     (if (= 0 (-sum (car machine))) (list machine)
  	       (--map (cons it (cdr machine)) (--map (apply-button (car machine) it) (good-buttons machine)))))
  	    machines ))

  (-iterate 'solve-machines (list (car machines)) 19)

Instead, go depth first and memoize for the win… This works for the test input, but takes forever for the true input.

  (setq machines (--map (-rotate 1 (cdr it)) data)
        machines (--map (cons (car it) (--sort (> (length it) (length other)) (cdr it))) machines))

  (defun apply-button (joltage button)
    (--map-indexed (if (-contains-p button it-index) (- it 1) it) joltage))

  (defun good-buttons (machine)
    (-filter (lambda (button) (--every (< 0 (nth it (car machine))) button)) (cdr machine)))

  (defun or-min (l)
    (when l (-min l)))

  (defun nil-1+ (l)
    (when l (1+ l)))

  (defun solve-machine (machine)
    (when machine
      (if (= 0 (-sum (car machine))) 0
        (nil-1+ (solve-machine (-first 'solve-machine (--map (cons it (cdr machine)) (--map (apply-button (car machine) it) (good-buttons machine)))))))))

  (memoize 'solve-machine)
  (-sum (-map 'solve-machine machines))
33

So we need to stop being a brute and realize that this is a linear algebra problem. Gauss elimination to the rescue. There is a little complication, since the matrices involved are degenerate and we have constraints;

  (setq machines (--map (-rotate 1 (cdr it)) data))

These are some auxiliary functions to create and deal with matrices

  (defun matrix-buttons (machine)
    "Takes MACHINE and returns the corresponding augmented matrix of the
  linear system.  The vector of constants is the first column vector
  instead of the last column as usual(it is more idiomatic this way)"
    (--map-indexed (cons it (--map (if (-contains-p it it-index) 1 0)
                                   (cdr machine)))
                   (car machine)))

  ;; These are convenience functions that we will use for row-reducing
  (defun find-pivot (row index)
    (let ((p (--find-index (not (= it 0)) (-drop index row))))
      (when p (+ p index))))

  (defun swap-indices (i j list)
    (if (= i j) list
      (let ((el-i (nth i list))
            (el-j (nth j list)))
        (-replace-at j el-i (-replace-at i el-j list)))))

  (defun subtract-indices (λ i j list)
    "Subtracts λ× element i from element j"
    (let ((el-i (nth i list))
          (el-j (nth j list)))
      (-replace-at j (- el-j (* λ el-i)) list)))

  (defun flip-index (i list)
    "Flip the sign of element i"
    (let ((el-i (nth i list)))
      (-replace-at i (* -1 el-i) list)))

  (defun subtract-composite (lambdas i list)
    (--each (-iota (length lambdas))
      (setq list (subtract-indices (nth it lambdas) i it list)))
    list)

  ; This is a routine for row-reducing the augmented matrix
  (defun row-reduce (matrix)
    (let* ((rMt (apply '-zip-lists matrix)) ;transpose
           (base-index 0))
      ; here we cannot use -map, since we are changing the matrix as we
      ; go
      (--each (-iota (1- (length rMt)) 1) ;skip over the constant
        (let* ((original-row (nth it rMt))
               (pivot-index (find-pivot original-row base-index)))
          (when pivot-index
            (setq rMt (--map (swap-indices base-index pivot-index it) rMt))
            (let* ((pivot-coeff (nth pivot-index original-row)))
              (when (< pivot-coeff 0)
                (setq rMt (--map (flip-index base-index it) rMt)))
              (if (not (= 1 (abs pivot-coeff))) (setq pivot-coeff (* 1.0 pivot-coeff)))
              (let* ((lambdas (append (-repeat (1+ base-index) 0)
                                      (-drop (1+ base-index) (nth it rMt))))
                     (lambdas-corrected (--map (/ it (abs pivot-coeff)) lambdas)))
                (setq rMt (--map (subtract-composite lambdas-corrected base-index it) rMt)
                      base-index (1+ base-index)))))))
      (apply '-zip-lists rMt)))
row-reduce
  (defun fix-machine (machine)
    (let ((machine-1 (let ((permutation (-grade-up '> (car machine))))
                       (cons (-sort '> (car machine)) (--map (--map (nth it permutation) it) (cdr machine))))))
      (cons (car machine-1)
            (--sort (< (-max it) (-max other))
                    (--sort (> (length it) (length other)) (cdr machine-1))))))


  (setq machines (-map #'fix-machine machines))
(29 26 26 12 9 26 26) (0 1 3 5) (1 2 4 5 6) (0 1 2 5 6) (0 2 3 4 6) (0 3 4 6)
(31 51 38 61 77 74 49 72) (1 3 4) (0 1 2 3 4 5) (1 3 4 5 6) (3 4 6) (0 4 5 7) (2 3 4 7) (1 5 7) (2 6 7) (0 5 7) (5 6 7)
(59 21 65 80 39 32 29 43) (1 2 3) (0 2 4 5 6) (0 3 6) (2 5 6) (0 2 3 4 5 7) (0 1 3 5 7) (0 2 3 4 7) (1 3 5 7)
(45 34 45 25 51 61 41) (0 1 2 3 4) (1 4) (0 2 3 5) (0 1 2 4 5 6) (0 2 3 5 6) (4 5 6)
(84 50 59 44 21 77 61 83) (0 1 3 4 5 6) (0 3 4 5 6) (0 1 3 5 6) (0 1 2 4 6 7) (0 1 5 6 7) (0 2 4 5 7) (0 2 3 5 7) (0 1 2 6 7) (2 6 7) (5 7)
(35 18 29 30 49 28 30 35 48) (1 2 3 4 6 7) (0 1 2 4 5 7) (0 2 7) (0 3 4 5 6 7 8) (0 1 3 4 6 8) (0 2 3 4 6 8) (2 4 5 7 8)
(45 8 50 30 16 45) (1 2) (0 2 3) (0 2 3 4 5) (1 2 4 5) (0 5) (2 5) (5)
(26 33 44 35 25 48 30 33 11 45) (2 5) (1 3 6) (1 7) (2 3 4 6 7 8) (0 1 2 4 5 6 7 9) (2 3 4 5 8 9) (1 3 5 7 9) (0 5 9) (3 9)
(49 37 54 32 31 23) (0 1 2) (0 1 2 3) (2 3 4) (0 2 3 4 5) (0 1 3 4 5) (0 2 4 5) (0 1 5) (4 5)
(46 18 33 22) (0) (0 1) (0 1 2) (0 2 3) (2 3)
(23 50 24 46 47 43) (0 1) (0 2 3) (0 1 3 4) (1 3 4) (2 3 4) (0 1 2 3 5) (1 4 5) (5)
(22 15 45 45 48 49) (0) (2 4) (0 2 3 4 5) (1 3 4 5) (0 1 2 5) (0 2 3 5) (2 3 4 5) (1 2 5)
(42 51 56 67 54 34 32 69 49) (0 3 4 5 6 7) (1 3 4 7) (2 6 7) (5 7) (0 1 2 3 4 5 8) (0 1 2 3 5 6 8) (1 3 4 7 8) (0 2 3 7 8) (1 2 4 8)
(74 36 61 78 36 34 19 46 17 29) (2 3) (1 3 4) (0 1 2 3 4 5 6 7) (0 2 3 7) (0 1 2 3 4 6 7 8) (0 1 3 4 5 7 8) (1 3 4 5 7 8) (0 2 3 5 8 9) (2 3 9) (0 9)
(30 19 38 38 32) (0 2 3) (2 3) (0 2 3 4) (1 4)
(42 58 43 59 47 32 29 70 66 53) (0 3 4 7) (4 7) (1 6 7 8) (0 8) (1 8) (0 1 2 3 6 7 8 9) (1 2 3 4 5 7 8 9) (0 3 4 5 7 8 9) (0 1 2 3 4 6 9) (1 2 5 6 7 9)
(9 194 203 18 194) (0 2 3) (1 2 3 4) (1 2 4)
(1 16 1 16) (0 2) (1 3)
(19 23 23 62 25 60 23) (0) (2) (3 4) (0 1 3 4 5) (3 5) (1 2 3 4 5 6) (0 3 4 5 6) (2 3 5 6) (1 2 5 6)
(38 71 40 20 34 45 46 22 57) (4) (0 1 2 6 7) (0 1 2 4 5 6 8) (1 2 3 5 6 7 8) (0 1 4 5 6 8) (1 2 3 8) (1 5 8)
(21 34 25 11 38) (1) (2) (0 2 3) (1 2 3) (0 1 4) (1 4) (4)
(18 24 25 33 23 31) (0 1 3) (1 3) (0 4) (0 2 3 4 5) (1 3 4 5) (1 5) (2 5)
(210 12 211 19 219) (0) (1 2) (0 2 3 4) (1 3 4) (0 2 4) (2 4)
(44 25 62 37 54 51 26 74 57) (0 2 5) (0 3 4 5 6 7) (0 3 7) (1 2 4 5 6 7 8) (0 2 3 4 5 7 8) (0 1 4 5 6 8) (1 3 5 6 7 8) (2 4 7 8)
(66 66 214 278 231 77 256 48 78 46) (2 3 4 6) (0 1 3 5 6 7) (0 2 7) (1 3 4 5 7 8) (0 2 3 4 6 8) (0 1 3 4 8) (3 6 8) (0 8) (0 2 3 5 6 8 9) (0 3 5 6 7 8 9) (1 3 4 5 6 9) (1 2 5 9) (3 6 9)
(19 13 16 50 42) (1 2 3) (0 3) (2 3 4) (3 4) (1 4)
(71 22 39 41 31 39 55) (0 2) (0 1 2 3 4) (2 4) (0 1 2 3 4 5) (0 3 4 5 6) (0 1 2 3 6) (0 3 5 6) (0 4 5 6)
(147 46 37 53 31 26 46 109 31) (1 2 3 5 6) (0 3 6) (0 7) (0 1 2 3 4 6 8) (0 1 3 4 5 6 8) (0 1 2 3 4 5 8) (1 4 8)
(11 11 10 6) (0 2) (1 2) (0 1 3)
(49 39 214 216 34 83 235 89 223 64) (2 3 5 6 7) (3 5 7 8) (2 3 6 8) (0 2 3 4 5 6 7 8 9) (1 2 3 5 6 7 8 9) (0 1 2 4 5 6 7 9) (0 1 5 6 7 8 9) (6 7 9)
(45 28 7 23 28 27 13 14 21) (0 1 3 4 5) (0 5 6) (2 6) (0 1 6 7) (0 1 2 3 6 7 8) (0 4 5 7 8) (0 8) (4 8)
(54 28 43 21 41 57 26) (0 2) (0 1 3 5) (1 2 4 5) (0 3 5) (2 5) (0 2 4 5 6) (0 1 4 6)
(38 18 3 17 18) (0 2) (0 3) (0 1 4) (1 2 4)
(163 183 34 36) (0 1) (1 2 3) (0 1 3) (1 3) (2 3)
(57 40 57 53 234 58 29 49 76 44) (0 1 2) (4) (3 5) (0 5 6) (0 1 2 4 5 7 8) (1 2 3 5 6 8) (2 3 4 7 8) (3 4 6 8) (0 3 4 5 7 8 9) (0 6 8 9) (5 7 8 9) (9)
(38 25 29 19 26 40 9 31) (0) (2 3 5) (3 4 5) (0 1 2 3 4 6) (0 5 6) (1 6) (0 1 2 4 5 7) (2 4 6 7) (3 5 7)
(9 1 27 8 1) (2) (0 2 3) (0 1 4)
(48 17 224 48 26 16) (0 1 2) (2) (0 3) (3) (0 1 2 4) (0 2 3 4) (0 2 3 4 5) (1 3 5)
(214 20 197 17) (0 1 2) (0 2) (0 1 3)
(25 50 13 26 27) (1 2) (1 3) (0 1 3 4) (1 2 4) (0 1 4)
(32 37 40 36 26 33 39 33 23) (2 5) (0 1 2 3 4 6 7) (0 1 2 3 5 6 7) (3 5 7) (1 3 4 6 7 8) (0 4 5 6 7 8) (0 3 5 6 8) (1 8)
(21 23 1 24 8 28 35) (3) (0 1 2 3 4 5) (1 4 5) (0 3 5 6) (1 6)
(92 58 43 92 54 73 46) (0 1 2) (0 1 2 3 4) (0 1 3 4 5) (0 2 3 5) (0 3 5) (2 3 4 5 6) (1 3 4 5 6) (0 3 4 6) (0 3 5 6)
(27 14 36 69 36 40) (0 1 3) (2 3 4) (4) (0 2 3 5) (1 3 5) (3 5)
(19 15 69 27) (1 2) (0 2) (2) (0 2 3) (2 3)
(57 154 139 128 143 13) (0 1 2) (1 3) (0 1 2 3 4) (1 2 3 4) (0 4) (0 3 4 5) (1 5)
(58 47 61 54 71 45 39 45) (3 4) (1 4 5) (4 5) (0 1 2 3 6) (4 6) (1 2 4 5 6 7) (0 1 5 6 7) (0 2 4 5 7) (0 1 2 3 7)
(87 24 5 78 65 95 69 62 69 62) (0 3) (5 6) (6) (3 4 5 7) (3 4 7) (1 3 4 5 8) (0 8) (5 8) (0 3 5 6 7 9) (0 4 6 7 8 9) (1 5 6 7 9) (2 3 4 5 9) (0 5 9)
(19 45 13 142 172 161 156) (1 2 4) (1 4 5) (0 3 4 5 6) (0 2 3 5 6) (3 4 5 6) (1 6)
(9 4 17 133) (1 2) (0 2) (2 3) (3)
(15 7 27 12 25 25) (0 2 3) (1 2 3) (2 3 4 5) (0 2 4 5) (1 3 4 5) (2 4 5)
(39 45 71 73 97 91 65 68 71) (0 4) (3 5 6) (1 2 3 4 5 6 7) (7) (0 1 2 3 4 5 6 8) (2 3 4 5 6 7 8) (0 1 2 4 5 8) (0 1 2 3 4 8) (0 2 4 7 8) (4 5 7 8) (8)
(6 35 41 16 13 35) (1 2 4) (0 2 3 5) (1 2 4 5) (1 2 3 5) (1 2 5)
(50 59 51 46 50 33 28 49 71 68) (6 7) (0 2 3 4 5 6 8) (1 4 8) (0 2 3 4 5 7 8 9) (1 2 4 6 7 8 9) (1 3 4 5 6 7 9) (0 1 2 5 8 9) (0 1 3 7 8 9) (2 3 4 5 9) (0 1 2 8 9) (7 9)
(46 19 31 32 25 32) (0) (1 3) (0 1 2 3 4) (1 2 3 4) (3 4) (3 4 5) (0 2 5)
(12 24 7 17 36) (1 3 4) (2 3 4) (1 2 4) (0 4)
(17 12 35 29 23 29) (0 2 4) (0 2 3 4 5) (2 3 4 5) (1 2 3 5)
(42 210 196 207 47 232 92 48 233 227) (4 6) (0 6) (0 1 2 4 5 6 8) (0 3 4 5 6 8) (1 3 6 7 8) (0 1 2 4 5 6 8 9) (0 2 4 5 7 8 9) (1 2 3 5 8 9) (1 3 5 7 8 9) (1 3 5 6 9) (2 5 6 8 9)
(177 139 153 37 38 62 49 56) (0 1 2) (1 2 3 4 5) (1 2 3 4 5 6) (0 1 2 4 5 6) (0 2 5 6) (2 4 6) (0 1 2 3 4 5 7) (0 3 6 7) (0 5 7) (7)
(189 197 199 38 46 190 25) (2) (0 2 3 4) (1 3 4) (0 1 2 3 4 5) (0 1 2 5) (2 5) (0 1 4 6) (0 3 4 6) (3 5 6)
(71 55 64 38 41 63 44) (2) (1 3 4) (0 1 3 4 5) (0 1 2 5) (0 5) (0 1 2 4 5 6) (0 1 2 4 6) (0 3 4 6) (2 3 6)
(220 33 198 38 18 55 42) (0 2) (1 3 5) (3 5) (0 2 3 4 5 6) (0 1 3 5 6) (1 2 4 6) (0 1 5 6) (3 6)
(71 27 201 51 60 53 41 39 56) (2) (3 4) (0 1 3 4 5 6 7) (0 1 3 5 6 7) (0 2 3 4 7 8) (0 4 5 6 8) (1 4 6 8) (0 2 5 8)
(33 37 33 38 40 33 51 38 33) (1 3) (4) (0 1 2 3 4 6) (3 6) (6 7) (0 2 4 5 6 7 8) (1 2 4 5 6 7 8) (0 1 2 3 5 7 8) (5 6 7 8)
(19 0 5 15 16 11) (0 1 3) (0 3 4) (1 2 4) (3 4) (0 2 3 5) (0 4 5)
(35 0 13 59 30) (2) (0 3) (3) (0 3 4) (2 3 4) (1 2 4) (4)
(20 15 5 20) (0 1 3) (0 2 3)
(22 11 11 31) (0 1 2) (0 1 3) (0 3) (2 3)
(11 1 11 1) (0 2) (1 3)
(45 45 32 29 45 43 28 49 38 32) (5 6) (0 3 4 5 7) (0 1 2 4 5 6 7 8) (0 1 4 5 6 7 8) (1 2 5 7 8) (0 3 4 6 9) (1 2 8 9) (1 7 9)
(8 9 6 23) (2 3) (1 3) (0 3)
(242 110 78 295 305 83 116 282 116 76) (0 3 4 7) (1 4 6 7) (0 6 7) (1 2 3 4 5 6 7 8) (0 1 2 3 5 6 7 8) (1 2 3 4 5 6 8) (0 1 3 4 6 7 8 9) (0 2 3 4 6 7 8 9) (1 3 4 5 6 7 8 9) (0 1 2 3 4 5 7 9) (1 2 3 4 6 8 9) (1 4 5 7 8 9) (0 4 5 8 9)
(5 5 0 23 23 5) (0 2 4) (3 4) (0 1 3 4 5) (1 2 5)
(9 13 22 13) (0 2) (1 2 3)
(51 29 19 41 52 29 38 34) (0 2 3 4) (4 5) (1 3 4 5 6) (3 6) (0 1 2 5 6 7) (0 1 5 6 7) (0 4 7)
(181 23 187 183) (1) (0 1 2) (1 2) (0 2 3) (1 3) (0 3)
(16 16 22 16 33) (0 2 3) (0 1 3) (1 2 3) (0 3) (0 3 4) (1 2 4) (4)
(41 32 18 32 27 24 21) (1 2 3) (0 4) (0 1 3 5) (1 2 3 6) (0 4 6) (5 6)
(42 195 42 45 188 221) (0 1 2 3 5) (0 2 3 4 5) (2 3 4 5) (0 1 5) (1 4 5) (0 3 5)
(28 187 185 45 187 30 171 35) (1) (0 1 2) (2 4) (2 3 5) (1 2 4 6) (0 1 2 4 5 6 7) (1 2 3 4 5 6 7) (0 1 3 4 6 7) (4 5 7)
(51 64 57 59 81 67 39 70 53 50) (1 4) (0 5 6 7) (1 2 3 4 5 6 7 8) (1 2 3 5 6 7 8) (0 4 5 6 7 8) (0 1 3 4 5 6 7 8 9) (0 2 3 4 5 7 8 9) (0 1 2 3 4 7 9) (0 2 3 5 9) (2 4 5 9) (1 5 9)
(151 20 21 130 150) (0 2) (0 1 2 4) (0 3 4)
(69 66 62 54 68 71 37 25 38) (0 1 2 3) (1 4) (4) (0 1 2 3 4 5) (0 3 4 5) (4 6) (0 1 2 3 5 6 7 8) (0 2 5 6 7 8) (1 5 6 7 8) (1 2 5 8)
(36 33 40 13 50 20) (0 3) (0 1 2 4) (2 4) (1 4 5) (0 2 5)
(18 210 210 14 10) (1 2) (0 1 2 3) (1 2 3) (0 4)
(24 15 9 0) (0 1) (0 2) (0 3)
(50 31 27 160 140 49 129 7 39 144) (0 1 3 4 5 6) (0 7) (0 3 5 6 8) (0 1 2 3 4 5 8 9) (1 2 4 6 7 8 9) (1 3 4 5 8 9) (0 2 3 5 8 9) (0 1 3 4 8 9) (3 4 6 9)
(52 60 212 241 50 32 21 221 51 92) (0 1 2 4 6 7) (2 3 7) (4 6 7 8) (0 1 3 4 5 7 8 9) (0 1 3 5 6 7 8 9) (2 3 4 5 6 7 9) (0 1 2 3 4 5 9) (0 1 4 6 7 8 9) (0 2 3 7 9) (2 3 7 8 9) (3 4 8 9) (1 9)
(2 26 26 17 19 24) (1 3) (0 1 2 4) (1 2 3 4 5) (1 2 5)
(53 34 19 122 32 140 151 51 44) (3 5 6) (0 1 2 3 5 7) (0 6 7) (0 1 3 5 6 7 8) (0 1 2 4 6 7 8) (0 1 4 5 7 8) (1 2 4 7 8) (0 1 7 8) (2 3 5 8) (4 5 6 8) (0 2 3 8)
(24 36 8 16 20) (0 2) (0 1 3) (1 3) (0 1 4) (1 4)
(27 40 47 51 31 38) (1 2 3) (3 4) (0 2 3 4 5) (0 1 2 5) (1 5)
(64 57 76 53 61 66 28 43 34 43) (0 1 2 4 5 7) (2 6 7) (0 7) (0 1 3 4 5 8) (0 1 2 3 4 6 7 9) (0 1 2 3 4 5 8 9) (0 1 2 3 4 7 8 9) (1 2 3 5 6 8 9) (0 2 3 4 5 9)
(39 57 68 14 50 54 35 70) (1 2 5) (2 4 6) (0 1 2 4 5 6 7) (0 1 2 5 6 7) (0 1 4 5 6 7) (0 1 3 4 7) (2 4 7) (5 7)
(19 21 20 27 32) (0 1 3) (1 2 3 4) (2 3 4) (0 4)
(32 10 12 12 40 32 50 12) (0 1 2 4 5) (4 5 6) (0 6) (4 6) (0 1 3 4 5 6 7) (0 2 3 4 5 6 7)
(225 75 226 54 241 203 20 182 39 208) (0 1 4) (1 2 3 4 5) (0 1 3 8) (0 1 2 4 6 7 8 9) (2 3 4 5 6 8 9) (1 2 3 4 6 8 9) (0 2 4 5 7 9) (0 1 2 4 9)
(37 32 46 56 23 40 37 56) (1 5) (0 1 4 6) (1 2 3 4 5 7) (0 2 3 5 6 7) (0 1 2 4 5 7) (0 2 3 6 7) (1 3 4 7)
(131 150 133 9 151) (1 2 3) (0 1 2 4) (0 3 4) (1 4) (3 4)
(79 59 72 88 29 73 77 23 38) (0 1 3 4) (2 5) (0 1 2 4 5 6) (0 1 2 3 6) (0 3 5 6) (5 6) (1 2 3 4 5 6 8) (0 2 3 6 7 8) (1 2 3 4 5 8) (1 3 4 7 8) (1 3 5 8)
(63 43 43 55 65 19 58 55) (0 1 2 3 4) (0 2 3 4 5 6) (0 1 3 4 6) (0 2 3 4 6 7) (0 1 2 3 6 7) (0 1 2 4 6 7) (0 2 6 7) (3 4 5 7)
(195 190 16 21 13 7 201) (1 2) (0 3 5) (0 3 6) (0 1 6) (4 6)
(30 11 29 17) (0) (0 2) (1 2) (3)
(70 36 63 23 42 69 62 71 89) (0 1 4) (1 2 6 7) (0 2 4 5 6 7 8) (0 3 5 6 7 8) (0 1 4 5 7 8) (2 3 5 7 8) (4 5 6 8) (0 2 5 8) (0 2 6 8) (3 8) (0 8)
(53 57 81 50 47 94 41 81) (0 1 2 5) (0 1 5) (2 5) (0 6) (0 1 2 3 6 7) (0 3 4 5 6 7) (4 5 6 7) (1 2 4 7) (2 3 5 7) (1 3 7)
(33 35 28 31 54 29 7) (0 2 4) (0 1 4) (3 4) (1 2 3 4 5) (0 2 3 4 5) (0 1 2 4 5) (0 3 4 5 6)
(72 32 62 50 29 71 30 45 60 75) (0 2 3) (0 1 2 5 7 8) (0 1 3 7 8) (6 8) (0 1 2 3 4 5 7 9) (0 1 3 4 6 7 8 9) (0 1 2 3 5 7 9) (2 4 5 6 8 9) (1 2 3 5 8 9) (2 4 6 8 9) (0 3 5 8 9) (0 5 7 9) (2 8 9)
(256 29 36 227 204 38 231) (0 1 2) (0 2) (0 1 3 4 5) (0 1 3 5 6) (0 3 4 6) (0 3 5 6) (0 5 6) (2 6)
(9 14 20 13) (1) (2) (0 2 3) (1 2 3) (0 3) (3)
(38 64 31 27 44 41 68) (1 4) (0 1 2 4 5 6) (0 1 2 3 6) (0 4 5 6) (1 4 5 6) (1 3 6)
(24 18 18 6) (0) (0 1 2) (1 3) (3)
(52 36 15 52 56) (0 1 2) (0 2 3) (0 1 3 4) (0 3 4) (1 3 4) (0 4)
(76 49 67 39 55 23 72 56 52) (0) (0 4) (0 5) (0 1 3 4 6 7) (1 2 7) (0 1 7) (0 2 3 4 6 8) (0 2 5 6 7 8) (1 2 4 6 7 8) (1 2 6 8)
(58 35 48 49 51 71 49 49) (0 1 3 4) (0 1 2 3 5 6) (0 4 5 6) (2 3 6) (1 2 3 4 7) (0 2 3 5 7) (0 4 5 7) (5 7)
(18 9 24 27 23 7) (1 3) (0 2 3 4) (1 2 3 4 5) (0 2 3 5)
(21 55 74 70 51 64 49 26 53) (0 2 3 5) (0 1 3 6) (2 4 6) (1 2 3 4 5 6 7) (0 1 3 5 6 7 8) (1 2 3 4 5 6 8) (1 3 4 5 7 8) (0 2 3 5 7 8) (1 2 3 5 8) (0 3 5 8)
(12 15 27 23 32 28) (0 3) (1 2 4) (1 2 3 4 5) (0 3 4 5) (2 4 5)
(49 66 35 36 41 85 24 59 66 58) (2) (2 3 5) (5 7) (3 7 8) (6 7 8) (1 5 8) (0 1 2 3 4 6 7 8 9) (0 1 2 4 5 7 8 9) (1 2 3 4 5 6 8 9) (1 3 5 6 7 8 9) (0 3 5 6 7 8 9) (0 1 4 5 9)
(32 36 28 28 46 32 41 45 30) (4) (1 4 5) (2 3 4 6) (0 2 3 6 7) (0 1 2 3 6 7 8) (1 5 7 8) (0 6 7 8)
(143 136 128 21 145 109 42) (1 2) (0 1 2 4 5) (2 4 5) (0 1 3 4 6) (0 3 4 6) (0 4 6) (0 6)
(30 29 30 165 131 61 11 13 24 71) (3 4) (3 4 5) (0 2 3 5 6 8 9) (0 2 4 5 7 8 9) (0 2 3 4 5 9) (3 5 7 8 9) (1 3 9) (1 5 9)
(43 18 34 48 32 32 23) (0 2 3 4 5) (0 3 4 5) (2 3 4 5 6) (0 1 2 3 6) (1 2 6)
(73 41 80 52 67 18 49 75 23 77) (0 2 3 4 6 7) (6 7) (0 1 3 4 5 7 8) (1 2 3 4 5 6 8 9) (0 1 2 3 7 9) (0 2 4 6 7 9) (0 2 3 5 9) (0 1 4 9) (2 3 7 9) (2 6 8 9) (2 4 9)
(145 13 158 145 13) (0 2) (0 2 3) (1 2 4)
(223 26 57 51 57 17 93 199 63 45) (0 6) (1 6) (0 2 3 4 5 6 7) (6 7) (0 7) (0 2 4 6 8) (0 2 3 4 6 7 8 9) (1 2 3 4 6 8 9) (0 1 3 7 8 9) (3 5 8 9)
(41 41 43 68 46 46 61 65 69 29) (1 6) (0 1 7) (3 4 7) (2 3 4 5 6 7 8) (0 2 3 6 7 8) (2 3 4 5 8) (3 5 8) (0 1 2 3 4 7 8 9) (1 2 3 4 7 8 9) (0 3 5 6 8 9) (0 3 4 6 8 9) (1 2 4 6 8 9) (5 6 8 9)
(48 83 75 50 66 48 89 93) (0 2 5) (3 4 5) (2 3 6) (4 6) (1 2 4 5 6 7) (0 1 2 3 6 7) (1 3 4 6 7) (2 4 5 6 7) (0 1 6 7) (1 4 7)
(60 34 40 115 126 23 109) (0) (1 3) (0 2 4) (0 1 2 5) (2 5) (0 1 2 4 5 6) (3 4 6)
(224 208 62 40 233 203 226 219) (0 1 2 3 4) (0 5) (0 1 2 5 6) (2 3 4 6) (6) (0 1 4 5 6 7) (0 2 3 6 7) (2 4 7) (7)
(44 67 46 53 27 70 71 65 45 44) (1 3 6) (0 5 6) (0 1 2 3 4 5 6 7) (0 1 2 4 5 6 7) (5 7) (1 3 4 6 7 8) (1 2 3 5 6 7 8 9) (0 1 2 5 8 9) (0 1 2 5 9) (0 3 6 9)
(157 16 30 30 64 29 43 43 47 49) (0) (4 6) (1 2 3 4 7) (0 1 2 3 4 6 7 8) (0 2 3 5 8) (0 2 4 7 8) (1 3 4 5 6 7 9) (4 5 6 7 8 9) (2 3 4 6 8 9) (3 4 5 6 8 9) (0 2 4 6 9) (0 9)
(8 20 37 4) (1) (0 1 2) (1 2) (2) (2 3) (1 3)
(60 71 64 56 11 87 91 44) (0 2 4 5) (0 1 2 3 5 6) (1 2 3 5 6) (0 1 2 6) (1 2 3 5 6 7) (1 3 5 6 7) (0 5 6 7)
(27 82 67 61 47 74 82 63 69 56) (1) (5) (0 4 5 7) (1 5 6 7) (1 2 3 4 5 6 7 8) (0 1 2 4 6 7 8) (1 2 3 6 8) (1 2 5 6 7 8 9) (2 3 4 6 7 9) (1 2 3 4 7 9) (1 4 5 6 8 9) (0 3 9)
(27 28 51 54 42 15 38 29 39 42) (1 3 4 7) (0 1 2 3 5 6 7 8) (0 2 6 8) (1 5 7 8) (0 2 3 4 6 7 8 9) (1 2 3 4 5 6 8 9) (1 2 5 6 9) (2 3 9) (0 4 9)
(53 23 71 30 38 44 28 45) (2 3 4) (2 5) (0 1 4 5 6) (2 5 6) (0 2 3 4 5 6 7) (0 1 2 7) (0 7)
(37 13 26 11 31 17 32 22) (0 4) (1 5) (0 2 3 4 5 6) (0 1 5 6) (0 1 4 7) (2 6 7)
(33 28 29 36 32) (1 2) (1 2 3) (0 3) (1 2 3 4) (2 3 4) (0 4)
(39 26 16 31 45 16 50 49) (1 2 3 5 6) (0 1 3 4 6 7) (2 3 4 5 6 7) (2 3 5 6 7) (0 1 4 7) (0 4 6 7)
(42 60 31 44 73 44 49) (0 2) (0 2 3) (0 1 2 3 4) (0 2 4 5) (5) (0 1 3 4 6) (1 3 4 5 6) (1 4 6)
(28 15 66 59 19) (2) (1 2 3) (2 3) (0 3) (0 2 3 4) (4)
(19 24 44 39 33 18 56 44 30) (2 5) (1 2 4 5 6) (2 6) (3 6 7) (3 7) (0 7) (1 2 4 8) (0 8) (4 8)
(22 32 28 28 24 36 14 17) (0 1 3 5) (2 5) (2 4 6) (0 1 2 4 5 6 7) (1 2 3 4 5 7) (0 2 3 5 6 7)
(55 23 31 58 49 66 80 65 72) (0 3) (0 1 4 6 7) (0 5 7) (2 3 4 5 6 7 8) (1 2 3 4 5 6 8) (0 4 5 6 7 8) (1 2 3 6 7 8) (3 6 7 8) (5 6 8) (0 3 8)
(29 33 4 16) (0 1) (1) (1 2) (0 1 3) (0 3)
(30 78 105 170 48) (0 1 2) (0 1 3) (1 3) (2 3) (1 3 4) (0 3 4) (1 4)
(31 81 67 81 83 40 55 17 29 78) (1 2 3 4 5) (1 3 4 5 6) (1 3 4 6) (2 6) (0 1 2 3 4 6 8) (0 1 2 3 5 7 8 9) (1 2 3 4 5 7 8 9) (0 1 2 3 4 6 9) (0 1 2 3 5 8 9) (2 4 9) (1 3 9) (4 9)
(166 154 173 176 17 183 166) (2 3) (2 4) (5) (0 2 3 4 5 6) (0 1 3 4 5 6) (0 1 2 3 5 6)
(33 181 19 39) (0 1) (1) (2) (0 2 3) (2 3) (3)
(148 7 155 155) (0 2 3) (1 2 3)
(138 146 47 31 160 41 32 24 54) (0 1 4) (0 1 2 3 4 5) (1 5 7) (3 4 7) (0 1 4 5 6 8) (0 2 3 5 8) (2 4 6 8) (4 5 7 8) (1 2 6 8)

This is the tricky part; we want solve the row-reduced form, but we need to be careful with our choices if we have more than one possibility

  (defun find-possible-indices (matrix i)
    (let* ((row (nth i matrix))
           (next-row (nth (1+ i) matrix))
           (i )
           (j (if next-row (--find-index (not (= 0 it)) (cdr next-row))
                (1- length row))))
      (-iota (- j i) i)))


  (defun solve-row-reduced (matrix)
    ;; we start from the last row
    (let* ((soln (list (-repeat (1- (length (car matrix))) 0)))
           (last-used-button (length (car soln)))
           (current-row (1- (length matrix))))
      (while (<= 0 current-row)
        (let* ((row (nth current-row matrix))
               (a (car row))
               (i (--find-index (not (= 0 it)) (cdr row))))
          (if i
              (let ((possible-indices (--filter (not (= 0 (nth it (cdr row))))
                                                (-iota (- last-used-button i) i))))
                (if (= 1 (length possible-indices)) ;no choices here, easy
                    (setq soln (-non-nil (--map (let* ((correction (advent/dot it (-replace-at i 0 (cdr row))))
                                                       (corrected-a (- a correction))
                                                       (pushes (/ corrected-a (nth i (cdr row)))))
                                                  (unless (< pushes 0) (-replace-at i pushes it)))
                                                soln))
                          last-used-button i
                          current-row (1- current-row))
                  ;;otherwise, we create a number of solutions
                  (let* ((button (-last-item possible-indices)))
                    (setq soln (--mapcat (let* ((correction (advent/dot it (-replace-at i 0 (cdr row))))
                                                (corrected-a (- a correction))
                                                (max-soln (/ corrected-a (nth button (cdr row)))))
                                           (if (< max-soln 0) (list it)
                                             (-map (lambda (candidate) (-replace-at button candidate it)) (-iota (1+ (round max-soln))))))
                                         soln)
                          last-used-button button))))
            (setq current-row (1- current-row)))))
      soln))

  (defun minimal-pushes (machine)
    (-min (-map #'-sum (solve-row-reduced (row-reduce (matrix-buttons machine))))))


  (setq problematic (--first (not (solve-row-reduced (row-reduce (matrix-buttons it)))) machines))

  (row-reduce (matrix-buttons problematic))
51.0 1.0 1.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0
31.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0
43.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0 1.0
10.0 0.0 0.0 0.0 1.0 0.0 1.0 -1.0 0.0 0.0 0.0
16.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0
23.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 1.0 -1.0 0.0
33.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 2.0 1.0
19.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2.0 -1.0 0.0






       ;; now, this is correct, but we need a positive solution that has
       ;; fewest button presses possible.

      (defun rank (matrix)
        (length (-non-nil (--map (--find-index (not (= 0 it)) (cdr it)) matrix))))

      (defun matrix-appl (matrix vector)
        (--map (advent/dot it vector) matrix))

      (defun solution-p (machine candidate)
        (--every (= 0 it) (matrix-appl (matrix-buttons machine) (cons -1 candidate))))

      (defun solve--machine (machine)
        (let ((candidate (solve-row-reduced (row-reduce (matrix-buttons machine)))))
          (and (--every (= (round it) it) candidate)
               (--every (>= it 0) candidate)
               (solution-p machine candidate) candidate)))

      (defun solve-machine (machine)
        (let* ((reduced-mat (row-reduce (matrix-buttons machine)))
               (rank (rank reduced-mat))
          (bunch (--map (cons (car machine) it)
                    (--filter (= rank (length it))
                              (-powerset (cdr machine))))))
          (-min (-map '-sum (-non-nil (-map 'solve--machine bunch))))))
  
  (-sum (-map 'solve-machine machines))
33