aboutsummaryrefslogtreecommitdiff
path: root/aoc-2022-dotnet/Day08/Program.fs
blob: 1a98c6d259156851e3c0ac1e9c9c1f489f0d3bab (plain)
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
module Day08

open System.IO
open System.Globalization

let parseMatrix =
    array2D
    >> Array2D.map CharUnicodeInfo.GetDigitValue

let mapEachToSeq mapping m =
    seq {
        for r in 0 .. Array2D.length1 m - 1 do
            for c in 0 .. Array2D.length2 m - 1 -> mapping m r c
    }

let sideViews (m: 'a [,]) r c =
    [ m[0 .. r - 1, c] |> Array.rev
      m[r, c + 1 ..]
      m[r + 1 .., c]
      m[r, 0 .. c - 1] |> Array.rev ]

let isVisible (m: 'a [,]) r c =
    not
    <| List.forall (Array.exists ((<=) m[r, c])) (sideViews m r c)

let scenicScore (m: 'a [,]) r c =
    sideViews m r c
    |> List.map (fun s ->
        s
        |> Seq.tryFindIndex ((<=) m[r, c])
        |> Option.map ((+) 1)
        |> Option.defaultValue (Array.length s))
    |> List.reduce (*)

let solution1 =
    parseMatrix
    >> mapEachToSeq isVisible
    >> Seq.filter id
    >> Seq.length

let solution2 = parseMatrix >> mapEachToSeq scenicScore >> Seq.max

let test = File.ReadLines("test.txt")
assert (solution1 test = 21)
assert (solution2 test = 8)

let input = File.ReadLines("input.txt")
printfn "%d" <| solution1 input
printfn "%d" <| solution2 input