module _59 open System open System.IO let cypher = let encrypted = File.ReadAllLines(@"59_cipher1.txt") |> Array.collect (fun line -> line.Split(',') |> Array.map uint16) let decrypt f message key = let repeatedKey = seq { while true do yield! key } Seq.map2 f message repeatedKey let decryptXor = decrypt (^^^) let decriptMessage = decryptXor encrypted let de = encrypted |> Seq.distinct |> Seq.toArray let filteri f s = seq { for i in 0..((s |> Seq.length) - 1) do let si = Seq.nth i s if f i si then yield si } let validKeys encryptedSymbols = let lowercase = [97us..122us] |> List.toArray let validSymbols = [32us..122us] |> List.toArray let isValidChar i = Array.exists ((=) i) validSymbols [0..2] |> List.map (fun offset -> lowercase |> Seq.filter (fun lc -> encryptedSymbols |> filteri (fun i e -> i % 3 = offset) |> Seq.forall (fun e -> (e ^^^ lc) |> isValidChar)) ) let messageToText message = message |> Seq.map (char >> string) |> Seq.fold (fun acc e -> acc + e) "" validKeys encrypted |> common.slottedPermutations |> Seq.map (fun p -> (p, (decriptMessage >> messageToText) p)) |> Seq.find (fun p -> (snd p).Contains(" the ")) |> (fst >> decriptMessage) |> Seq.map (int) |> Seq.sum