Repo for my Advent of Code solutions.
open System.IO

let readLines (filePath: string) = seq {
    use sr = new StreamReader (filePath)
    while not sr.EndOfStream do
        yield sr.ReadLine()
}

type Range = { first: int; last: int }
let rangeFront (r: Range): Range =
    { Range.first = r.first; last = r.first + ((r.last - r.first) / 2) }
let rangeBack (r: Range): Range =
    { Range.first = r.first + ((r.last - r.first) / 2) + 1; last = r.last }
let rangeLower = rangeFront
let rangeUpper = rangeBack

let calculateSeatId (row: int) (col: int): int =
    row * 8 + col

let rec binarySearch (s: string) (i: int) (final: int) (r: Range): Range =
    let c = s.[i]
    let newRange = if (c = 'F' || c = 'L') then (rangeFront r)
                    else (rangeBack r)
    if i = final then newRange
    else binarySearch s (i + 1) final newRange

[<EntryPoint>]
let main argv =
    let lines = readLines "input.txt"
    let seats: bool array = [| for i in 0..(128 * 8) do false |]

    let usedSeats = [ for line in lines do
                        let rowRange = binarySearch line 0 6 { Range.first = 0; last = 127 }
                        let colRange = binarySearch line 7 9 { Range.first = 0; last = 7 }
                        let seatId = calculateSeatId rowRange.first colRange.first
                        Array.set seats seatId true
                        (seatId) ]
    
    let highestSeatId = List.max usedSeats

    let part2 = query {
        for i in 1..seats.Length - 1 do
            find (seats.[i - 1] && not seats.[i] && seats.[i + 1])
    }

    printf "%d\n%A\n" highestSeatId part2
    0