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() |> 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