this post was submitted on 06 Dec 2024
26 points (96.4% liked)

Advent Of Code

987 readers
4 users here now

An unofficial home for the advent of code community on programming.dev!

Advent of Code is an annual Advent calendar of small programming puzzles for a variety of skill sets and skill levels that can be solved in any programming language you like.

AoC 2024

Solution Threads

M T W T F S S
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25

Rules/Guidelines

Relevant Communities

Relevant Links

Credits

Icon base by Lorc under CC BY 3.0 with modifications to add a gradient

console.log('Hello World')

founded 1 year ago
MODERATORS
 

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

you are viewing a single comment's thread
view the rest of the comments
[โ€“] [email protected] 2 points 3 weeks ago* (last edited 3 weeks 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