;;;; 2015.01.02-more-lispy-this-time.lisp ;;;; Advent of Code 2015 ;;;; Day 1: Not Quite Lisp ;;;; Attempt 2: More Lispy This Time ;; --------------------------------------------------------------------- ;;; Package Definition ;; --------------------------------------------------------------------- (defpackage :2015-01-02-more-lispy-this-time (:use #:common-lisp)) (in-package :2015-01-02-more-lispy-this-time) ;; --------------------------------------------------------------------- ;;; Definitions ;; --------------------------------------------------------------------- (defconstant +PUZZLE-INPUT-FILE+ "~/proj/Learn/aoc/src/2015.01._PUZZLE-INPUT.txt" "File to be used as input to the program.") (defconstant +PUZZLE-INPUT-STRING+ (uiop:read-file-string +PUZZLE-INPUT-FILE+) "String version of the text in `+PUZZLE-INPUT-FILE+'.") (defconstant +PUZZLE-INPUT-LIST+ (loop for char across +PUZZLE-INPUT-STRING+ collect char) "Puzzle input in lisp list form.") (defconstant +PUZZLE-INPUT-VALUES-LIST+ (mapcar (lambda (INPUT-LIST) (cond ((eql INPUT-LIST #\() 1) ((eql INPUT-LIST #\)) -1))) +PUZZLE-INPUT-LIST+) "Puzzle input converted into floor direction values.") ;; --------------------------------------------------------------------- ;;; Part 1 ;; ------- ;; Santa is trying to deliver presents in a large apartment building, but ;; he can't find the right floor - the directions he got are a little ;; confusing. He starts on the ground floor (floor 0) and then follows ;; the instructions one character at a time. ;; ;; An opening parenthesis, (, means he should go up one floor, and a ;; closing parenthesis, ), means he should go down one floor. ;; ;; The apartment building is very tall, and the basement is very deep; ;; he will never find the top or bottom floors. ;; ;; For example: ;; ;; (()) and ()() both result in floor 0. ;; ((( and (()(()( both result in floor 3. ;; ))((((( also results in floor 3. ;; ()) and ))( both result in floor -1 (the first basement level). ;; ))) and )())()) both result in floor -3. ;; ;; To what floor do the instructions take Santa? ;; --------------------------------------------------------------------- (defun final-floor (INPUT) "Calculate the final floor Santa ends up on given the provided `INPUT'." (apply #'+ INPUT)) (assert (= 138 (final-floor +PUZZLE-INPUT-VALUES-LIST+))) ;; --------------------------------------------------------------------- ;;; Part 2 ;; ------- ;; Now, given the same instructions, find the position of the first ;; character that causes him to enter the basement (floor -1). The first ;; character in the instructions has position 1, the second character ;; has position 2, and so on. ;; ;; For example: ;; ;; ) causes him to enter the basement at character position 1. ;; ()()) causes him to enter the basement at character position 5. ;; ;; What is the position of the character that causes Santa to first enter the basement? ;; --------------------------------------------------------------------- (defun next-floor () "Determine the result of the next button press, go in that direction, and destroy the information so the Nazis don't get their dirty hands on it." (let ((FLOOR-NUMBER 0) (INPUT-POSITION 0) (INPUT +PUZZLE-INPUT-VALUES-LIST+)) (lambda () (list (incf FLOOR-NUMBER (pop INPUT)) (incf INPUT-POSITION))))) (defvar next-floor (next-floor)) (defun first-basement-input () "Determine the position of the input in `+PUZZLE-INPUT-VALUES-LIST' which results in the first entry into the basement (floor -1)." (let ((RESULT (funcall next-floor))) (loop until (= -1 (car RESULT)) do (setf RESULT (funcall next-floor))) (cdr RESULT))) ;; Test for correct result (assert (= 1771 (first-basement-input)))