Skip to content

Instantly share code, notes, and snippets.

@wyager
Created June 13, 2015 22:56
Show Gist options
  • Save wyager/adb7e752f147e2effe2a to your computer and use it in GitHub Desktop.
Save wyager/adb7e752f147e2effe2a to your computer and use it in GitHub Desktop.
import Data.Map (Map, fromList, toList, unionWith, adjust, insert)
import Data.List (isPrefixOf)
data Area = Savings | Food | FoodSavings | Investments | Expenses | Play deriving (Show, Read, Ord, Eq, Enum)
data Entry = Expense Area Integer | Credit Integer | Plan [(Area, Integer)] | Comment deriving (Show, Read)
type Savings = Map Area Integer
type Plan = Map Area Integer
noSavings = fromList [(area, 0) | area <- [Savings .. Play]]
defaultPlan = fromList $ (Savings, 100) : [(area, 0) | area <- [Food .. Play]]
process :: [Entry] -> Savings
process = fst . foldl update (noSavings, defaultPlan)
update :: (Savings, Plan) -> Entry -> (Savings, Plan)
update (savings, plan) entry = case entry of
Expense area amount -> (adjust (subtract amount) area savings, plan)
Credit amount -> (unionWith (+) (amount `splitBy` plan) savings, plan)
Plan new | sum (map snd new) == 100 -> (savings, fromList new)
| otherwise -> error "Plan doesn't add to 100%"
splitBy :: Integer -> Plan -> Savings
splitBy amount plan = fromList
[(area, (percent * amount) `div` 100) | (area, percent) <- toList plan]
parse :: String -> [Entry]
parse str = map read $ filter (not . isComment) (lines str)
where
isComment ('#':_) = True
isComment _ = False
main = do
entries <- parse `fmap` readFile "Savings.txt"
print $ process entries
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment