Day 11: Plutonian Pebbles

Megathread guidelines

  • 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

FAQ

  • janAkali@lemmy.one
    link
    fedilink
    English
    arrow-up
    2
    ·
    edit-2
    11 days ago

    Nim

    Runtime: 30-40 ms
    I’m not very experienced with recursion and memoization, so this took me quite a while.

    Edit: slightly better version

    template splitNum(numStr: string): seq[int] =
      @[parseInt(numStr[0..<numStr.len div 2]), parseInt(numStr[numStr.len div 2..^1])]
    
    template applyRule(stone: int): seq[int] =
      if stone == 0: @[1]
      else:
        let numStr = $stone
        if numStr.len mod 2 == 0: splitNum(numStr)
        else: @[stone * 2024]
    
    proc memRule(st: int): seq[int] =
      var memo {.global.}: Table[int, seq[int]]
      if st in memo: return memo[st]
      result = st.applyRule
      memo[st] = result
    
    proc countAfter(stone: int, targetBlinks: int): int =
      var memo {.global.}: Table[(int, int), int]
      if (stone,targetBlinks) in memo: return memo[(stone,targetBlinks)]
    
      if targetBlinks == 0: return 1
      for st in memRule(stone):
        result += st.countAfter(targetBlinks - 1)
      memo[(stone,targetBlinks)] = result
    
    proc solve(input: string): AOCSolution[int, int] =
      for stone in input.split.map(parseInt):
        result.part1 += stone.countAfter(25)
        result.part2 += stone.countAfter(75)
    

    Codeberg repo