Quest 1: Whispers in the Shell

  • Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
  • You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL

Link to participate: https://everybody.codes/

you are viewing a single comment's thread
view the rest of the comments
[โ€“] 3 points 1 year ago* (last edited 1 year ago) (5 children)

edit: I did the wrong quest

I wasn't very happy with myself on this one. Part 1 wound up being simple enough, but part 2 took me for a loop. My disappointment was that I asked an AI for a hint, but instead it coded up a solution revolved around checking cycle dependency.

I tried to at least redo it in a functional way, since I'm writing this in FSharp, but I ran into a bunch of hiccups around indexes and index tracking. That always costs me so much time. This took me forever and I'm near the bottom of the rankings haha.

Overall, I wasn't terribly happy with how I did on this one. Oh, I wound up switching all of the types to BigInteger because I was lost as to what was happening. It turned out to be indexes and orderings, but I thought that maybe something was getting truncated.

    /// Map from (prev, curr) pair to position  
    type PositionMap = Map<BigInteger * BigInteger, BigInteger * BigInteger>  
    let rec findCycle (pairToNextPair: PositionMap) startPair currentPair acc =  
        if currentPair = startPair && List.length acc > 0 then  
            Some (List.rev acc)  
        else  
            match Map.tryFind currentPair pairToNextPair with  
            | None -> None  
            | Some nextPair -> 
                findCycle pairToNextPair startPair nextPair (snd currentPair :: acc)  

    let rec eni2' score (n:BigInteger) (exp:BigInteger) (m:BigInteger) (pairMap: PositionMap) (scores:BigInteger list) iter =  
        if iter > exp then scores |> List.rev |> List.skip (max 0 (List.length scores - 5)) |> toBigInt  
        else  
            let newScore = (score * n) % m  
            let key = (score, newScore)  
            
            match Map.tryFind key pairMap with  
            | Some _ -> 
                match findCycle pairMap key key [] with  
                | Some cycle ->  
                    let remaining = int64 (exp - iter)  
                    let cycleValues = cycle  
                    let cycleLength = List.length cycleValues |> int64  
                    let scoresLength = List.length scores |> int64  
                    let totalLength = scoresLength + 1L + remaining // scores + newScore + remaining  
                    
                    let needCount = min 5L totalLength  
                    let startPos = max 0L (totalLength - needCount)  
                    
                    let scoresReversed = List.rev scores  
                    
                    let final5 = 
                        [startPos..totalLength - 1L]  
                        |> List.map (fun pos ->  
                            if pos < scoresLength then  
                                // Position is in scores (scores is reversed, so oldest is at end)  
                                scoresReversed.[int pos]  
                            elif pos = scoresLength then  
                                // Position is newScore  
                                newScore  
                            else  
                                let cycleOffset = pos - scoresLength  
                                let cyclePos = cycleOffset % cycleLength  
                                cycleValues.[int cyclePos]  
                        )  
                    
                    // final 5 comes out in reverse order  
                    final5 |> List.rev |> toBigInt  
                | None -> 
                    eni2' newScore n exp m (Map.add key ((newScore, (newScore * n) % m)) pairMap) (newScore::scores) (iter + BigInteger 1)  
            | None ->  
                let nextPair = (newScore, (newScore * n) % m)  
                eni2' newScore n exp m (Map.add key nextPair pairMap) (newScore::scores) (iter +  BigInteger 1)  

    let eni2 (n) (exp) (m) = eni2' (BigInteger 1) n exp m Map.empty [] (BigInteger 1)  

    let part2 (input: IDictionary<string, BigInteger> array)=  
        input  
        |> Array.map (fun line ->  
            //printfn $"""running line {line.AsEnumerable() |> Seq.map(fun kv -> kv.Key + "=" + kv.Value.ToString()) |> fun x -> String.Join(", ", x)}"""  
            let a = eni2 line["A"] line["X"] line["M"]  
            let b = eni2 line["B"] line["Y"] line["M"]  
            let c = eni2 line["C"] line["Z"] line["M"]  
            let ret = a + b + c  
            //printfn $"found {ret}"  
            ret  
        ) |> Seq.max  

    let part2Answer = 
        File.ReadAllLines "Inputs/Q01_P02.txt"  
        |> part1Lines  
        |> part2  
  • source
  • hideshow 5 child comments
  • Hmmm, I am certain I did the wrong one? I did quest 1, I'm pretty sure

  • source
  • parent
  • hideshow 3 child comments
  • [โ€“] 2 points 1 year ago* (2 children)

    Here's the right challenge. This was a lot simpler than the tracking of cycles.

    type Direction = Left | Right  
    type Instruction = { Direction: Direction; Distance: int }  
    let parseInstruction (segment:string) =  
        let direction = if segment[0] = 'L' then Left else Right  
        let distance = Int32.Parse(segment.AsSpan().Slice(1)) 
        { Direction = direction; Distance = distance }  
        
    let inline normalize (array: 'a array) idx =  
        if idx >= 0 then idx % array.Length else array.Length - (-idx % array.Length)  
        
    let inline nextIndex instruction idx =  
        match instruction.Direction with  
        | Left -> idx - instruction.Distance  
        | Right -> idx + instruction.Distance  
        
    let readFile file =  
        File.ReadAllLines(file)  
        |> fun lines ->  
            let names = lines.[0] |> _.Split(",", StringSplitOptions.RemoveEmptyEntries ||| StringSplitOptions.TrimEntries)  
            let instructions =  
                lines[2]  
                |> _.Split(",", StringSplitOptions.RemoveEmptyEntries ||| StringSplitOptions.TrimEntries)  
                |> Array.map parseInstruction  
            (names, instructions)  
    
    let part1File file : string =  
            readFile file  
            |> fun (names, instructions) ->  
                    instructions  
                    |> Seq.fold (fun (idx, _) instruction  ->  
                            let next = nextIndex instruction idx |> fun v -> Math.Clamp(v, 0, names.Length - 1)  
    
                            match Array.tryItem next names with  
                            | Some n -> next, n  
                            | None -> failwith "off array"  
                        ) (0, "")  
            |> snd  
            
    let part1 () = part1File "Inputs/Quest01/Q01_P01.txt"  
    
    let part2File file =  
        readFile file  
        |> fun (names, instructions) ->  
            instructions  
            |> Seq.fold (fun (idx, _) instruction ->  
                 let next =  nextIndex instruction idx |> normalize names  
                 match Array.tryItem next names with  
                            | Some n -> next, n  
                            | None -> failwith "off array"  
                        ) (0, "")  
            |> snd  
    
    let part2() = part2File "Inputs/Quest01/Q01_P02.txt"  
    
    let part3File file =  
        readFile file  
        |> fun (names, instructions) ->  
            // need to preserve a reference to an array that can be mutated  
            let mutable nameArray = names  
            instructions  
            |> Seq.fold (fun _ instruction ->  
                // for this challenge the index doesn't matter  
                let next = match instruction.Direction with  
                            | Left -> names.Length - instruction.Distance  
                            | Right -> instruction.Distance  
                            |> normalize names  
                match Array.tryItem next nameArray with  
                            | Some n ->  
                                nameArray <- arraySwap 0 next names  
                                0, n  
                            | None -> failwith "off array"  
                ) (0, "")  
            |> snd  
    
    let part3() = part3File  "Inputs/Quest01/Q01_P03.txt"  
    
  • source
  • parent
  • hideshow 2 child comments