Day 6: Guard Gallivant

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
    23 days ago

    Nim

    Not the prettiest code, but it runs in 3 seconds. For part 2 I just place an obstacle at every position guard visited in part 1.

    solution
    type
      Vec2 = tuple[x,y: int]
      Dir = enum
        Up, Right, Down, Left
      Guard = object
        pos: Vec2
        dir: Dir
    
    proc step(guard: var Guard, map: seq[string]): bool =
      let (x, y) = guard.pos
      case guard.dir
      of Up:
        if y == 0: return false
        if map[y-1][x] != '#': dec guard.pos.y
        else: guard.dir = Right
      of Right:
        if x == map[0].high: return false
        if map[y][x+1] != '#': inc guard.pos.x
        else: guard.dir = Down
      of Down:
        if y == map.high: return false
        if map[y+1][x] != '#': inc guard.pos.y
        else: guard.dir = Left
      of Left:
        if x == 0: return false
        if map[y][x-1] != '#': dec guard.pos.x
        else: guard.dir = Up
      true
    
    proc solve(input: string): AOCSolution[int, int] =
      var map = input.splitLines()
      var guardStart: Vec2
      block findGuard:
        for y, line in map:
          for x, c in line:
            if c == '^':
              guardStart = (x, y)
              map[y][x] = '.'
              break findGuard
    
      var visited: HashSet[Vec2]
      block p1:
        var guard = Guard(pos: guardStart, dir: Up)
        while true:
          visited.incl guard.pos
          if not guard.step(map): break
    
        result.part1 = visited.len
    
      block p2:
        for (x, y) in visited - [guardStart].toHashSet():
          var loopCond: HashSet[Guard]
          var guard = Guard(pos: guardStart, dir: Up)
          var map = map
          map[y][x] = '#'
    
          while true:
            loopCond.incl guard
            if not guard.step(map): break
            if guard in loopCond:
              inc result.part2
              break
    

    Codeberg repo