Last active
August 29, 2015 14:05
-
-
Save seanlilmateus/67b9bef852652ae1f9dc to your computer and use it in GitHub Desktop.
Swift version of http://learnyouahaskell.com/functionally-solving-problems, let's call it HaSwift
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
#!/usr/bin/env xcrun swift | |
// http://learnyouahaskell.com/functionally-solving-problems | |
enum Label : String { case A = "A", B = "B", C = "C" } | |
typealias Section = (Int, Int, Int) | |
typealias RoadSystem = [Section] | |
typealias Path = [(name:Label, price:Int)] | |
// Helpers, A little bit of F# in my life | |
infix operator |> { associativity left } | |
func |><T,U> (lhs: T, rhs: (T)->U ) -> U { | |
return rhs(lhs) | |
} | |
infix operator <| { associativity right } | |
func <| <T, U> (lhs: (T)->U, rhs: T ) -> U { | |
return lhs(rhs) | |
} | |
// function that prints the path as string instead of ((Enum Value).... | |
func pathDescription(xs:Path) -> String { | |
let res = join(", ", map(xs) { x in "(\(x.name.toRaw())-\(x.1))" }) | |
return "[\(res)]" | |
} | |
// functionality | |
func roadStep(pathA:Path, pathB:Path, section:Section) -> (Path, Path) { | |
let (a, b, c) = section | |
let priceA = reduce(pathA, 0) { (acc, lbl) in acc + lbl.1 }, | |
priceB = reduce(pathB, 0) { (acc, lbl) in acc + lbl.1 } | |
let forwardPriceToA = priceA + a, | |
crossPriceToA = priceB + b + c, | |
forwardPriceToB = priceB + b, | |
crossPriceToB = priceA + a + c | |
var newPathToA:Path?, newPathToB:Path? | |
// One day, this might be possible | |
// newPathToA = if forwardPriceToA <= crossPriceToA { [(.A, a)] + pathA } | |
// else { [(.C, c), (.B, b)] + pathB } | |
if forwardPriceToA <= crossPriceToA { | |
newPathToA = [(.A, a)] + pathA | |
} else { | |
newPathToA = [(.C, c), (.B, b)] + pathB | |
} | |
if forwardPriceToB <= crossPriceToB { | |
newPathToB = [(.B, b)] + pathB | |
} else { | |
newPathToB = [(.C, c), (.A, a)] + pathA | |
} | |
return (newPathToA!, newPathToB!) | |
} | |
func optimalPath(xs: RoadSystem) -> Path { | |
let (bestAPath, bestBPath) = reduce(xs, (Path(), Path())) { (acc, x) in | |
roadStep(acc.0, acc.1, x) | |
} | |
let priceA = reduce(bestAPath, 0) { (acc, path) in acc + path.price }, | |
priceB = reduce(bestBPath, 0) { (acc, path) in acc + path.price } | |
if priceA <= priceB { | |
return bestAPath |> reverse | |
} else { | |
return bestBPath |> reverse | |
} | |
} | |
let heathrowToLondon = [Section(50, 10, 30), Section(5, 90, 20), Section(40, 2, 25), Section(10, 8, 0)] | |
let result = optimalPath(heathrowToLondon) | |
println(result |> pathDescription) // [(B-10), (C-30), (A-5), (C-20), (B-2), (B-8), (C-0)] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment