Skip to content

Commit

Permalink
adds 2023 day 6 solution
Browse files Browse the repository at this point in the history
  • Loading branch information
danprince committed Dec 6, 2023
1 parent 3e88058 commit a7df84d
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 0 deletions.
2 changes: 2 additions & 0 deletions 2023/day6.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Time: 7 15 30
Distance: 9 40 200
2 changes: 2 additions & 0 deletions 2023/day6.input
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Time: 38 94 79 70
Distance: 241 1549 1074 1091
49 changes: 49 additions & 0 deletions 2023/day6.lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
(ql:quickload :cl-ppcre)

(defparameter *input* (uiop:read-file-string "2023/day6.input"))

(defparameter *example* (uiop:read-file-string "2023/day6.example"))

(defun parse-ints (str)
"Parse all the positive integers out of a string."
(mapcar #'parse-integer (ppcre:all-matches-as-strings "\\d+" str)))

(defun parse-sparse-int (str)
"Parse a sparse integer (allows gaps between digits) out of a string."
(parse-integer (remove-if-not #'digit-char-p str)))

(defun count-ways-to-win (total-time record-distance)
"Count the number of ways you can beat the record distance with different
amounts of time holding the charging button."
(loop for holding-time from 0 to total-time
for moving-time = (- total-time holding-time)
for distance = (* holding-time moving-time)
count (when (> distance record-distance) 1)))

(assert (equal (count-ways-to-win 7 9) 4))
(assert (equal (count-ways-to-win 15 40) 8))
(assert (equal (count-ways-to-win 30 200) 9))

(defun part-1 (input)
(let* ((lines (split-sequence:split-sequence #\newline input))
(times (parse-ints (first lines)))
(distances (parse-ints (second lines))))
(reduce #'* (loop for time in times
for distance in distances
collect (count-ways-to-win time distance)))))

(defun part-2 (input)
(let* ((lines (split-sequence:split-sequence #\newline input))
(time (parse-sparse-int (first lines)))
(distance (parse-sparse-int (second lines))))
(count-ways-to-win time distance)))

;; There's certainly a much more efficient closed form solution here for part
;; two but it turns out that Common Lisp will crunch the numbers the naive way
;; in under a second. Not going to say no to that!

(part-1 *example*)
(part-1 *input*)

(part-2 *example*)
(part-2 *input*)

0 comments on commit a7df84d

Please sign in to comment.