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
|
module Solutions.Day8
open System.IO
let input = File.ReadLines("inputs/day8.txt") |> Array.ofSeq |> Array.map (Array.ofSeq >> Array.map (fun x -> int x - int '0')) |> array2D
let rec countVisible line index indices max =
if line = [||] then indices
else
let current = Array.head line
if current > max then
countVisible (Array.tail line) (index + 1) (Set.add index indices) current
else
countVisible (Array.tail line) (index + 1) indices max
let countBidirectional goHorizontal index line =
let dirSet dir =
countVisible (Array.tail dir) 1 (Set.singleton 0) (Array.head dir)
let forwards = dirSet line
let backwards = dirSet (Array.rev line) |> Set.map (fun x -> Array.length line - 1 - x)
Set.union forwards backwards |> Set.map(fun x -> if goHorizontal then (index, x) else (x, index))
let countGridVisible grid =
let rows, cols = Array2D.length1 grid, Array2D.length2 grid
let rowSet = seq { for x in 0..rows - 1 -> x } |> Seq.map (fun x -> grid[x, *] |> countBidirectional true x) |> Set.unionMany
let colSet = seq { for y in 0..cols - 1 -> y } |> Seq.map (fun y -> grid[*, y] |> countBidirectional false y) |> Set.unionMany
Set.union rowSet colSet |> Set.count
let part1 () = countGridVisible input
let getViewingDistance index (line: int array) =
let before, after = Array.rev line[..index - 1], line[index + 1..]
let getDistance height trees =
try
1 + Array.findIndex (fun x -> x >= height) trees
with
| :? System.Collections.Generic.KeyNotFoundException -> Array.length trees
| :? System.ArgumentNullException -> failwith "should never happen"
getDistance line[index] before * getDistance line[index] after
let getScore (grid: int[,]) (x, y) =
let row, col = grid[x, *], grid[*, y]
let hScore = getViewingDistance y row
let vScore = getViewingDistance x col
hScore * vScore
let part2 () =
seq {for x in 0..Array2D.length1 input - 1 do
for y in 0..Array2D.length2 input - 1 -> (x, y)}
|> Seq.map (getScore input)
|> Seq.max
|