aoc2024

My solutions to the 2024 Advent of Code puzzles
git clone git://git.ethandl.dev/aoc2024
Log | Files | Refs | LICENSE

Utils.hs (2100B)


      1 module Utils (SolType(..), safeRead, liftMonadTuple, both, integerDiff, xor, (|||), replace) where
      2 
      3 data SolType =
      4     IntSol Integer
      5   | FloatSol Double
      6   | StrSol String
      7   | MaybeSol (Maybe SolType)
      8 
      9 instance Show SolType where
     10   show (IntSol n) = show n
     11   show (FloatSol n) = show n
     12   show (StrSol s) = s
     13   show (MaybeSol msol) = case msol of
     14     Just sol -> show sol
     15     Nothing  -> "Nothing"
     16 
     17 -- | Given a datatype that can be read, attempt to read it. Instead of giving an
     18 --   exception, this gives a Maybe monad.
     19 -- Example:
     20 -- >>> (safeRead @Integer) "120"
     21 -- Just 120
     22 -- >>> (safeRead @Integer) "hello"
     23 -- Nothing
     24 safeRead :: Read a => String -> Maybe a
     25 safeRead s = case reads s of
     26   [(value, "")] -> Just value
     27   _             -> Nothing
     28 
     29 -- | Given a tuple of monadic values, return a lifted monadic tuple
     30 -- Example:
     31 -- >>> liftMonadTuple (Just "test", Just "case 1")
     32 -- Just ("test","case 1")
     33 -- >>> liftMonadTuple (Just "test", Nothing)
     34 -- Nothing
     35 -- >>> liftMonadTuple (Nothing, Just "test")
     36 -- Nothing
     37 liftMonadTuple :: Monad m => (m a, m b) -> m (a, b)
     38 liftMonadTuple (mx, my) = do
     39   x <- mx
     40   y <- my
     41   return (x, y)
     42 
     43 -- | Given a function and a tuple of values that function can act on, apply the
     44 --   function to each tuple element
     45 -- Example:
     46 -- >>> both ((+) 1) (2, 3)
     47 -- (3,4)
     48 both :: (a -> b) -> (a, a) -> (b, b)
     49 both f (a, b) = (f a, f b)
     50   
     51 -- | Take the absolute difference between two integers
     52 -- Example:
     53 -- >>> integerDiff 2 3
     54 -- 1
     55 -- >>> integerDiff 3 2
     56 -- 1
     57 -- >>> integerDiff 3 4
     58 -- 1
     59 -- >>> integerDiff 4 3
     60 -- 1
     61 -- >>> integerDiff 2 5
     62 -- 3
     63 -- >>> integerDiff 1 3
     64 -- 2
     65 -- >>> integerDiff 3 9
     66 -- 6
     67 -- >>> integerDiff 3 3
     68 -- 0
     69 integerDiff :: Integer -> Integer -> Integer
     70 integerDiff x y
     71   | x < y     = y - x
     72   | otherwise = x - y
     73 
     74 xor :: Bool -> Bool -> Bool
     75 xor True False = True
     76 xor False True = True
     77 xor _ _ = False
     78 
     79 (|||) :: (a -> Bool) -> (a -> Bool) -> (a -> Bool)
     80 (|||) p q = \x -> p x || q x
     81 
     82 replace :: Eq a => a -> a -> [a] -> [a]
     83 replace og repl (x:xs)
     84   | x == og   = repl : replace og repl xs
     85   | otherwise = x : replace og repl xs
     86 replace _ _ [] = []