diff --git a/day16/sol.tcl b/day16/sol.tcl index 5d27703..9b06ff1 100755 --- a/day16/sol.tcl +++ b/day16/sol.tcl @@ -1,8 +1,10 @@ #!/usr/bin/env tclsh source ../prelude.tcl -proc read-input {gridp input} { - upvar $gridp grid +proc read-input {input} { + global grid + global width + global height set i 0 while {[gets $input line] >= 0} { set j 0 @@ -12,25 +14,47 @@ proc read-input {gridp input} { } incr i } + set height $i + set width $j } -proc mark-visited {visitp x y d} { - if {$x < 0} {return 0} - upvar $visitp visit +proc reset-visited {} { + global visit + array unset visit +} + +proc mark-visited {x y d} { + global visit set v [switch -exact -- $d n {expr 1} s {expr 2} w {expr 4} e {expr 8} default {error "invalid dir '$d'"}] incr visit($y,$x) 0 set result [expr {($visit($y,$x) & $v) != 0}] - set visit($y,$x) [expr {$visit($y,$x)|$v}] + set visit($y,$x) [expr {$visit($y,$x) | $v}] return $result } -proc follow {gridp visitp beams {first 0}} { - upvar $gridp grid - upvar $visitp visit +proc print-visited {} { + global visit + global width + global height + for {set i 0} {$i < $height} {incr i} { + set row {} + for {set j 0} {$j < $width} {incr j} { + if {[info exist visit($i,$j)] && $visit($i,$j)} { + lappend row "#" + } else { + lappend row "." + } + } + puts [join $row ""] + } +} + +proc follow {beams {first 0}} { + global grid set newbeams {} foreach {x y d} $beams { if {!$first} { - if { [mark-visited visit $x $y $d] } continue + if { [mark-visited $x $y $d] } continue switch $d { n { incr y -1 } s { incr y +1 } @@ -38,48 +62,37 @@ proc follow {gridp visitp beams {first 0}} { e { incr x +1 } } } - if {![info exists grid($y,$x)]} continue - switch -exact "$grid($y,$x) $d" { - {\ n} { set d w } - {\ s} { set d e } - {\ e} { set d s } - {\ w} { set d n } - {/ n} { set d e } - {/ s} { set d w } - {/ e} { set d n } - {/ w} { set d s } - {| w} { set d {n s} } - {| e} { set d {n s} } - {- n} { set d {w e} } - {- s} { set d {w e} } - } - foreach d' [split $d] { - lappend newbeams $x $y ${d'} + if {[info exists grid($y,$x)]} { + switch -exact "$grid($y,$x) $d" { + {\ n} { set d w } + {\ s} { set d e } + {\ e} { set d s } + {\ w} { set d n } + {/ n} { set d e } + {/ s} { set d w } + {/ e} { set d n } + {/ w} { set d s } + {| w} { set d {n s} } + {| e} { set d {n s} } + {- n} { set d {w e} } + {- s} { set d {w e} } + } + foreach d' [split $d] { + lappend newbeams $x $y ${d'} + } } } return $newbeams } proc solve {} { - global grid - set beams [follow grid visit {0 0 e} 1] + global visit + reset-visited + set beams [follow {0 0 e} 1] while {[llen $beams] > 0} { - set beams [follow grid visit $beams] - } - set t 0 - set N 10 - for {set i 0} {$i < $N} {incr i} { - set row {} - for {set j 0} {$j < $N} {incr j} { - if {[info exists visit($i,$j)] && $visit($i,$j)} { - lappend row "#" - incr t - } else { - lappend row "." - } - } - puts [join $row ""] + set beams [follow $beams] } + print-visited puts [array size visit] } @@ -89,8 +102,13 @@ proc lmax {list} { return $t } -proc solve2 {width height} { +proc solve2 {} { global grid + global width + global height + global visit + puts "width=$width height=$height" + set edges {} foreach k [array names grid] { lassign [split $k ","] y x @@ -102,10 +120,10 @@ proc solve2 {width height} { set l {} foreach beams $edges { - array unset visit - set beams [follow grid visit $beams 1] + reset-visited + set beams [follow $beams 1] while {[llen $beams] > 0} { - set beams [follow grid visit $beams] + set beams [follow $beams] } puts [array size visit] lappend l [array size visit] @@ -114,9 +132,10 @@ proc solve2 {width height} { puts [lmax $l] } -read-input grid stdin +read-input stdin puts [array get grid] -puts [follow grid visit {0 0 e}] +puts [follow {0 0 e}] +puts [array get visit] solve -solve2 110 110 +solve2