Skip to content

Instantly share code, notes, and snippets.

@SteveGilham
Last active March 19, 2017 11:46
Show Gist options
  • Save SteveGilham/ccb8d6a8ac5e6aec77d8070e1e100f6d to your computer and use it in GitHub Desktop.
Save SteveGilham/ccb8d6a8ac5e6aec77d8070e1e100f6d to your computer and use it in GitHub Desktop.
open System.Linq
type Cell = North | East | West | Root
type Connected = { exit: Cell; West : Connected option; South : Connected option; East : Connected option }
let rows = 10
let cols = 10
let rand = System.Random()
let row () = Seq.append (Enumerable.Repeat(East, cols - 1)) (Seq.singleton Root) |> Seq.toList
let placeholder() = Enumerable.Repeat({ exit=Root; South=None; West=None; East=None}, cols) |> Seq.toList
let maingrid() = Enumerable.Repeat(placeholder(), rows - 1) |> Seq.toList
let key x =
match x.exit with
| North -> "N"
| East -> "E"
| West -> "W"
| _ -> "X"
let linked x =
match x.South with
| None -> " "
| _ -> "V"
let rec slice l cuts =
match cuts with
| [] -> []
| (x::xs) -> let (head, tail) = List.splitAt x l
head :: (slice tail xs)
// grow from the bottom up
let g = maingrid() |> List.scan (fun accum r -> let links = accum
|> List.map (fun cell -> match cell.exit with
| North -> Some cell
| _ -> None)
let runs = r
|> List.map (fun cell -> rand.Next(2))
|> List.scan ( + ) 0
|> List.tail
|> List.groupBy id
|> List.sortBy fst
|> List.map (fun (k, s) -> let l = Seq.length s
let cut = rand.Next(l - 1)
(l, [cut; 1; l - (cut+1)]))
let relinks = slice links (runs |> List.map fst)
let matched = List.zip relinks (runs |> List.map snd)
|> List.map (fun (link,cuts) -> let (e::n::w::[]) = slice link cuts
let e' = e
|> List.scan (fun accum cell -> Some { exit=East; South=cell; West=accum; East=None }) None
|> List.tail
|> List.map Option.get
let w' = w
|> List.rev
|> List.scan (fun accum cell -> Some { exit=West; South=cell; East=accum; West=None }) None
|> List.tail
|> List.map Option.get
|> List.rev
List.concat [e';
[{exit=North; South=List.head n; East=List.tryHead w'; West = List.tryLast e'}];
w'])
List.concat matched ) (placeholder())
|> List.tail
|> List.rev
let toprow = g
|> List.head
|> List.zip <| row ()
|> List.scan (fun accum (cell, exit) -> let s = match cell.exit with
| North -> Some cell
| _ -> None
Some { exit=exit; South=s; West=accum; East=None }) None
|> List.tail
|> List.map Option.get
let grid = toprow :: g;;
grid |> List.iter (fun r -> printf "+"
Seq.iter (fun cell -> match cell.exit with
| North -> printf " "
| _ -> printf "---"
printf "+") r
printfn ""
printf "| %s%s" (linked <| Seq.head r) (match (Seq.head r).East with
| None -> " "
| _ -> ">")
r |> Seq.pairwise
|> Seq.iter (fun cells -> let l = match (fst cells).exit, (snd cells).exit with
| (_, West)
| (East, _) -> (" ") // (East, West) never happens
| _ -> "|"
let x,y = match (snd cells).West, (snd cells).East with
| (Some _, Some _) -> ("<", ">")
| (Some _, _) -> ("<", " ")
| (_, Some _) -> (" ", ">")
| _ -> (" ", " ")
printf "%s%s%s%s" l x (linked <| snd cells) y)
printfn "|")
grid |> List.head |> (fun r -> printf "+"
Seq.iter (fun cell -> printf "---+") r
printfn "" )
;;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment