adventofcode2023/day16/sol.tcl

123 lines
3.0 KiB
Tcl
Executable File

#!/usr/bin/env tclsh
source ../prelude.tcl
proc read-input {gridp input} {
upvar $gridp grid
set i 0
while {[gets $input line] >= 0} {
set j 0
foreach c [split $line ""] {
set grid($i,$j) $c
incr j
}
incr i
}
}
proc mark-visited {visitp x y d} {
if {$x < 0} {return 0}
upvar $visitp 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}]
return $result
}
proc follow {gridp visitp beams {first 0}} {
upvar $gridp grid
upvar $visitp visit
set newbeams {}
foreach {x y d} $beams {
if {!$first} {
if { [mark-visited visit $x $y $d] } continue
switch $d {
n { incr y -1 }
s { incr y +1 }
w { incr x -1 }
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'}
}
}
return $newbeams
}
proc solve {} {
global grid
set beams [follow grid visit {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 ""]
}
puts [array size visit]
}
proc lmax {list} {
set t 0
foreach x $list { if {$t < $x} {set t $x} }
return $t
}
proc solve2 {width height} {
global grid
set edges {}
foreach k [array names grid] {
lassign [split $k ","] y x
if {$x == 0} { lappend edges [list $x $y e] }
if {$y == 0} { lappend edges [list $x $y s] }
if {$x == $width - 1} { lappend edges [list $x $y n] }
if {$y == $height - 1} { lappend edges [list $x $y w] }
}
set l {}
foreach beams $edges {
array unset visit
set beams [follow grid visit $beams 1]
while {[llen $beams] > 0} {
set beams [follow grid visit $beams]
}
puts [array size visit]
lappend l [array size visit]
}
puts [lmax $l]
}
read-input grid stdin
puts [array get grid]
puts [follow grid visit {0 0 e}]
solve
solve2 110 110