summaryrefslogtreecommitdiffstats
path: root/2024/tcl/06.tcl
blob: 39f980e5bac47ccd2dc37679c1f85b9895f15df6 (plain) (blame)
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#!/bin/env tclsh

source lib.tcl
setup 6 grid

puts {Part 1: Count unique guard coords}

set input(visits) {}
set guard(y) [lsearch $input(grid) *^*]
set guard(x) [lsearch [lindex $input(grid) $guard(y)] ^]
set guard(dir) 0
set placed_obstructions {}

set rot_map {{-1 0} {0 1} {1 0} {0 -1}}

proc step_guard {} {
  global guard rot_map input
  dict set input(visits) [list $guard(y) $guard(x)] $guard(dir) 1
  lset input(debug) $guard(y) $guard(x) [lindex {^ > v <} $guard(dir)]

  lassign [lindex $rot_map $guard(dir)] ydir xdir
  set ynew [expr {$guard(y) + $ydir}]
  set xnew [expr {$guard(x) + $xdir}]

  if {$ynew < 0 || $ynew >= $input(h) || $xnew < 0 || $xnew >= $input(w)} { return 0 }

  if {[lindex $input(grid) $ynew $xnew] == "#"} {
    set guard(dir) [expr {($guard(dir) + 1) % 4}]
    return 1
  }

  set guard(y) $ynew
  set guard(x) $xnew
  return 1
}

# sigh
set potential_loops 0
while {[step_guard]} {
  puts -nonewline "Unique coords: [llength [dict keys $input(visits)]]\r"
  flush stdout

  lassign [lindex $rot_map $guard(dir)] ydir xdir
  set ynew [expr {$guard(y) + $ydir}]
  set xnew [expr {$guard(x) + $xdir}]
  if {$ynew < 0 || $ynew >= $input(h) || $xnew < 0 || $xnew >= $input(w)} continue

  # it took me. 2 hours. to realize i needed the clause after the ||. god dammit.
  if {[dict exists $placed_obstructions [list $ynew $xnew]] || [dict exists $input(visits) [list $ynew $xnew]]} {
    continue
  }
  if {[dict exists $input(visits) [list $guard(y) $guard(x)] [expr {($guard(dir) + 1) % 4}]]} {
#    foreach line $input(debug) {
#      puts [join $line ""]
#    }
    dict incr placed_obstructions [list $ynew $xnew] 1
    incr potential_loops
  } elseif {[lindex $input(grid) $ynew $xnew] != "#"} {
    set input_backup [array get input]
    set guard_backup [array get guard]

    lset input(grid) $ynew $xnew "#"
    lset input(debug) $ynew $xnew "#"

    while {[step_guard]} {
      if {[dict exists $input(visits) [list $guard(y) $guard(x)] $guard(dir)]} {
        dict incr placed_obstructions [list $ynew $xnew] 2
        incr potential_loops
        break
      }
    }

    array set input $input_backup
    array set guard $guard_backup
  }
}

puts "Unique coords: [llength [dict keys $input(visits)]]"

puts ""
puts {Part 2: Number of potential looping obstructions}

puts "Potential count: [llength [dict keys $placed_obstructions]]"