···11+* Reverse Polish Notation Calculator
22+33+[[https://en.wikipedia.org/wiki/Reverse_Polish_notation][Link for the wikipedia for the explanation]]
44+55+#+begin_src haskell
66+ import Data.List
77+#+end_src
88+99+#+RESULTS:
1010+1111+#+begin_src haskell
1212+ :{
1313+ solveRPN :: String -> Float
1414+ solveRPN = head . foldl foldingFunction [] . words
1515+ where foldingFunction (x:y:ys) "*" = (x * y):ys
1616+ foldingFunction (x:y:ys) "+" = (x + y):ys
1717+ foldingFunction (x:y:ys) "-" = (y - x):ys
1818+ foldingFunction (x:y:ys) "/" = (y / x):ys
1919+ foldingFunction (x:y:ys) "^" = (y ** x):ys
2020+ foldingFunction (x:xs) "ln" = log x:xs
2121+ foldingFunction xs "sum" = [sum xs]
2222+ foldingFunction xs numberString = read numberString:xs
2323+ :}
2424+2525+ solveRPN "10 10 10 10 sum 4 /"
2626+#+end_src
2727+2828+#+RESULTS:
2929+: Prelude Data.List> 10.0
3030+3131+* Heathrow to London
3232+3333+Your plane just landed in England and you rent a car.
3434+You have a meeting really soon and you have to get fro Heathrow Airport to London as fast as you can (but safely!).
3535+3636+There are two main roads going from Heathrow to London and there's a number of regional roads crossing them.
3737+It takes you a fixed amount of time to travel from one crossroads to another.
3838+It's up to you to find the optimal path to take so that you get to London as fast as you can!
3939+You start on the lest side and can either cross to the other main road or go forward.
4040+4141+Our job is to make a program that takes input that represents a road system and print out what the shortert path across it is.
4242+Here's what the input would look like for this care:
4343+4444+#+begin_example
4545+ 50
4646+ 10
4747+ 30
4848+ 5
4949+ 90
5050+ 20
5151+ 40
5252+ 2
5353+ 25
5454+ 10
5555+ 8
5656+ 0
5757+#+end_example
5858+5959+To mentally parse the input file, read it in threes and mentally split the road system into sections.
6060+Each section is comprised of a road A, road B and a crossing road.
6161+To have it neatly fit into threes, we say that there's a last crossing section that takes 0 minutes to drive over.
6262+That's because we don't care where we arrive in London, as long as we're in London.
6363+6464+To get the best path we do this: first we see what the best path to the next crossroads on main road A is.
6565+The two options are going directly forward or starting at the opposite road, going forward and then crossing over.
6666+We remember the cost and the path. We use the same method to see what the best path to the next crossroads on main road B is and remember that.
6767+Then, we see if the path to the next crossroads on A is cheaper if we go prom the previous A crossroads or if we to from the previous B crossroads and then cross over.
6868+We remember the cheaper path and then we to the same for the crossroads opposite of it.
6969+We do this for every section until we reach the end.
7070+Once we've reachead the end, the cheapest of the two paths that we have is our optimal path!
7171+7272+So in essence, we keep one shortest path on the road A and one path on the B road and when we reach the end, the shorter of those two ir our path.
7373+7474+#+begin_src haskell
7575+ :{
7676+ data Section = Section { getA :: Int, getB :: Int, getC :: Int } deriving (Show)
7777+ type RoadSystem = [Section]
7878+7979+ heathrowToLondon :: RoadSystem
8080+ heathrowToLondon = [Section 50 10 30, Section 5 90 20, Section 40 2 25, Section 10 8 0]
8181+8282+ data Label = A | B | C deriving (Show)
8383+ type Path = [(Label, Int)]
8484+8585+ roadStep :: (Path, Path) -> Section -> (Path, Path)
8686+ roadStep (pathA, pathB) (Section a b c) =
8787+ let priceA = sum $ map snd pathA
8888+ priceB = sum $ map snd pathB
8989+ forwardPriceToA = priceA + a
9090+ crossPriceToA = priceB + b + c
9191+ forwardPriceToB = priceB + b
9292+ crossPriceToB = priceA + a + c
9393+ newPathToA = if forwardPriceToA <= crossPriceToA
9494+ then (A,a):pathA
9595+ else (C,c):(B,b):pathB
9696+ newPathToB = if forwardPriceToB <= crossPriceToB
9797+ then (B,b):pathB
9898+ else (C,c):(A,a):pathA
9999+100100+ in (newPathToA, newPathToB)
101101+102102+103103+ optimalPath :: RoadSystem -> Path
104104+ optimalPath roadSystem =
105105+ let (bestAPath, bestBPath) = foldl roadStep ([], []) roadSystem
106106+ in if sum (map snd bestAPath) <= sum (map snd bestBPath)
107107+ then reverse bestAPath
108108+ else reverse bestBPath
109109+110110+ resolveProblem :: RoadSystem
111111+ resolveProblem roadSystem =
112112+ let path = optimalPath roadSystem
113113+ pathString = concat $ map (show . fst) path
114114+ pathPrice = sum $ map snd path
115115+ putStrLn $ "The best path to take is: " ++ pathString
116116+ putStrLn $ "The price is: " ++ pathPrice
117117+ :}
118118+119119+ resolveProblem heathrowToLondon
120120+#+end_src
121121+122122+#+RESULTS:
123123+: Prelude Data.List>
124124+: <interactive>:208:1-14: error:
125125+: Variable not in scope: resolveProblem :: RoadSystem -> t