Roc

Other Roc solutions.
module [saddlePoints]

Forest : List (List U8)
Position : { row : U64, column : U64 }

saddlePoints : Forest -> Set Position
saddlePoints = \treeHeights ->
    tallestInRows = List.walkWithIndex treeHeights [] \tallestTrees, row, rowIndex ->
        tallest = List.max row |> Result.withDefault 0
        tallestPositionsInRow = List.walkWithIndex row [] \tallestTreesInRow, treeHeight, columnIndex ->
            if treeHeight == tallest then
                List.append tallestTreesInRow ({ row: rowIndex + 1, column: columnIndex + 1 })
            else
                tallestTreesInRow
        List.concat tallestTrees tallestPositionsInRow
    tallestInRowsSet = Set.fromList tallestInRows

    columnCount =
        treeHeights
        |> List.first
        |> Result.map \row -> List.len row
        |> Result.withDefault 0

    columns = List.range { start: At 0, end: Before columnCount }

    shortestInColumns =
        List.joinMap columns \columnIndex ->
            column =
                treeHeights
                |>
                List.mapWithIndex \row, rowIdx ->
                    List.get row columnIndex
                    |> Result.map \treeHeight -> { treeHeight, rowIdx }
                |> List.keepOks identity
            shortest = List.map column .treeHeight |> List.min |> Result.withDefault 0

            column
            |> List.keepIf \{ treeHeight } -> treeHeight == shortest
            |> List.map \{ rowIdx } -> { row: rowIdx + 1, column: columnIndex + 1 }

    shortestInColumnsSet = Set.fromList shortestInColumns
    Set.intersection tallestInRowsSet shortestInColumnsSet

identity = \id -> id