day 16 cleanup

switch to globals (passing array names around is ugly).
(maybe look into dicts sometime?)

also, properly detect width/height from the input
instead of hardcoding it
main
magical 2023-12-17 06:24:26 +00:00
parent c592761d00
commit 539cf753d0
1 changed files with 70 additions and 51 deletions

View File

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