-
Notifications
You must be signed in to change notification settings - Fork 0
/
Program.fs
111 lines (87 loc) · 4.39 KB
/
Program.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
open System
open BenchmarkDotNet.Attributes
open BenchmarkDotNet.Running
type Coordinates =
{ X: int
Y: int }
module Utils =
let boolGrid grid = grid |> Array2D.map (fun x -> match x with 1 -> true | _ -> false)
module Iterative =
let isContainedCell coordinates islandCell =
let xRange = [| (coordinates.X - 1) .. (coordinates.X + 1) |]
let yRange = [| (coordinates.Y - 1) .. (coordinates.Y + 1) |]
xRange |> Array.contains islandCell.X
&& yRange |> Array.contains islandCell.Y
&& coordinates <> islandCell
let getIslands (grid: bool[,]) =
let mutable islands = []
for x = 0 to (grid |> Array2D.length1) - 1 do
for y = 0 to (grid |> Array2D.length2) - 1 do
let coordinates = { X = x; Y = y }
if grid.[x, y] then
let appendedIsland = coordinates :: (islands |> List.fold (fun newIsland island -> if (island |> List.exists (isContainedCell coordinates)) then newIsland @ island else newIsland) [])
let otherIslands = islands |> List.filter (fun island -> not (island |> List.exists (isContainedCell coordinates)))
islands <- appendedIsland :: otherIslands
islands
let getIslandCount (grid: bool[,]) =
grid |> getIslands |> List.length
module Recursive =
let getNewSurroundingCoordinates grid startingCoordinates currentIsland =
let minX = max 0 (startingCoordinates.X - 1)
let maxX = min ((grid |> Array2D.length1) - 1) (startingCoordinates.X + 1)
let minY = max 0 (startingCoordinates.Y - 1)
let maxY = min ((grid |> Array2D.length2) - 1) (startingCoordinates.Y + 1)
seq { for x in minX .. maxX do
for y in minY .. maxY do
let coordinates = { X = x; Y = y }
if grid.[x, y] && not (currentIsland |> Seq.contains coordinates) then yield coordinates
}
let rec buildIsland grid coordinates currentIsland =
let newSurroundingLandCoordinates = currentIsland |> getNewSurroundingCoordinates grid coordinates
currentIsland |> Seq.append (seq { for x in newSurroundingLandCoordinates do yield! buildIsland grid x currentIsland })
//let unionIsland existingIslands grid coordinates =
let getIslands (grid: bool[,]) =
let mutable islands = Seq.empty
grid |> Array2D.iteri(fun x y isLand-> if isLand then islands <- buildIsland grid { X = x; Y = y } Seq.empty)
islands
let getIslandCount (grid: bool[,]) =
grid |> getIslands |> Seq.length
open Utils
open Iterative
open Recursive
type GridCountBenchmark () =
let mutable emtpyGrid = array2D []
let mutable blackoutGrid = array2D []
let mutable grid = array2D [ [ 1; 0; 1; 0; 0; 1; 0; 0; ]
[ 0; 1; 0; 0; 1; 1; 1; 0; ]
[ 1; 0; 1; 0; 0; 1; 0; 0; ]
[ 0; 0; 0; 0; 0; 0; 0; 0; ]
[ 1; 1; 1; 1; 1; 1; 1; 1; ]
[ 1; 1; 1; 1; 1; 1; 1; 1; ]
[ 1; 1; 1; 1; 1; 1; 1; 1; ]
[ 1; 1; 1; 1; 1; 1; 1; 1; ] ]
[<Params (1, 10, 100)>]
member val public GridSize = 0 with get, set
[<GlobalSetup>]
member self.GlobalSetupData() =
emtpyGrid <- Array2D.create self.GridSize self.GridSize false
blackoutGrid <- Array2D.create self.GridSize self.GridSize true
[<Benchmark(Baseline = true)>]
[<BenchmarkCategory("Iterative")>]
member self.IterativeEmpty () = emtpyGrid |> getIslandCount
[<Benchmark>]
[<BenchmarkCategory("Iterative")>]
member self.IterativeBlackout () = blackoutGrid |> getIslandCount
[<EntryPoint>]
let main argv =
//let summary = BenchmarkRunner.Run typeof<GridCountBenchmark>
let grid = array2D [ [ 1; 0; 1; 0; 0; 1; 0; 0; ]
[ 0; 1; 0; 0; 1; 1; 1; 0; ]
[ 1; 0; 1; 0; 0; 1; 0; 0; ]
[ 0; 0; 0; 0; 0; 0; 0; 0; ]
[ 1; 1; 1; 1; 1; 1; 1; 1; ]
[ 1; 1; 1; 1; 1; 1; 1; 1; ]
[ 1; 1; 1; 1; 1; 1; 1; 1; ]
[ 1; 1; 1; 1; 1; 1; 1; 1; ] ]
grid |> boolGrid |> getIslandCount |> printfn "%i"
0 // return an integer exit code