Commit Diff


commit - 18c13061da0c7b642446e64b7dc1a561c3958fc0
commit + dfca954de59ae6453cfc4e6aa21316dbe790a432
blob - f4b0f56ab9800d5825e2ce332f188bf935387e99
blob + 022893dd0baa944b9960b3546e89aa61caf49a9f
--- src/day-7.lisp
+++ src/day-7.lisp
@@ -3,18 +3,6 @@
   (:export #:day-7))
 (in-package #:aoc/day-7)
 
-(defparameter *operators-task-1* '(+ *))
-(defparameter *operators-task-2* '(+ * combine))
-
-(defun map-operator-combinations (function length operators)
-  (labels ((%map (current n)
-             (if (= n length)
-                 (funcall function current)
-                 (loop with nn = (1+ n)
-                       for operator in operators
-                       do (%map (cons operator current) nn)))))
-    (%map nil 0)))
-
 (defun number-digits (number)
   (if (zerop number)
       1
@@ -23,29 +11,27 @@
 (defun combine (num-1 num-2)
   (+ (* num-1 (expt 10 (number-digits num-2))) num-2))
 
-(defun calculate (operators numbers test-value)
-  (loop with current = (car numbers)
-        for operator in operators
-        for next in (cdr numbers)
-        do (setf current (funcall operator current next))
-        when (> current test-value)
-          do (return current)
-        finally (return current)))
+(defun test-value-valid-p (test-value numbers &optional combine-op)
+  (labels ((%solve (test-value numbers combine-op current)
+             (if (null numbers)
+                 (= current test-value)
+                 (if (> current test-value)
+                     nil
+                     (or (%solve test-value (cdr numbers) combine-op
+                                 (+ current (car numbers)))
+                         (%solve test-value (cdr numbers) combine-op
+                                 (* current (car numbers)))
+                         (and combine-op
+                              (%solve test-value (cdr numbers) combine-op
+                                      (combine current (car numbers)))))))))
+    (%solve test-value (cdr numbers) combine-op (car numbers))))
 
-(defun test-value-valid-p (test-value numbers operators)
-  (map-operator-combinations (lambda (operators)
-                               (when (= test-value (calculate operators numbers test-value))
-                                 (return-from test-value-valid-p t)))
-                             (1- (length numbers))
-                             operators)
-  nil)
-
 (defun day-7 (input)
   (loop for line = (read-line input nil)
         until (null line)
         for (test-value . numbers) = (read-number-list line)
-        when (test-value-valid-p test-value numbers *operators-task-1*)
+        when (test-value-valid-p test-value numbers)
           sum test-value into task-1
-        when (test-value-valid-p test-value numbers *operators-task-2*)
+        when (test-value-valid-p test-value numbers t)
           sum test-value into task-2
         finally (return (values task-1 task-2))))