Skip to content

Instantly share code, notes, and snippets.

@essic
Last active December 4, 2020 14:38
Show Gist options
  • Save essic/d3679c12e9d79c4ea3960f4ebd21d573 to your computer and use it in GitHub Desktop.
Save essic/d3679c12e9d79c4ea3960f4ebd21d573 to your computer and use it in GitHub Desktop.
#!/usr/bin/env cabal
{-# LANGUAGE OverloadedStrings #-}
{- cabal:
build-depends:
, base ^>= 4.13.0.0
, unliftio ^>= 0.2.13.1
, text ^>= 1.2.4.0
, transformers ^>= 0.5.6.2
-}
import Control.Monad.IO.Class (MonadIO, liftIO)
import System.IO (IOMode(ReadMode), openFile)
import Data.Text.IO (hGetContents)
import Data.Text as T ( Text, words, unpack)
import Data.Text.Read (decimal)
import Data.Either (rights)
import Control.Monad.Trans.Maybe (runMaybeT, MaybeT(MaybeT))
import Data.Foldable as F ( Foldable(foldl) )
import Debug.Trace ( trace )
main :: (MonadIO m) => m ()
main = do
expenses <- readExpenses "../data/day1.txt"
results <- runMaybeT $ do
step1 <- fmap calculate (findTwoErrors 2020 expenses)
step2 <- fmap calculate (findThreeErrors 2020 expenses)
return (step1, step2)
liftIO $
case results of
Nothing -> print "Error"
Just r -> print r
readExpenses :: MonadIO m => Text -> m [Int]
readExpenses path = do
fileHandle <- liftIO . openFile (T.unpack path) $ ReadMode
content <- liftIO . hGetContents $ fileHandle
pure $ ints content
where
ints = fmap fst . rights . fmap decimal . T.words
calculate :: [Int] -> Int
calculate = F.foldl (*) 1
findThreeErrors :: (Monad m) => Int -> [Int] -> MaybeT m [Int]
findThreeErrors _ [] = MaybeT $ do return Nothing
findThreeErrors searchTarget (expense:xs) = MaybeT $ do
r <- runMaybeT $ findTwoErrors (searchTarget - expense) xs
case r of
Nothing -> runMaybeT $ findThreeErrors searchTarget xs
Just [a,b] -> return $ Just [expense,a,b]
Just wtf -> trace (show wtf) (return Nothing)
findTwoErrors :: Monad m => Int -> [Int] -> MaybeT m [Int]
findTwoErrors _ [] = MaybeT $ do return Nothing
findTwoErrors searchTarget (expense:xs) = MaybeT $ do
if localTarget `elem` xs
then return $ Just [localTarget,expense]
else runMaybeT $ findTwoErrors searchTarget xs
where
localTarget = searchTarget - expense
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment