Day 7: Bridge Repair

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
    link
    fedilink
    English
    arrow-up
    2
    ·
    edit-2
    5 days ago

    Nim

    Bruteforce, my beloved.

    Wasted too much time on part 2 trying to make combinations iterator (it was very slow). In the end solved both parts with 3^n and toTernary.

    Runtime: 1.5s

    func digits(n: int): int =
      result = 1; var n = n
      while (n = n div 10; n) > 0: inc result
    
    func concat(a: var int, b: int) =
      a = a * (10 ^ b.digits) + b
    
    func toTernary(n: int, len: int): seq[int] =
      result = newSeq[int](len)
      if n == 0: return
      var n = n
      for i in 0..<len:
        result[i] = n mod 3
        n = n div 3
    
    proc solve(input: string): AOCSolution[int, int] =
      for line in input.splitLines():
        let parts = line.split({':',' '})
        let res = parts[0].parseInt
        var values: seq[int]
        for i in 2..parts.high:
          values.add parts[i].parseInt
    
        let opsCount = values.len - 1
        var solvable = (p1: false, p2: false)
        for s in 0 ..< 3^opsCount:
          var sum = values[0]
          let ternary = s.toTernary(opsCount)
          for i, c in ternary:
            case c
            of 0: sum *= values[i+1]
            of 1: sum += values[i+1]
            of 2: sum.concat values[i+1]
            else: raiseAssert"!!"
          if sum == res:
            if ternary.count(2) == 0:
              solvable.p1 = true
            solvable.p2 = true
            if solvable == (true, true): break
        if solvable.p1: result.part1 += res
        if solvable.p2: result.part2 += res
    

    Codeberg repo