#!/usr/bin/env tclsh8.6 # Read input into grid (array). set maxy 0 while {[gets stdin line] >= 0} { set maxx 0 foreach c [split $line {}] { set grid($maxx,$maxy) $c incr maxx } incr maxy } # Add "." padding all around the grid. for {set x -1} {$x <= $maxx} {incr x} { set grid($x,-1) . set grid($x,$maxy) . } for {set y -1} {$y <= $maxy} {incr y} { set grid(-1,$y) . set grid($maxx,$y) . } # Determine whether a given number borders a symbol other than ".". proc ispart {y startx endx} { global grid set y1 [expr {$y-1}] set y2 [expr {$y+1}] set x1 [expr {$startx-1}] set x2 [expr {$endx+1}] # Check to the left and right of the digits. set s "$grid($x1,$y1)$grid($x1,$y)$grid($x1,$y2)" append s "$grid($x2,$y1)$grid($x2,$y)$grid($x2,$y2)" # Check above and below each digit. for {set x $startx} {$x <= $endx} {incr x} { append s "$grid($x,$y1)$grid($x,$y2)" } foreach c [split $s {}] { if {$c eq "." || [string is digit $c]} continue return 1 } return 0 } set parts [list] for {set y 0} {$y <= $maxy - 1} {incr y} { set number {} set startx -1 ;# starting X coord of current number # Let this loop hit the dot padding on the right edge. for {set x 0} {$x <= $maxx} {incr x} { set c $grid($x,$y) if {[string is digit $c]} { append number $c if {$startx < 0} { set startx $x # puts "New number beginning $x,$y" } } else { if {$startx >= 0} { # puts "Number terminated $x,$y" if {[ispart $y $startx [expr {$x-1}]]} { lappend parts $number # puts "Part number $number" } } set number {} set startx -1 } } } puts [::tcl::mathop::+ {*}$parts] puts [::tcl::mathop::+ {*}[lsort -unique $parts]]