summaryrefslogtreecommitdiffstats
path: root/2024/tcl/06.tcl
blob: fa480618f44ae86d4bb68ab1b7f75bfaabeeda67 (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
84
85
86
87
88
89
90
#!/bin/env tclsh

source lib.tcl
setup 6

puts {Part 1: Count unique guard coords}

set map(grid) {}
foreach line $input {
  lappend map(grid) [split $line ""]
}
set map(h) [llength $map(grid)]
set map(w) [llength [lindex $map(grid) 0]]
set map(visits) {}
set map(debug) $map(grid)
set guard(y) [lsearch $map(grid) *^*]
set guard(x) [lsearch [lindex $map(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 map
  dict set map(visits) [list $guard(y) $guard(x)] $guard(dir) 1
  lset map(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 >= $map(h) || $xnew < 0 || $xnew >= $map(w)} { return 0 }

  if {[lindex $map(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 $map(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 >= $map(h) || $xnew < 0 || $xnew >= $map(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 $map(visits) [list $ynew $xnew]]} {
    continue
  }
  if {[dict exists $map(visits) [list $guard(y) $guard(x)] [expr {($guard(dir) + 1) % 4}]]} {
#    foreach line $map(debug) {
#      puts [join $line ""]
#    }
    dict incr placed_obstructions [list $ynew $xnew] 1
    incr potential_loops
  } elseif {[lindex $map(grid) $ynew $xnew] != "#"} {
    set map_backup [array get map]
    set guard_backup [array get guard]

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

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

    array set map $map_backup
    array set guard $guard_backup
  }
}

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

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

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