#!/usr/local/bin/tclsh set state(0) [join [split [read stdin] \n] ""] proc step {} { global state # Expand current state levels into grids. set zmin 0; set zmax 0; set levels [list] foreach z [array names state] { lappend levels $z if {$z < $zmin} {set zmin $z} if {$z > $zmax} {set zmax $z} set i 0 for {set y 0} {$y < 5} {incr y} { for {set x 0} {$x < 5} {incr x} { set grid($z,$x,$y) [string index $state($z) $i] incr i } } } # Create empty grids just above and below. set zmin1 [expr {$zmin - 1}]; set zmax1 [expr {$zmax + 1}] foreach z [list $zmin1 $zmax1] { lappend levels $z for {set y 0} {$y < 5} {incr y} { for {set x 0} {$x < 5} {incr x} { set grid($z,$x,$y) . } } } # Calculate new state strings. foreach z $levels { set state($z) "" for {set y 0} {$y < 5} {incr y} { for {set x 0} {$x < 5} {incr x} { if {$x == 2 && $y == 2} {append state($z) ?; continue} set n 0 ;# neighboring bugs set tiles {} ;# neighboring tiles to check for bugs # Look "up". if {$y == 0} { # "up" is tile 8 (2,1) of level z-1 set zup [expr {$z-1}] if {[info exists grid($zup,2,1)]} {lappend tiles $zup,2,1} } elseif {$y == 3 && $x == 2} { # "up" is 5 bottom-row tiles of level z+1 set zup [expr {$z+1}] foreach xup {0 1 2 3 4} { if {[info exists grid($zup,$xup,4)]} { lappend tiles $zup,$xup,4 } } } else { # "up" is on the same level set yup [expr {$y-1}] lappend tiles $z,$x,$yup } # Look "down". if {$y == 4} { # "down" is tile 18 (2,3) of level z-1 set zd [expr {$z-1}] if {[info exists grid($zd,2,3)]} {lappend tiles $zd,2,3} } elseif {$y == 1 && $x == 2} { # "down" is 5 top-row tiles of level z+1 set zd [expr {$z+1}] foreach xd {0 1 2 3 4} { if {[info exists grid($zd,$xd,0)]} { lappend tiles $zd,$xd,0 } } } else { # "down" is on the same level set yd [expr {$y+1}] lappend tiles $z,$x,$yd } # Look "left". if {$x == 0} { # "left" is tile 12 (1,2) of level z-1 set zl [expr {$z-1}] if {[info exists grid($zl,1,2)]} {lappend tiles $zl,1,2} } elseif {$x == 3 && $y == 2} { # "left" is 5 right-column tiles of level z+1 set zl [expr {$z+1}] foreach yl {0 1 2 3 4} { if {[info exists grid($zl,4,$yl)]} { lappend tiles $zl,4,$yl } } } else { # "left" is on the same level set xl [expr {$x-1}] lappend tiles $z,$xl,$y } # Look "right". if {$x == 4} { # "right" is tile 14 (3,2) of level z-1 set zr [expr {$z-1}] if {[info exists grid($zr,3,2)]} {lappend tiles $zr,3,2} } elseif {$x == 1 && $y == 2} { # "right" is 5 left-column tiles of level z+1 set zr [expr {$z+1}] foreach yr {0 1 2 3 4} { if {[info exists grid($zr,0,$yr)]} { lappend tiles $zr,0,$yr } } } else { # "right" is on the same level set xr [expr {$x+1}] lappend tiles $z,$xr,$y } # Check neighboring tiles for bugs. foreach t $tiles { if {$grid($t) eq "#"} {incr n} } switch -- $grid($z,$x,$y) { # {if {$n == 1} {set s #} else {set s .}} . {if {$n == 1 || $n == 2} {set s #} else {set s .}} } append state($z) $s } } # Prune vacant levels. if {$z == $zmin1 || $z == $zmax1} { if {$state($z) eq "............?............"} {unset state($z)} } } } proc show {} { global state foreach z [lsort -integer [array names state]] { puts "Depth $z:" set i 0 for {set y 0} {$y < 5} {incr y} { for {set x 0} {$x < 5} {incr x} { puts -nonewline [string index $state($z) $i] incr i } puts "" } puts "" } } proc count {} { global state set n 0 foreach z [array names state] { foreach c [split $state($z) ""] { if {$c eq "#"} {incr n} } } return $n } #foreach i {1 2 3 4 5 6 7 8 9 10} step #show for {set i 0} {$i < 200} {incr i} step puts [count]