-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday11_part02.fs
97 lines (84 loc) · 4.21 KB
/
day11_part02.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
module day11_part02
open System.Collections.Generic
open CustomDataTypes
open AdventOfCode_2020.Modules
let path = "day11/day11_input.txt"
let inputLines = LocalHelper.GetLinesFromFile(path)
let maxX = inputLines.[0].Length
let maxY = inputLines.Length
let placesDict = new Dictionary<int*int, SeatInfo>()
let plane =
seq {
for jdx in [0..maxY - 1] do
for idx in [0..maxX - 1] do
let seat =
match inputLines.[jdx].[idx] with
| '.' -> SeatStatus.FLOOR
| 'L' -> SeatStatus.EMPTY
| '#' -> SeatStatus.OCCUPIED
| _ -> failwith("wrong site type")
let seatToAdd = { Seat = seat; Location = (jdx, idx); Content = inputLines.[jdx].[idx] }
if seatToAdd.Seat <> SeatStatus.FLOOR then
placesDict.Add((jdx, idx), seatToAdd)
yield seatToAdd
} |> List.ofSeq
let printPlane (dictPlane: Dictionary<(int*int), SeatInfo>)=
for idx in [0 .. maxY - 1] do
for jdx in [0 .. maxX - 1] do
if dictPlane.ContainsKey(idx, jdx) then
printf "%c" dictPlane.[(idx, jdx)].Content
else
printf "."
printfn ""
let rec findFirstSeat (direction: int[]) (seat: int[]) (originalSeat: int[]) (places: Dictionary<(int*int), SeatInfo>) (limits: int[]) =
let newSeat = [| seat.[0] + direction.[0]; seat.[1] + direction.[1] |]
if newSeat.[0] > (limits.[0] - 1) || newSeat.[1] > (limits.[1] - 1) then
places.[(originalSeat.[0], originalSeat.[1])]
else
match places.ContainsKey(newSeat.[0], newSeat.[1]) with
| true -> places.[(newSeat.[0], newSeat.[1])]
| false ->
if (newSeat.[0] > -1 && newSeat.[1] > -1) then
findFirstSeat direction newSeat originalSeat places limits
else
match places.ContainsKey((seat.[0], seat.[1])) with
| true -> places.[(seat.[0], seat.[1])]
| false -> places.[(originalSeat.[0], originalSeat.[1])]
let getNewPlaces (places: Dictionary<(int*int), SeatInfo>) =
let directions = [ [|-1; -1|]; [|-1; 0|]; [|-1; 1|]; [|0; -1|]; [|0; 1|]; [|1; -1|]; [|1; 0|]; [|1; 1|] ]
let newPlaces = new Dictionary<(int*int), SeatInfo>()
for place in places do
let seatsToCheck =
seq{
for dir in directions do
let originalSeat = [| fst place.Value.Location; snd place.Value.Location |]
let newSeatPlace = findFirstSeat dir originalSeat originalSeat places [|maxY; maxX|]
if newSeatPlace.Location <> place.Value.Location then
yield newSeatPlace
} |> List.ofSeq
let adjOccupied = seatsToCheck |> List.filter(fun s -> s.Seat = SeatStatus.OCCUPIED) |> List.length
let newSeat =
match place.Value.Seat with
| SeatStatus.EMPTY ->
if adjOccupied = 0 then
{ Seat= SeatStatus.OCCUPIED; Location= (place.Value.Location); Content= '#'}
else
{ Seat= place.Value.Seat; Location= (place.Value.Location); Content= place.Value.Content }
| SeatStatus.OCCUPIED ->
if adjOccupied > 4 then
{ Seat= SeatStatus.EMPTY; Location= (place.Value.Location); Content= 'L'}
else
{ Seat= place.Value.Seat; Location= (place.Value.Location); Content= place.Value.Content }
| _ -> place.Value
newPlaces.Add((fst place.Value.Location, snd place.Value.Location), newSeat)
newPlaces
let rec round (oldplaces: Dictionary<(int*int), SeatInfo>) (rounds: int) =
let newplacesDict = getNewPlaces oldplaces
//printfn "Round %i" rounds
//printPlane newplacesDict
let planesAreIdentical = oldplaces.Values |> List.ofSeq |> List.forall(fun op -> newplacesDict.[(fst op.Location, snd op.Location)].Seat = op.Seat)
match planesAreIdentical with
| true -> newplacesDict |> List.ofSeq |> List.filter(fun s -> s.Value.Seat = SeatStatus.OCCUPIED) |> List.length
| false -> round newplacesDict (rounds + 1)
let execute =
round placesDict 0