packages feed

aoc 0.2.0.0 → 0.2.1.0

raw patch · 2 files changed

+94/−2 lines, 2 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Utility.AOC: (:+) :: a -> a -> ComplexL1 a
+ Utility.AOC: conjugate :: Num a => ComplexL1 a -> ComplexL1 a
+ Utility.AOC: data ComplexL1 a
+ Utility.AOC: imagPart :: ComplexL1 a -> a
+ Utility.AOC: infix 6 :+
+ Utility.AOC: instance Control.Monad.Fix.MonadFix Utility.AOC.ComplexL1
+ Utility.AOC: instance Control.Monad.Zip.MonadZip Utility.AOC.ComplexL1
+ Utility.AOC: instance Data.Data.Data a => Data.Data.Data (Utility.AOC.ComplexL1 a)
+ Utility.AOC: instance Data.Foldable.Foldable Utility.AOC.ComplexL1
+ Utility.AOC: instance Data.Hashable.Class.Hashable a => Data.Hashable.Class.Hashable (Utility.AOC.ComplexL1 a)
+ Utility.AOC: instance Data.Traversable.Traversable Utility.AOC.ComplexL1
+ Utility.AOC: instance Foreign.Storable.Storable a => Foreign.Storable.Storable (Utility.AOC.ComplexL1 a)
+ Utility.AOC: instance GHC.Base.Applicative Utility.AOC.ComplexL1
+ Utility.AOC: instance GHC.Base.Functor Utility.AOC.ComplexL1
+ Utility.AOC: instance GHC.Base.Monad Utility.AOC.ComplexL1
+ Utility.AOC: instance GHC.Classes.Eq a => GHC.Classes.Eq (Utility.AOC.ComplexL1 a)
+ Utility.AOC: instance GHC.Classes.Ord a => GHC.Classes.Ord (Utility.AOC.ComplexL1 a)
+ Utility.AOC: instance GHC.Generics.Generic (Utility.AOC.ComplexL1 a)
+ Utility.AOC: instance GHC.Generics.Generic1 Utility.AOC.ComplexL1
+ Utility.AOC: instance GHC.Num.Num a => GHC.Num.Num (Utility.AOC.ComplexL1 a)
+ Utility.AOC: instance GHC.Read.Read a => GHC.Read.Read (Utility.AOC.ComplexL1 a)
+ Utility.AOC: instance GHC.Show.Show a => GHC.Show.Show (Utility.AOC.ComplexL1 a)
+ Utility.AOC: magnitude :: Num a => ComplexL1 a -> a
+ Utility.AOC: realPart :: ComplexL1 a -> a

Files

aoc.cabal view
@@ -20,7 +20,7 @@ -- PVP summary:     +-+------- breaking API changes --                  | | +----- non-breaking API additions --                  | | | +--- code changes with no API change-version:            0.2.0.0+version:            0.2.1.0  -- A short (one-line) description of the package. synopsis:           Utility functions commonly used while solving Advent of Code puzzles
src/Utility/AOC.hs view
@@ -12,6 +12,10 @@ {-# OPTIONS_GHC -Wno-incomplete-patterns #-} {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} {-# OPTIONS_GHC -Wno-type-defaults #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveTraversable #-}  module Utility.AOC (     -- * Pathfinding algorithms@@ -63,6 +67,12 @@     memo2,     memo3,     memo4,+    -- * ComplexL1 datatype+    ComplexL1 (..),+    realPart,+    imagPart,+    conjugate,+    magnitude,     -- * Miscellaneous     range,     rangeIntersect,@@ -74,7 +84,7 @@ ) where  import qualified Data.HashMap.Strict as HM-import Data.Hashable (Hashable)+import Data.Hashable (Hashable (hashWithSalt)) import qualified Data.Set as S import qualified Data.Heap as H import Data.List (permutations, genericIndex, groupBy)@@ -82,6 +92,12 @@ import System.IO.Unsafe (unsafePerformIO) import Control.Concurrent (threadDelay, newMVar, readMVar, modifyMVar_) import Data.Function (on)+import Data.Data (Data)+import GHC.Generics (Generic, Generic1)+import Foreign (Storable (sizeOf, peek, poke, peekElemOff, pokeElemOff, alignment), castPtr)+import qualified GHC.Ptr+import Control.Monad.Zip (MonadZip (mzipWith))+import Control.Monad.Fix (MonadFix (mfix))  createMinPrioHeap :: Ord a1 => (a1,a) -> H.MinPrioHeap a1 a createMinPrioHeap = H.singleton@@ -367,3 +383,79 @@ -- | Converts a list of booleans (parsed as a binary number) to an integer. binToDec :: Num a => [Bool] -> a binToDec = sum . zipWith (*) (map (2^) [0..]) . map (fromIntegral . fromEnum) . reverse++infix 6 :++-- | A @Complex@ number type whose instance requires the constituent type to only be part of @Num@ instead of @RealFloat@.+-- As a consequence of this, the @abs@ and @magnitude@ functions use the L1 metric instead of the L2 metric (which is quite useful for Advent of Code puzzles).+-- Also, @signum@ is performed element-wise and can only return one of 8 different values.+-- This breaks the equality @abs z * signum z == z@ that is true in the Complex datatype.+-- The functions @mkPolar@, @cis@, @polar@ and @phase@ are unimplemented for obvious reasons.+-- Unlike @Complex@, Ord and Hashable are supported. The Ord instance treats the values as tuples.+-- The name of the datatype contains "L1" in order to reflect these changes.+data ComplexL1 a = a :+ a deriving (Eq, Ord, Read, Show, Data, Generic, Generic1, Functor, Foldable, Traversable)++-- | Real part of a complex number.+realPart :: ComplexL1 a -> a+realPart (a :+ _) = a+-- | Imaginary part of a complex number.+imagPart :: ComplexL1 a -> a+imagPart (_ :+ b) = b++-- | Conjugate of a complex number.+conjugate :: Num a => ComplexL1 a -> ComplexL1 a+conjugate (a :+ b) = a :+ negate b+-- | (Taxicab) magnitude of a complex number.+magnitude :: Num a => ComplexL1 a -> a+magnitude (a :+ b) = abs a + abs b++instance Num a => Num (ComplexL1 a) where+    (+) :: Num a => ComplexL1 a -> ComplexL1 a -> ComplexL1 a+    (a:+b) + (c:+d) = (a+c) :+ (b+d)+    (*) :: Num a => ComplexL1 a -> ComplexL1 a -> ComplexL1 a+    (a:+b) * (c:+d) = (a*c - b*d) :+ (b*c + a*d)+    abs :: Num a => ComplexL1 a -> ComplexL1 a+    abs (a :+ b) = (abs a + abs b) :+ 0+    signum :: Num a => ComplexL1 a -> ComplexL1 a+    signum (a :+ b) = signum a :+ signum b+    fromInteger :: Num a => Integer -> ComplexL1 a+    fromInteger n = fromInteger n :+ 0+    negate :: Num a => ComplexL1 a -> ComplexL1 a+    negate (a :+ b) = (a :+ b) * ((-1) :+ 0)++instance Hashable a => Hashable (ComplexL1 a) where+    hashWithSalt :: Hashable a => Int -> ComplexL1 a -> Int+    hashWithSalt salt (a :+ b) = hashWithSalt (hashWithSalt salt a) b++instance Storable a => Storable (ComplexL1 a) where+    sizeOf :: Storable a => ComplexL1 a -> Int+    sizeOf a       = 2 * sizeOf (realPart a)+    alignment :: Storable a => ComplexL1 a -> Int+    alignment a    = alignment (realPart a)+    peek :: Storable a => GHC.Ptr.Ptr (ComplexL1 a) -> IO (ComplexL1 a)+    peek p           = do+                        let q = castPtr p+                        r <- peek q+                        i <- peekElemOff q 1+                        return (r :+ i)+    poke :: Storable a => GHC.Ptr.Ptr (ComplexL1 a) -> ComplexL1 a -> IO ()+    poke p (r :+ i)  = do+                        let q = castPtr p+                        poke q r+                        pokeElemOff q 1 i++instance Applicative ComplexL1 where+  pure :: a -> ComplexL1 a+  pure a = a :+ a+  (<*>) :: ComplexL1 (a -> b) -> ComplexL1 a -> ComplexL1 b+  f :+ g <*> a :+ b = f a :+ g b+  liftA2 :: (a -> b -> c) -> ComplexL1 a -> ComplexL1 b -> ComplexL1 c+  liftA2 f (x :+ y) (a :+ b) = f x a :+ f y b++instance Monad ComplexL1 where+  a :+ b >>= f = realPart (f a) :+ imagPart (f b)++instance MonadZip ComplexL1 where+  mzipWith = liftA2++instance MonadFix ComplexL1 where+  mfix f = (let a :+ _ = f a in a) :+ (let _ :+ a = f a in a)