39 lines
1.4 KiB
Haskell
39 lines
1.4 KiB
Haskell
{-# OPTIONS_GHC -Wno-missing-signatures #-}
|
|
|
|
module INSolver where
|
|
|
|
import Control.Monad
|
|
import Control.Monad.State
|
|
import Data.List (tails,find)
|
|
|
|
import INAST
|
|
|
|
-- solve :: Int -> InsuranceNetworkAST -> [INASTInsurerId]
|
|
solve i = maybe [] (map unNASTInsurerId . reverse . fst)
|
|
. find ((== 100) . snd)
|
|
. map foldMe
|
|
. tails
|
|
. flip execState []
|
|
. mapM potentialInsId
|
|
where
|
|
foldMe :: [(INASTInsurerId,INASTPercent)] -> ([INASTInsurerId],Int)
|
|
foldMe = foldr (\ (i',INASTPercent p) (ixacc,pacc) -> (i':ixacc,p+pacc)) ([],0)
|
|
|
|
-- | Result is sensitive to order of execution.
|
|
-- One thing not speficied in the problem statement is whether expressions
|
|
-- only apply to previous lines, or if they can be looking forward
|
|
-- Here we're assuming the former case holds true.
|
|
potentialInsId :: INASTLine -> State [(INASTInsurerId,INASTPercent)] ()
|
|
potentialInsId (INASTLine iid pct exprs) = do
|
|
insidpctx <- get
|
|
when (allExprEval i insidpctx exprs) (modify ((iid,pct) :))
|
|
|
|
allExprEval :: Int -> [(INASTInsurerId,INASTPercent)] -> [INASTExpr] -> Bool
|
|
allExprEval i xs = all (exprEval i (map fst xs))
|
|
|
|
exprEval :: Int -> [INASTInsurerId] -> INASTExpr -> Bool
|
|
exprEval i _ (INASTExprLt (INASTLt n)) = i < n
|
|
exprEval i _ (INASTExprGt (INASTGt n)) = i > n
|
|
exprEval i _ (INASTExprEq (INASTEq n)) = i == n
|
|
exprEval _ insx (INASTExprInsurerId insid) = insid `elem` insx
|