#!/usr/bin/env tclsh set state 0 while {[gets stdin line] >= 0} { switch -- $state { 0 { if {$line eq ""} {set state 1; continue} if {[scan $line {%[^:]: %d-%d or %d-%d} field min1 max1 min2 max2] != 5} { continue } set rule($field) [list $min1 $max1 $min2 $max2] lappend rules $rule($field) lappend unknowns $field } 1 { if {$line eq ""} {set state 2; continue} if {$line eq "your ticket:"} continue set your [split $line ,] } 2 { if {$line eq ""} break if {$line eq "nearby tickets:"} continue lappend tmp [split $line ,] } } } set nearby {} foreach tkt $tmp { set valid 1 foreach i $tkt { set ok 0 foreach r $rules { lassign $r min1 max1 min2 max2 if {($i >= $min1 && $i <= $max1) || ($i >= $min2 && $i <= $max2)} { set ok 1 break } } if {! $ok} { # puts "invalid: $i tkt=<$tkt>" set valid 0 } } if {$valid} {lappend nearby $tkt} } # puts [join $nearby \n] # puts $unknowns foreach tkt $nearby { set ncols [llength $tkt] for {set i 0} {$i < $ncols} {incr i} { lappend col($i) [lindex $tkt $i] } } # puts $col(0) while {[llength $unknowns]} { # Try to find a column that only satisfies one rule. for {set i 0} {$i < $ncols} {incr i} { set matchrules {} if {[info exists match($i)]} continue foreach field $unknowns { lassign $rule($field) min1 max1 min2 max2 # puts "considering col=$i rule=<$field> $min1 $max1 $min2 $max2" set ok 1 foreach j $col($i) { if {$j < $min1 || $j > $max2 || ($j > $max1 && $j < $min2)} { set ok 0 # puts " failed: j=$j" break } } if {$ok} { lappend matchrules $field # puts " passed" } } # puts "col=$i matches [llength $matchrules] rules" if {[llength $matchrules] == 1} { set match($i) [lindex $matchrules 0] set revmatch($match($i)) $i # puts "match($i)=$match($i)" # Remove this field from unknowns. set tmp {} foreach j $unknowns { if {$j ne $match($i)} {lappend tmp $j} } set unknowns $tmp # puts "unknowns: $unknowns" } } } parray revmatch set n 1 foreach i [array names revmatch departure*] { set n [expr {$n * [lindex $your $revmatch($i)]}] } puts $n