#!/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]]"