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
    link
    fedilink
    English
    arrow-up
    2
    ·
    edit-2
    9 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.

    Edit: made step procedure more readable.

    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 next: Vec2 =
        case guard.dir
        of Up: (guard.pos.x, guard.pos.y-1)
        of Right: (guard.pos.x+1, guard.pos.y)
        of Down: (guard.pos.x, guard.pos.y+1)
        of Left: (guard.pos.x-1, guard.pos.y)
    
      if next.y < 0 or next.x < 0 or next.y > map.high or next.x > map[0].high:
        return false
      elif map[next.y][next.x] == '#':
        guard.dir = Dir((guard.dir.ord + 1) mod 4)
      else:
        guard.pos = next
      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