summary refs log blame commit diff stats
path: root/solutions/day13.fs
blob: 6caed93602ad7f41d724d17ede623ef714862e28 (plain) (tree)




















































                                                                                         
module Solutions.Day13
open System
open System.IO
open System.Text.Json.Nodes

type Packet =
| PList of Packet array
| PInt of int

let rec parsePacket (p: JsonNode) =
    match p with
    | :? JsonArray as a -> a |> Seq.map parsePacket |> Array.ofSeq |> PList
    | :? JsonValue as v -> v.GetValue<int>() |> PInt
    | _ -> failwith "shouldn't happen"

let rec comparePackets (left: Packet) (right: Packet) =
    match left, right with
    | PInt l, PInt r when l < r -> -1
    | PInt l, PInt r when l > r -> 1
    | PInt _, PInt _ -> 0
    | PInt _, PList _ -> comparePackets (PList [|left|]) right
    | PList _, PInt _ -> comparePackets left (PList [|right|])
    | PList l, PList r ->
        (l, r) 
        ||> Seq.fold2 (fun acc a b ->
                        match acc with
                        | 0 -> comparePackets a b
                        | x -> x) 0
        |> function
        | 0 when l.Length < r.Length -> -1
        | 0 when l.Length > r.Length -> 1
        | x -> x


let input = File.ReadAllLines("inputs/day13.txt") 
            |> Seq.filter (fun x -> not <| String.IsNullOrEmpty x) 
            |> Seq.map (fun x -> JsonNode.Parse x |> parsePacket)

let part1 () = input
               |> Seq.chunkBySize 2
               |> Seq.map (fun x -> comparePackets x[0] x[1])
               |> Seq.indexed
               |> Seq.map (fun (index, compare) -> if compare = -1 then index + 1 else 0)
               |> Seq.sum

let part2 () = 
    let divider2 = PList [| PList [| PInt 2 |] |]
    let divider6 = PList [| PList [| PInt 6 |] |]
    let input' = Seq.append input [|divider2; divider6|]
    let sorted = Seq.sortWith comparePackets input'
    let d2Index = Seq.findIndex ((=) divider2) sorted |> (+) 1
    let d6Index = Seq.findIndex ((=) divider6) sorted |> (+) 1
    d2Index * d6Index