Created
December 1, 2023 18:30
-
-
Save skatenerd/825014f7ca0cedf1d35c0ab06937d4e5 to your computer and use it in GitHub Desktop.
AOC 2023 Day 1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module DayOne | |
( partOne, decodeLine, substringIndices, Digit (..), operateOnString, toLower, allDigits, firstDigit, lastDigit, scoreDigit, scoreLine, partTwo | |
) where | |
import qualified Data.Text as T | |
import qualified Data.Text.IO as TI | |
import qualified Data.Maybe as M | |
import qualified Data.List as L | |
import qualified Data.List.Safe as LS | |
-- ############# Data Structures ############## | |
data Digit = Zero | One | Two | Three | Four | Five | Six | Seven | Eight | Nine deriving (Show, Enum, Eq) | |
allDigits = enumFrom Zero | |
scoreDigit d = M.fromJust $ L.elemIndex d allDigits | |
-- ############################################# | |
toLower = operateOnString T.toLower | |
operateOnString f = T.unpack . f . T.pack | |
substringIndices target world = go world 0 | |
where go "" _ = [] | |
go remainingWorld currentIndex = | |
if L.isPrefixOf target remainingWorld | |
then currentIndex : go (tail remainingWorld) (currentIndex + 1) | |
else go (tail remainingWorld) (currentIndex + 1) | |
hitIndices :: Digit -> String -> [Int] | |
hitIndices target world = fullNameIndices ++ numeralIndices | |
where fullNameIndices = substringIndices (toLower (show target)) world | |
numeralIndices = substringIndices (toLower (show (scoreDigit target))) world | |
firstDigit :: String -> Maybe Digit | |
firstDigit s = LS.minimumBy score allDigits | |
where score a b = myCompare (hitIndices a s) (hitIndices b s) | |
myCompare [] [] = EQ | |
myCompare [] _ = GT | |
myCompare _ [] = LT | |
myCompare a b = compare (L.minimum a) (L.minimum b) | |
lastDigit :: String -> Maybe Digit | |
lastDigit s = LS.maximumBy score allDigits | |
where score a b = compare maxLeftHit maxRightHit | |
where maxLeftHit :: Maybe Int = (LS.maximum (hitIndices a s)) | |
maxRightHit :: Maybe Int = (LS.maximum (hitIndices b s)) | |
scoreLine :: String -> Int | |
scoreLine line = read $ map (head . show. scoreDigit) $ M.catMaybes [firstDigit line, lastDigit line] | |
partTwo :: IO () | |
partTwo = do | |
fileBody <- TI.readFile "/users/wailee.feman/Downloads/input.txt" | |
let allLines = T.lines fileBody | |
ints = map (scoreLine . T.unpack) allLines | |
answer = sum ints | |
print answer | |
-- part 1 | |
partOne :: IO () | |
partOne = do | |
fileBody <- TI.readFile "/users/wailee.feman/Downloads/input.txt" | |
let allLines = T.lines fileBody | |
ints = map (decodeLine . T.unpack) allLines | |
answer = sum ints | |
print answer | |
decodeLine :: String -> Int | |
decodeLine s = read [firstDigit, lastDigit] | |
where firstDigit = head digits | |
lastDigit = last digits | |
digits :: String | |
digits = filter isDigit s | |
isDigit :: Char -> Bool | |
isDigit c = elem c allDigitsString | |
allDigitsString :: String | |
allDigitsString = enumFromTo '0' '9' | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment