summary refs log tree commit diff stats
path: root/solutions/day14.fs
blob: 0bc0464e4bdd9cc528be3de394ec8663d3a52f55 (plain) (blame)
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
module Solutions.Day14

open System
open System.IO

let lineToCoords (line: string) =
    line.Split([|","; " -> "|], StringSplitOptions.None) 
    |> Array.map int
    |> Array.chunkBySize 2
    |> Array.map (fun x -> x[0], x[1])

let coordsToPointSet (coords: (int * int) array) =
    let coordLine (x1, y1) (x2, y2) =
        seq { for x in min x1 x2 .. max x1 x2 do for y in min y1 y2 .. max y1 y2 -> (x, y) }
        |> Set.ofSeq
    Array.fold2 (fun points coord1 coord2 -> coordLine coord1 coord2 |> Set.union points) Set.empty coords[..Array.length coords - 2] coords[1..]

let cave = File.ReadAllLines("inputs/day14.txt") |> Array.map (lineToCoords >> coordsToPointSet) |> Set.unionMany

let startPoint = (500, 0)

let rec watch abyss (cave, p1) =
    let rec drop cave p1 (x, y) =
        [ x, y+1; x-1, y+1; x+1, y+1]
        |> Seq.tryFind (fun n -> not (Set.contains n cave))
        |> (function
            | None -> Set.add (x, y) cave, p1
            | Some (nx, ny) when ny = abyss ->
                Set.add (nx, ny) cave,
                (if p1 = -1 then Set.count cave else p1)
            | Some n -> drop cave p1 n)
    
    if Set.contains startPoint cave then 
        (p1, Set.count cave)
    else
        watch abyss (drop cave p1 startPoint)

let solution =
    let abyss = (cave |> Seq.maxBy snd |> snd) + 1
    let r = Set.count cave
    let rns = watch abyss (cave, -1)
    (fst rns - r), (snd rns - r)

let part1 () = fst solution

let part2 () = snd solution