Skip to content

Instantly share code, notes, and snippets.

@seanlilmateus
Last active August 29, 2015 14:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seanlilmateus/67b9bef852652ae1f9dc to your computer and use it in GitHub Desktop.
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
#!/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