{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE UndecidableInstances #-}
module Hedgehog.Classes.Common.Equation
( LinearEquation(..), runLinearEquation, genLinearEquation
, LinearEquationTwo(..), runLinearEquationTwo, genLinearEquationTwo
, LinearEquationM(..), runLinearEquationM, genLinearEquationM
, QuadraticEquation(..), runQuadraticEquation, genQuadraticEquation
, CubicEquation(..), runCubicEquation, genCubicEquation
) where
import Hedgehog
import Hedgehog.Classes.Common.Gen
import qualified Hedgehog.Gen as Gen
import qualified Hedgehog.Range as Range
import qualified Data.List as List
import Data.Monoid (Endo(..))
data QuadraticEquation = QuadraticEquation
{ _quadraticEquationQuadratic :: Integer
, _quadraticEquationLinear :: Integer
, _quadraticEquationConstant :: Integer
}
deriving (Eq)
instance Show QuadraticEquation where
show (QuadraticEquation a b c) = "\\x -> " ++ show a ++ " * x ^ 2 + " ++ show b ++ " * x + " ++ show c
genQuadraticEquation :: Gen QuadraticEquation
genQuadraticEquation = do
a <- Gen.integral (Range.linear 0 15)
b <- Gen.integral (Range.linear 0 15)
c <- Gen.integral (Range.linear 0 15)
pure (QuadraticEquation a b c)
runQuadraticEquation :: QuadraticEquation -> Integer -> Integer
runQuadraticEquation (QuadraticEquation a b c) x = a * x ^ (2 :: Integer) + b * x + c
data LinearEquation = LinearEquation
{ _linearEquationLinear :: Integer
, _linearEquationConstant :: Integer
}
deriving (Eq)
instance Show LinearEquation where
showsPrec _ (LinearEquation a b) = shows a . showString " * x + " . shows b
showList xs = appEndo
$ mconcat
$ [Endo (showChar '[')]
++ List.intersperse (Endo (showChar ',')) (map (Endo . showsPrec 0) xs)
++ [Endo (showChar ']')]
runLinearEquation :: LinearEquation -> Integer -> Integer
runLinearEquation (LinearEquation a b) x = a * x + b
genLinearEquation :: Gen LinearEquation
genLinearEquation = LinearEquation <$> genSmallInteger <*> genSmallInteger
data LinearEquationM m = LinearEquationM (m LinearEquation) (m LinearEquation)
deriving instance (forall x. Eq x => Eq (m x)) => Eq (LinearEquationM m)
instance (forall x. Show x => Show (m x)) => Show (LinearEquationM m) where
show (LinearEquationM a b) = (\f -> f "")
$ showString "\\x -> if odd x then "
. showsPrec 0 a
. showString " else "
. showsPrec 0 b
runLinearEquationM :: Functor m => LinearEquationM m -> Integer -> m Integer
runLinearEquationM (LinearEquationM e1 e2) i = if odd i
then fmap (flip runLinearEquation i) e1
else fmap (flip runLinearEquation i) e2
genLinearEquationM :: Applicative m => Gen (LinearEquationM m)
genLinearEquationM = LinearEquationM <$> (pure <$> genLinearEquation) <*> (pure <$> genLinearEquation)
data LinearEquationTwo = LinearEquationTwo
{ _linearEquationTwoX :: Integer
, _linearEquationTwoY :: Integer
, _linearEquationTwoConstant :: Integer
}
instance Show LinearEquationTwo where
show (LinearEquationTwo x y c) = "\\x y -> " ++ show x ++ " * x + " ++ show y ++ " * y + " ++ show c
genLinearEquationTwo :: Gen LinearEquationTwo
genLinearEquationTwo = LinearEquationTwo <$> absGenInteger <*> absGenInteger <*> absGenInteger
where
absGenInteger = abs <$> genSmallInteger
runLinearEquationTwo :: LinearEquationTwo -> Integer -> Integer -> Integer
runLinearEquationTwo (LinearEquationTwo a b c) x y = a * x + b * y + c
data CubicEquation = CubicEquation
{ _cubicEquationCubic :: Integer
, _cubicEquationQuadratic :: Integer
, _cubicEquationLinear :: Integer
, _cubicEquationConstant :: Integer
}
instance Show CubicEquation where
show (CubicEquation x y z c) = "\\x -> " ++ show x ++ " * x ^ 3 + " ++ show y ++ " * x ^ 2 + " ++ show z ++ " * x + " ++ show c
genCubicEquation :: Gen CubicEquation
genCubicEquation = CubicEquation <$> genSmallInteger <*> genSmallInteger <*> genSmallInteger <*> genSmallInteger
runCubicEquation :: CubicEquation -> Integer -> Integer -> Integer -> Integer
runCubicEquation (CubicEquation a b c d) x y z = a * x + b * y + c * z + d