Skip to content

Instantly share code, notes, and snippets.

@ijrussell
Last active March 6, 2022 20:32
Show Gist options
  • Save ijrussell/7ecf2fb05361a6e38ea68ff050b0473a to your computer and use it in GitHub Desktop.
Save ijrussell/7ecf2fb05361a6e38ea68ff050b0473a to your computer and use it in GitHub Desktop.
A,B,km,speed
Cogburg,Copperhold,1047,91
Leverstorm,Irondale,629,89
Cogburg,Steamdrift,1269,89
Copperhold,Irondale,345,91
Copperhold,Leverstorm,569,91
Leverstorm,Gizbourne,866,91
Rustport,Cogburg,1421,93
Rustport,Steamdrift,1947,99
Rustport,Gizbourne,1220,96
Irondale,Gizbourne,526,97
Cogburg,Irondale,1034,98
Rustport,Irondale,1302,95
open System.IO
type Tree<'T> =
|Branch of 'T * Tree<'T> seq
|Leaf of 'T
type Waypoint = { Location:string; Route:(string * decimal) list; Duration:decimal }
type Connection = { From:string; To:string; Distance:int; Speed:int }
let lines =
Path.Combine(__SOURCE_DIRECTORY__, "resources", "data.csv")
|> File.ReadAllText
|> fun data -> data.Split(System.Environment.NewLine)
|> Array.skip 1
let myData = [
for line in lines do
match line.Split(",") with
| [|A; B; Km; speed|] ->
{ From = A; To = B; Distance = int Km; Speed = int speed }
{ From = B; To = A; Distance = int Km; Speed = int speed }
| _ -> ()
]
let generateChildren (wayPoint:Waypoint) =
myData
|> List.filter (fun x -> x.From = wayPoint.Location)
|> List.filter (fun x -> wayPoint.Route |> List.tryFind (fun z -> fst z = x.To) = None)
|> List.map (fun x ->
let duration = decimal x.Distance / decimal x.Speed
{ Location = x.To; Route = (x.From, wayPoint.Duration)::wayPoint.Route; Duration = duration + wayPoint.Duration })
let hasChildren wayPoint =
generateChildren wayPoint
|> List.isEmpty
|> not
let rec createTree hasChildren generateChildren finish (current:Waypoint) =
let generateTree = createTree hasChildren generateChildren
match hasChildren current && current.Location <> finish with
| true -> Branch(current, seq{for next in generateChildren current do yield (generateTree finish next)})
| false -> Leaf(current)
let findRoute start finish =
createTree hasChildren generateChildren finish { Location = start; Route = []; Duration = 0M }
let rec treeToList tree =
match tree with
| Leaf x -> [x]
| Branch (x, xs) -> x :: (List.collect treeToList (xs |> Seq.toList))
[<EntryPoint>]
let main argv =
findRoute argv.[0] argv.[1]
|> treeToList
|> List.filter (fun x -> x.Location = argv.[1])
|> List.minBy (fun x -> x.Duration)
|> fun x -> (x.Location, x.Duration)::x.Route |> List.rev |> List.tail
|> List.fold (fun acc (loc,time) -> fst acc + "\n" + $"%.2f{time}h ARRIVE {loc}", 0M) ($"00.00h DEPART {argv.[0]}", 0M)
|> fun x -> printfn "%s" (fst x)
0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment