#!/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 1, add up version numbers as we go. proc decode {trans} { global sum set ver [lrange $trans 0 2] incr sum [expr {[lindex $ver 0]*4 + [lindex $ver 1]*2 + [lindex $ver 2]}] set type [lrange $trans 3 5] if {$type eq "1 0 0"} { # Literal value. Figure out how long it is. set len 6 while 1 { set digit [lrange $trans $len $len+4] incr len 5 if {[lindex $digit 0] == 0} break } return $len } 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} { set n [decode [lrange $trans $i [expr {$i+$len-1}]]] incr i $n set len [expr {$len - $n}] } return $total } # Operator with length type 1 (number of subpackets). set subs [frombinary [lrange $trans 7 17]] set len 18 while {$subs > 0} { set n [decode [lrange $trans $len end]] incr len $n incr subs -1 } return $len } proc frombinary {bits} { set n 0 foreach b $bits { set n [expr {$n*2 + $b}] } return $n } set sum 0 decode $trans puts $sum