Skip to content

Instantly share code, notes, and snippets.

@vba
Created May 13, 2019 19:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vba/1669ac1254326715dc4237242e0a2990 to your computer and use it in GitHub Desktop.
Save vba/1669ac1254326715dc4237242e0a2990 to your computer and use it in GitHub Desktop.
let fusionNeighbours (accumulator: int Set list) (neighbour: int Set) =
match accumulator with
| [] -> [neighbour]
| head :: tail ->
let intersect = neighbour |> Set.intersect
match (head |> intersect).Count with
| 2 -> (head |> (Set.union neighbour)) :: tail
| _ -> neighbour :: accumulator
let collection = [
[1; 2; 3] |> Set.ofList
[3; 4; 5] |> Set.ofList
[4; 5; 6] |> Set.ofList
[8; 9; 11] |> Set.ofList
[9; 10; 11] |> Set.ofList
]
collection
|> Seq.fold fusionNeighbours List.Empty
|> Seq.rev
|> printfn "Result: %A"
@victorbartel
Copy link

What about this one:

open System
open System
module Continents = 

    let matrix = [| 
                    [| 0; 0; 0; 0; 1 |]; 
                    [| 0; 0; 1; 0; 0 |]; 
                    [| 0; 0; 1; 0; 0 |];
                    [| 1; 0; 0; 0; 0 |];
                    [| 0; 0; 0; 0; 0 |];
                 |]

    type Segment = {landIndexes: Set<int>}
    type Cursor = {prevSegment: Segment; total: int}

    let toSet: seq<int> -> Set<int> = Seq.filter (fun x -> x >= 0 ) >> set 

    let initSegment = {landIndexes = Set.empty}

    let tupleToSet (x, y, z) = Set.ofList([x; y; z])

    let fusionNeighbours (accumulator: int Set list) (candidate: int Set) =
        match accumulator with
        | [] -> [candidate]
        | head :: tail ->
            let intersect = candidate |> Set.intersect
            match (head |> intersect).Count with
            | 2 -> (head |> (Set.union candidate)) :: tail
            | _ -> candidate :: accumulator

    let foldLands (acc: Cursor) (a: int []) =
        let intersect = acc.prevSegment.landIndexes |> Set.intersect 
        let mapTuples = fst >> (fun x -> [x - 1; x ; x + 1] |> Set.ofList)
        let currentLandIndexTuples = 
            (a 
                |> Seq.mapi (fun i x -> (i,x))
                |> Seq.filter (fun x -> (x |> snd) <> 0))
        let continentIndexes = 
            currentLandIndexTuples 
            |> Seq.map mapTuples
            |> Seq.fold fusionNeighbours []
        
        let discovery = 
            continentIndexes
            // |> Seq.fold 
            //     (fun (acc: Set<int> * int) x -> 
            //         printf "\r\nCounting  %A" acc
            //         let result = if (x |> intersect).Count = 0
            //                         then (x, (acc |> snd) + 1) 
            //                         else (x, (acc |> snd))
            //         if (acc |> fst |> Seq.length) > 0 && (acc |> fst |> Set.intersect x).Count < 2
            //         then (x, (acc |> snd) + 1)
            //         else (result |> fst, (result |> snd) - 1)
            //         ) (Set.empty, 0)
            |> Seq.filter (fun x -> (Set.intersect acc.prevSegment.landIndexes x).Count = 0) 
            |> Seq.length
            // |> snd

        let landIndexes = currentLandIndexTuples |> Seq.map fst |> Set.ofSeq 

        printf "\r\n found: %A \r\n" discovery
        printf " acc: %A \r\n" acc
        printf " continentIndexes: %A \r\n" continentIndexes

        { total = (discovery ) + acc.total; prevSegment = {landIndexes = landIndexes } }

    let countContinents x =
        (x |>
            Array.fold (foldLands) {prevSegment = initSegment; total = 0}).total

    let main args =
        matrix
        |> countContinents 
        |> (printf "Continents found: %d \r\n")
        0

Continents.main []

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment