Day 2

I probably should not have used so many . and used $ for some of these instead.

import System.IO
import Data.List

readArr :: String -> [Int]
readArr = map read.words

good :: [Int] -> Bool
good = all (\x -> 1<=x && x<=3) . ((\xs -> zipWith (-) (tail xs) (init xs)) . sort)

sorted :: [Int] -> Bool
sorted x = x == sort x || x == (reverse.sort) x

safe :: [Int] -> Bool
safe x = good x && sorted x

almostSafe :: [Int] -> Bool
almostSafe xs = (any safe . map (\idx -> take (idx-1) xs ++ drop idx xs)) [1 .. length xs]

main :: IO()
main = do 
          inp <- getContents
          let arr2D = map readArr (lines inp)
          (print . length . (filter safe)) arr2D
          
          (print . length . (filter almostSafe)) arr2D       

Day 3

Shoutout to Hutton’s Programming in Haskell for the parser.

import System.IO
import Control.Applicative
import Data.Char

newtype Parser a = P (String -> [(a,String)])

parse :: Parser a -> String -> [(a,String)]
parse (P p) inp = p inp

item :: Parser Char
item = P (\inp -> case inp of
                        [] -> []
                        (x:xs) -> [(x,xs)])
                        
instance Functor Parser where
    -- fmap :: (a -> b) -> Parser a -> Parser b
    fmap g p = P (\inp -> case parse p inp of
                               [] -> []
                               [(v,out)] -> [(g v, out)])

instance Applicative Parser where
    -- pure :: a -> Parser a
    pure v = P (\inp -> [(v,inp)])
    
    -- <*> :: Parser (a -> b) -> Parser a -> Parser b
    pg <*> px = P (\inp -> case parse pg inp of
                                [] -> []
                                [(g,out)] -> parse (fmap g px) out)

instance Monad Parser where
    -- (>>=) :: Parser a -> (a -> Parser b) -> Parser b
    p >>= f = P (\inp -> case parse p inp of
                              [] -> []
                              [(v,out)] -> parse (f v) out)

instance Alternative Parser where
    -- empty :: Parser a
   empty = P (\inp -> [])
   -- (<|>) :: Parser a -> Parser a -> Parser a
   p <|> q = P (\inp -> case parse p inp of
                             [] -> parse q inp
                             [(v,out)] -> [(v,out)])

sat :: (Char -> Bool) -> Parser Char
sat p = do
          x <- item
          if p x then return x else empty

digit :: Parser Char
digit = sat isDigit

char :: Char -> Parser Char
char x = sat (== x)

string :: String -> Parser String
string [] = return []
string (x:xs) = do
                   char x
                   string xs
                   return (x:xs)

nat :: Parser Int
nat = do
        xs <- some digit
        return (read xs)

mul :: Parser Int
mul = do
        string "mul("
        x <- nat
        string ","
        y <- nat
        string ")"
        return (x*y)
        
mul2 :: Parser Int
mul2 = do
         string "do()"
         return (-1)
   <|> do
         string "don't()"
         return (-2)
   <|> mul

   
solve1 :: String -> Int
solve1 [] = 0
solve1 xs = case (parse mul xs) of
                 [(a,b)] -> a + solve1(b)  
                 [] -> solve1 (tail xs)

    
solve2 :: Int -> String -> Int
solve2 _ [] = 0
solve2 f xs = case (parse mul2 xs) of
                 [(a,b)] -> if a<0 then solve2 (a+2) b else a*f+solve2 f b
                 [] -> solve2 f (tail xs)


main :: IO()
main = do 
          inp <- getContents
          print (solve1 inp)
          print (solve2 1 inp)

I know we can do without it since the parsing here is quite simple, but I wanted to try to understand Monads and stuff better. I guess it worked a bit?

Here is a solution without copying the parsing code from Hutton.

import System.IO
import Data.Maybe
import Data.List.Split
import Text.Read

mul :: String -> Maybe Int
mul ('m':'u':'l':'(':xs) = (*) <$> a <*> b
                           where
                                 (a:b:_) = map readMaybe $ splitOn "," $ splitOn ")" xs!!0++","
mul _ = Nothing

solve :: Int -> String -> [Int]
solve f s | isJust x              = zipWith (+) [jx*f,jx*(1-f)] $ solve f ts 
          | "don't()" == take 7 s = solve 0 ts
          | "do()"    == take 4 s = solve 1 ts
          | s==[]                 = [0,0]
          | otherwise             = solve f ts
          where x = mul s
                jx = fromJust x
                ts = tail s

main :: IO()
main = do 
          inp <- getContents
          let ans=solve 1 inp
          print(sum ans)
          print(ans!!0)

<
Previous Post
Cheesy Truffle Burger
>
Next Post
Haskell for Advent of Code (Day 4-7)