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