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/

  • Vulwsztyn@programming.dev
    link
    fedilink
    arrow-up
    0
    ·
    2 days ago

    my boring python solution:

    from pathlib import Path
    
    
    def main():
        input = Path('input.txt').read_text().split('\n')
        names = input[0].split(',')
        instructions = input[-1].split(',')
        print(names,instructions)
        index = 0
        for instruction in instructions:
            dir = instruction[0]
            number = int(instruction[1:])
            if dir == 'L':
                index -= number
                if index < 0:
                    index = 0
            else:
                index += number
                if index > len(names) - 1:
                    index = len(names) - 1
        print(names[index])
        index = 0
        for instruction in instructions:
            dir = instruction[0]
            number = int(instruction[1:])
            if dir == 'L':
                index -= number
            else:
                index += number
        print(names[index%(len(names))])
        indexes = list(range(len(names)))
        for instruction in instructions:
            dir = instruction[0]
            number = (int(instruction[1:]) if dir == 'R' else -int(instruction[1:])) % len(names)
            indexes[0], indexes[number] = indexes[number], indexes[0]
        print(names[indexes[0]])
    
    if __name__ == "__main__":
        main()
    

    I probably should read all 3 files though. I’ll hone it out later.

  • janAkali@lemmy.sdf.org
    link
    fedilink
    arrow-up
    0
    ·
    2 days ago

    So far I really like the difficulty level of EC, compared to AOC.
    Quest 1 is pretty straightforward:

    • part 1: add offsets to index then clamp it between 0..limit e.g. min(limit, max(0, index))
    • part 2: add offsets and then modulo to figure out last index
    • part 3: swap first element with element at index mod names.len until done =)

    My solution in Nim:

    proc parseInput(input: string): tuple[names: seq[string], values: seq[int]] =
      let lines = input.splitLines()
      result.names = lines[0].split(',')
    
      let values = lines[2].multiReplace({"R":"","L":"-"})
      for num in values.split(','):
        result.values.add parseInt(num)
    
    proc solve_part1*(input: string): Solution =
      let (names, values) = parseInput(input)
      var pos = 0
      for value in values:
        pos = min(names.high, max(0, pos + value))
      result := names[pos]
    
    proc solve_part2*(input: string): Solution =
      let (names, values) = parseInput(input)
      let pos = values.sum()
      result := names[pos.euclMod(names.len)]
    
    proc solve_part3*(input: string): Solution =
      var (names, values) = parseInput(input)
      for value in values:
        swap(names[0], names[euclMod(value, names.len)])
      result := names[0]
    

    Full solution at Codeberg: solution.nim

  • Amy@piefed.blahaj.zone
    link
    fedilink
    English
    arrow-up
    0
    ·
    edit-2
    3 days ago

    Ooh, challenges! Here we go!

    I haven’t really written any Haskell since last year’s AoC, and boy am I rusty.

    import Control.Monad  
    import Data.List  
    import Data.List.Split  
    import Data.Vector qualified as V  
    
    readInput s =  
      let [names, _, moves] = splitOn "," <$> lines s  
       in (names, map readMove moves)  
      where  
        readMove (d : s) =  
          let n = read s :: Int  
           in case d of  
                'L' -> -n  
                'R' -> n  
    
    addWith f = (f .) . (+)  
    
    part1 names moves =  
      names !! foldl' (addWith $ clamp (length names)) 0 moves  
      where  
        clamp n x  
          | x < 0 = 0  
          | x >= n = n - 1  
          | otherwise = x  
    
    part2 names moves =  names !! (sum moves `mod` length names)  
    
    part3 names moves =  
      V.head  
        . foldl' exchange (V.fromList names)  
        $ map (`mod` length names) moves  
      where  
        exchange v k = v V.// [(0, v V.! k), (k, V.head v)]  
    
    main =  
      forM_  
        [ ("everybody_codes_e2025_q01_p1.txt", part1),  
          ("everybody_codes_e2025_q01_p2.txt", part2),  
          ("everybody_codes_e2025_q01_p3.txt", part3)  
        ]  
        $ \(input, solve) ->  
          readFile input >>= putStrLn . uncurry solve . readInput  
    
  • VegOwOtenks@lemmy.world
    link
    fedilink
    arrow-up
    0
    ·
    3 days ago

    I coded this along with my girlfriend who’s learning python, but not motivated to share her solution. The program reads from stdin, because I usually invoke it like so: runhaskell Main.hs < input or runhaskell Main.hs < example. I think this is quite handy because I don’t have to change the source code to check the example input again.

    I struggled with Part 3, where I suddenly forgot I could’ve simply used mod, which I ended up doing anyway. I immediately recognized that Part 3 needs Mutable Arrays if I care to avoid Index hell, which is not what I wanted to with Haskell but oh well.

    {-# OPTIONS_GHC -Wall #-}
    {-# LANGUAGE PatternSynonyms #-}
    module Main (main) where
    
    import qualified Data.Text as Text
    import qualified Data.Text.IO as TextIO
    import Control.Monad ((<$!>), forM_)
    import Data.Text (Text, pattern (:<))
    import qualified Data.List as List
    import qualified Data.Array.MArray as MutableArray
    import Control.Monad.ST (runST, ST)
    import Data.Array.ST (STArray)
    
    commaSepLine :: IO [Text.Text]
    commaSepLine = Text.split (== ',') <$!> TextIO.getLine
    
    readInstruction :: Text -> Int
    readInstruction ('R' :< n) = read . Text.unpack $ n
    readInstruction ('L' :< n) = negate . read . Text.unpack $ n
    readInstruction _ = undefined
    
    myName :: (Foldable t, Ord b, Enum b, Num b) => b -> t b -> b
    myName maxPosition = List.foldl' (\ pos offset -> min (pred maxPosition) . max 0 $ pos + offset) 0
    
    parentName1 :: [Int] -> Int
    parentName1 = List.sum
    
    newSTArray :: [e] -> ST s (STArray s Int e)
    newSTArray xs = MutableArray.newListArray (0, length xs - 1) xs
    
    swap :: (MutableArray.MArray a e m, MutableArray.Ix i) => a i e -> i -> i -> m ()
    swap array i0 i1 = do
      e0 <- MutableArray.readArray array i0
      e1 <- MutableArray.readArray array i1
      MutableArray.writeArray array i0 e1
      MutableArray.writeArray array i1 e0
    
    parentName2 :: [Text] -> [Int] -> Text
    parentName2 nameList instructions = runST $ do
      names <- newSTArray nameList
      arrayLength <- succ . snd <$> MutableArray.getBounds names
      forM_ instructions $ \ offset -> do
        let arrayOffset = offset `mod` arrayLength
        swap names 0 arrayOffset
      MutableArray.readArray names 0
    
    main :: IO ()
    main = do
      names <- commaSepLine
      _ <- TextIO.getLine
      instructions <- fmap readInstruction <$> commaSepLine
    
      let namesLength = length names
      print $ names !! myName namesLength instructions
      print . (names !!) . (`mod` namesLength) $ parentName1 instructions
      print $ parentName2 names instructions
    
  • ragingHungryPanda@piefed.keyboardvagabond.com
    link
    fedilink
    English
    arrow-up
    0
    ·
    edit-2
    4 days ago

    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