#!/usr/bin/env tclsh8.6 array set hex { 0 {0 0 0 0} 1 {0 0 0 1} 2 {0 0 1 0} 3 {0 0 1 1} 4 {0 1 0 0} 5 {0 1 0 1} 6 {0 1 1 0} 7 {0 1 1 1} 8 {1 0 0 0} 9 {1 0 0 1} A {1 0 1 0} B {1 0 1 1} C {1 1 0 0} D {1 1 0 1} E {1 1 1 0} F {1 1 1 1} } while {[gets stdin line] >= 0} { foreach c [split $line {}] { if {[info exists hex($c)]} {lappend trans {*}$hex($c)} } } # Return length in bits of the packet contained in a transmission. # (We need the length in case we're called recursively, so the parent knows # how far to advance to get to the next subpacket.) # # For part 2, also return the expression value of the packet. So, return a # list of two numbers (length and value). proc decode {trans} { set type [frombinary [lrange $trans 3 5]] if {$type == 4} { # Literal value. Figure out how long it is, and its value. set len 6 set val 0 while 1 { set digit [lrange $trans $len $len+4] incr len 5 set n [frombinary [lrange $digit 1 end]] set val [expr {$val*16 + $n}] if {[lindex $digit 0] == 0} break } return [list $len $val] } # Operator packet. Get subpacket values, two possible ways. set subvals [list] set lentype [lindex $trans 6] if {$lentype == 0} { # Operator with length type 0 (number of bits). set len [frombinary [lrange $trans 7 21]] set total [expr {22 + $len}] set i 22 while {$len > 0} { lassign [decode [lrange $trans $i [expr {$i+$len-1}]]] n v lappend subvals $v incr i $n set len [expr {$len - $n}] } } else { # Operator with length type 1 (number of subpackets). set subs [frombinary [lrange $trans 7 17]] set total 18 while {$subs > 0} { lassign [decode [lrange $trans $total end]] n v lappend subvals $v incr total $n incr subs -1 } } # Apply the operator to get the packet's value. switch -- $type { 0 { set value [::tcl::mathop::+ {*}$subvals] } 1 { set value [::tcl::mathop::* {*}$subvals] } 2 { set value [lindex $subvals 0] foreach v $subvals { if {$v < $value} {set value $v} } } 3 { set value 0 foreach v $subvals { if {$v > $value} {set value $v} } } 5 { set value [expr {[lindex $subvals 0] > [lindex $subvals 1]}] } 6 { set value [expr {[lindex $subvals 0] < [lindex $subvals 1]}] } 7 { set value [expr {[lindex $subvals 0] == [lindex $subvals 1]}] } } return [list $total $value] } proc frombinary {bits} { set n 0 foreach b $bits { set n [expr {$n*2 + $b}] } return $n } puts [lindex [decode $trans] 1]