Created
December 11, 2020 06:46
-
-
Save object/9bce347fa411e1cbea0d12a035b5804a to your computer and use it in GitHub Desktop.
AdventOfCode 2020, December 11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| type SeatStatus = | |
| | Floor | |
| | Empty | |
| | Occupied | |
| let parseStatus ch = match ch with | '.' -> Floor | 'L' -> Empty | _ -> Occupied | |
| let input = | |
| File.ReadAllLines("Data/input11.txt") | |
| |> Array.filter (not << String.IsNullOrEmpty) | |
| |> Array.map Seq.toArray | |
| |> Array.map (fun line -> line |> Array.map (fun ch -> parseStatus ch)) | |
| let getNeighbours (area : SeatStatus array array) position = | |
| let rows = area.Length | |
| let cols = area.[0].Length | |
| let row,col = position | |
| [| (row-1,col-1); (row-1,col); (row-1,col+1); (row,col-1); (row,col+1); (row+1,col-1); (row+1,col); (row+1,col+1) |] | |
| |> Array.filter (fun (row,col) -> row >= 0 && col >= 0 && row < rows && col < cols) | |
| let rec findSeat (area : SeatStatus array array) currentSeat getNextSeat = | |
| getNextSeat area currentSeat | |
| |> Option.bind (fun nextSeat -> | |
| let row, col = nextSeat | |
| match area.[row].[col] with | |
| | Empty | Occupied -> Some nextSeat | |
| | Floor -> findSeat area nextSeat getNextSeat) | |
| let getVisible (area : SeatStatus array array) position = | |
| let rows = area.Length | |
| let cols = area.[0].Length | |
| [| | |
| findSeat area position (fun _ position -> | |
| let row,col = position | |
| if row = 0 || col = 0 then None else Some (row-1,col-1)) | |
| findSeat area position (fun _ position -> | |
| let row,col = position | |
| if row = 0 then None else Some (row-1,col)) | |
| findSeat area position (fun _ position -> | |
| let row,col = position | |
| if row = 0 || col = cols-1 then None else Some (row-1,col+1)) | |
| findSeat area position (fun _ position -> | |
| let row,col = position | |
| if col = 0 then None else Some (row,col-1)) | |
| findSeat area position (fun _ position -> | |
| let row,col = position | |
| if col = cols-1 then None else Some (row,col+1)) | |
| findSeat area position (fun _ position -> | |
| let row,col = position | |
| if row = rows-1 || col = 0 then None else Some (row+1,col-1)) | |
| findSeat area position (fun _ position -> | |
| let row,col = position | |
| if row = rows-1 then None else Some (row+1,col)) | |
| findSeat area position (fun _ position -> | |
| let row,col = position | |
| if row = rows-1 || col = cols-1 then None else Some (row+1,col+1)) | |
| |] | |
| |> Array.choose id | |
| let countStatus (area : SeatStatus array array) seats status = | |
| seats | |
| |> Array.filter (fun (row,col) -> area.[row].[col] = status) | |
| |> Array.length | |
| let occupyRule1 area neighbours = | |
| countStatus area neighbours Occupied = 0 | |
| let emptyRule1 area neighbours = | |
| countStatus area neighbours Occupied >= 4 | |
| let occupyRule2 area visible = | |
| countStatus area visible Occupied = 0 | |
| let emptyRule2 area visible = | |
| countStatus area visible Occupied >= 5 | |
| let getNext getVisible occupyRule emptyRule area = | |
| area |> Array.mapi (fun row seats -> | |
| seats |> Array.mapi (fun col status -> | |
| let neighbours = getVisible area (row,col) | |
| match status with | |
| | Empty -> if occupyRule area neighbours then Occupied else status | |
| | Occupied -> if emptyRule area neighbours then Empty else status | |
| | _ -> status)) | |
| let rec runUntilStop getVisible occupyRule emptyRule area = | |
| let next = getNext getVisible occupyRule emptyRule area | |
| if next = area then next else runUntilStop getVisible occupyRule emptyRule next | |
| // Part 1 | |
| let result1 = runUntilStop getNeighbours occupyRule1 emptyRule1 input | |
| result1 | |
| |> Array.sumBy (fun seats -> | |
| seats |> Array.sumBy (fun seat -> if seat = Occupied then 1 else 0)) | |
| // Part 2 | |
| let result2 = runUntilStop getVisible occupyRule2 emptyRule2 input | |
| result2 | |
| |> Array.sumBy (fun seats -> | |
| seats |> Array.sumBy (fun seat -> if seat = Occupied then 1 else 0)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment