commit d598c40185ca72b670d9f548d8a35f9273330e7c Author: eriedaberrie Date: Fri Dec 1 22:41:12 2023 -0800 2023 day 1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ec4d1ee --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.fasl +data.txt \ No newline at end of file diff --git a/2023/1/Main.hs b/2023/1/Main.hs new file mode 100644 index 0000000..e3ac098 --- /dev/null +++ b/2023/1/Main.hs @@ -0,0 +1,46 @@ +import Data.Char (isDigit, digitToInt) +import Data.Function (on) +import Data.List (tails, findIndex, isPrefixOf, minimumBy) +import Data.Maybe (mapMaybe) +import Data.Bifunctor (first) + +type LineOp = String -> Int + +wordMap :: [(String, Int)] +wordMap = [ ("one", 1) + , ("two", 2) + , ("three", 3) + , ("four", 4) + , ("five", 5) + , ("six", 6) + , ("seven", 7) + , ("eight", 8) + , ("nine", 9) + ] + +fullWordMap :: [(String, Int)] +fullWordMap = wordMap ++ (zip =<< map show) [1..9] + +opLineBasic :: LineOp +opLineBasic l = (combineDigits `on` ($ digitToInt <$> filter isDigit l)) head last + +firstNumInLine :: String -> [(String, Int)] -> Int +firstNumInLine l = fst . minimumBy (compare `on` snd) . mapMaybe numIndex + where + numIndex (str, num) = (num,) <$> findIndex (isPrefixOf str) (tails l) + +opLineAdvanced :: LineOp +opLineAdvanced l = (combineDigits `on` uncurry firstNumInLine) + (l, fullWordMap) + (reverse l, first reverse <$> fullWordMap) + +combineDigits :: Int -> Int -> Int +combineDigits = (+) . (10 *) + +opLines :: [String] -> Int +opLines = sum . map opLineAdvanced + +main :: IO () +main = do + content <- readFile "data.txt" + print . opLines . lines $ content diff --git a/2023/1/main-1.lisp b/2023/1/main-1.lisp new file mode 100644 index 0000000..36f6391 --- /dev/null +++ b/2023/1/main-1.lisp @@ -0,0 +1,23 @@ +(defpackage #:aoc-2023/1.1 + (:use #:cl) + (:export #:main)) + +(in-package #:aoc-2023/1.1) + +(defun digits-to-integer (a b) + (values (parse-integer (format NIL "~A~A" a b)))) + +(defun line-value (line) + (digits-to-integer (find-if #'digit-char-p line) + (find-if #'digit-char-p line :from-end T))) + +(defun main () + (format T + "~A~%" + (loop :for line := (read-line T NIL) + :while line + :unless (string= line "") + :sum (line-value line)))) + +(eval-when (:execute) + (main)) diff --git a/2023/1/main-2.lisp b/2023/1/main-2.lisp new file mode 100644 index 0000000..533417d --- /dev/null +++ b/2023/1/main-2.lisp @@ -0,0 +1,48 @@ +(defpackage #:aoc-2023/1.2 + (:use #:cl) + (:export #:main)) + +(in-package #:aoc-2023/1.2) + +(defparameter *numbers* '(("one" . 1) + ("two" . 2) + ("three" . 3) + ("four" . 4) + ("five" . 5) + ("six" . 6) + ("seven" . 7) + ("eight" . 8) + ("nine" . 9))) + +(defun digits-to-integer (a b) + (values (parse-integer (format NIL "~A~A" a b)))) + +(defun line-value (line) + (let* ((first-i (position-if #'digit-char-p line)) + (last-i (position-if #'digit-char-p line :from-end T)) + (first-val (when first-i (aref line first-i))) + (last-val (when last-i (aref line last-i)))) + (loop :for (str . num) :in *numbers* + :for first := (search str line) + :for last := (search str line :from-end T) + :when first + :do (when (or (null first-i) + (< first first-i)) + (setf first-i first) + (setf first-val num)) + (when (or (null last-i) + (> last last-i)) + (setf last-i last) + (setf last-val num))) + (digits-to-integer first-val last-val))) + +(defun main () + (format T + "~A~%" + (loop :for line := (read-line T NIL) + :while line + :unless (string= line "") + :sum (line-value line)))) + +(eval-when (:execute) + (main))