Last active
March 30, 2020 07:11
-
-
Save olligobber/9ac88131e83a80db45fed4cd0ba1e79d to your computer and use it in GitHub Desktop.
How many 1c, 7c, or 10c stamps do you need to total a given value
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import qualified DP | |
import Data.Map ((!)) | |
nextSubproblem :: DP.DPCalc Int Int () Int | |
nextSubproblem = do | |
this <- DP.thisSubproblem | |
return (this + 1) | |
subproblemSolver :: DP.DPCalc Int Int () Int | |
subproblemSolver = do | |
this <- DP.thisSubproblem | |
if this < 7 then | |
return this | |
else if this < 10 then | |
return (this - 6) | |
else do | |
less1 <- DP.getSolution (this-1) | |
less7 <- DP.getSolution (this-7) | |
less10 <- DP.getSolution (this-10) | |
return $ 1 + minimum [less1, less7, less10] | |
main :: IO () | |
main = do | |
total <- readLn | |
let dPTable = DP.runDP (DP.DP | |
{ DP.subproblemSolver = subproblemSolver | |
, DP.nextSubproblem = nextSubproblem | |
, DP.firstSubproblem = 0 | |
, DP.finalSubproblem = total | |
} ) () | |
print $ dPTable ! total |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module DP | |
( solutions | |
, thisSubproblem | |
, problemInput | |
, runDP | |
, getSolution | |
, DP(..) | |
, DPCalc | |
) where | |
import Data.Map.Lazy (Map) | |
import qualified Data.Map.Lazy as M | |
import Control.Monad.State (State) | |
import Control.Monad.State as S | |
data DPState i o r = DPState | |
{ solutions :: Map i o | |
, thisSubproblem :: i | |
, problemInput :: r | |
} | |
type DPCalc i o r x = DPState i o r -> x | |
data DP i o r = DP | |
{ subproblemSolver :: DPCalc i o r o | |
, nextSubproblem :: DPCalc i o r i | |
, firstSubproblem :: i | |
, finalSubproblem :: i | |
} | |
runDP :: Ord i => DP i o r -> r -> Map i o | |
runDP dp input = S.evalState | |
(runDP' (subproblemSolver dp) (nextSubproblem dp) (finalSubproblem dp)) | |
(DPState M.empty (firstSubproblem dp) input) | |
runDP' :: Ord i => DPCalc i o r o -> DPCalc i o r i -> i -> | |
State (DPState i o r) (Map i o) | |
runDP' subSolver nextSub finalSub = do | |
this <- S.gets thisSubproblem | |
solns <- S.gets solutions | |
thisSol <- S.gets subSolver | |
if this == finalSub then | |
return $ M.insert this thisSol solns | |
else do | |
next <- S.gets nextSub | |
probInput <- S.gets problemInput | |
S.put $ DPState (M.insert this thisSol solns) next probInput | |
runDP' subSolver nextSub finalSub | |
getSolution :: Ord i => i -> DPCalc i o r o | |
getSolution subproblem dpstate = case M.lookup subproblem $ solutions dpstate of | |
Nothing -> error "Solution is not calculated yet" | |
Just x -> x |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment