diff --git a/day19/sol.tcl b/day19/sol.tcl index 23eb66e..608c28f 100755 --- a/day19/sol.tcl +++ b/day19/sol.tcl @@ -45,15 +45,106 @@ proc filter {flows value} { return $f } - -set flows [read-workflows stdin] -set values [read-values stdin] -puts $flows -puts $values -foreach v $values { - set f [filter $flows $v] - set score [ladd [lextract $v 2 1]] - puts "$v : $f : $score" - if {$f eq "A"} { incr t $score } +proc solve input { + set flows [read-workflows stdin] + set values [read-values stdin] + puts $flows + puts $values + foreach v $values { + set f [filter $flows $v] + set score [ladd [lextract $v 2 1]] + puts "$v : $f : $score" + if {$f eq "A"} { incr t $score } + } + puts "$t" } -puts "$t" + +proc unfilter flows { + lappend state(in) [dict create x {1 4000} m {1 4000} a {1 4000} s {1 4000}] + #set state(in) { + # {x {787 787} m {2655 2655} a {1222 1222} s {2876 2876}} + # {x {1679 1679} m {44 44} a {2067 2067} s {496 496}} + # {x {2036 2036} m {264 264} a {79 79} s {2244 2244}} + # {x {2461 2461} m {1339 1339} a {466 466} s {291 291}} + # {x {2127 2127} m {1623 1623} a {2188 2188} s {1013 1013}} + #} + #set flows [dict map {k v} $flows {lmap } + set done 0 + while {!$done} { + puts [array get state] + # break if everything is in the accept or reject state + set done 1 + foreach {f ranges} [array get state] { + if {$f eq "A" || $f eq "R"} continue + set done 0 + unset state($f) + foreach range $ranges { + set rules [dict get $flows $f] + foreach {cond dest} $rules { + if {$cond eq "default"} { + lappend state($dest) $range + break + } + if {[string first < $cond] >= 0} { + lassign [split $cond <] var cutoff + set key [trim $var "$"] ;# TODO + lassign [dict get $range $key] min max + if {$cutoff > $max} { + # entire range already lower than required + lappend state($dest) $range + break + } + if {$min >= $cutoff} { + # entire range above required value + continue + } + # split range + lappend state($dest) [dict replace $range $key [list $min [expr {$cutoff-1}]]] + dict set range $key [list $cutoff $max] + continue + } + if {[string first > $cond] >= 0} { + lassign [split $cond >] var cutoff + set key [trim $var "$"] + lassign [dict get $range $key] min max + if {$cutoff < $min} { + # entire range already greater than required + lappend state($dest) $range + break + } + if {$max <= $cutoff} { + # entire range below required value + continue + } + # split range + lappend state($dest) [dict replace $range $key [list [expr {$cutoff+1}] $max]] + dict set range $key [list $min $cutoff] + continue + } + error "unhandled rule $cond:$dest" + } + } + } + } + set t 0 + foreach r $state(A) { + set p 1 + foreach {min max} [join [dict values $r]] { + if {$min > $max} { + error "invalid range: $min $max" + } + set p [expr {$p * ($max - $min + 1)}] + } + incr t $p + puts "A: $r = $p" + } + puts "$t" +} + +proc solve2 input { + set flows [read-workflows stdin] + #set values [read-values stdin] + unfilter $flows +} + +solve2 stdin