--- symmetry.pl 2007/08/26 02:53:41 1 +++ symmetry.pl 2007/08/26 10:59:01 4 @@ -6,8 +6,6 @@ use strict; -use Data::Dump qw/dump/; - my $board = << '_BOARD_'; +-+-+-+-+-+-+-+-+ | | |o| | | @@ -28,49 +26,54 @@ +-+-+-+-+-+-+-+-+ _BOARD_ +my $debug = shift @ARGV || 0; + my @board = map { split(//) } split(/\n/, $board); +my @trace; # line length my $ll = 8 * 2 + 1; +my @step_name = ( qw/right down left up/ ); +my @move_by = ( 1, $ll, -1, -$ll ); +my $step = 0; # right + +# offset 0, top-left corner +my $pos = 0; + +# unknown trace position +my $unknown = ' '; + +# path traversed +my @directions; + +my @found; + sub draw { - my @board = @_; my $o = 0; my $out; while ( $o < $#board ) { - $out .= join('', @board[ $o .. $o + $ll - 1 ]) . "\n"; + $out .= join('', @board[ $o .. $o + $ll - 1 ]); + $out .= ' '; + $out .= join('', @trace[ $o .. $o + $ll - 1 ]); + $out .= "\n"; $o += $ll; } return $out; } -print $board, draw( @board ); - -my @step_name = ( qw/right down left up/ ); -my @move_by = ( 1, $ll, -1, -$ll ); -my $step = 0; # right - -# offset 0, top-left corner -my $pos = 0; -$pos = 2; -$pos = 6; - -my @trace = ('x') x ( $#board + 1 ); sub trace { - warn "trace $pos\n"; + warn "## trace $pos\n"; $trace[ $pos ] = $board[ $pos ]; } -warn draw( @trace ); -trace; - sub move { warn "move $step $step_name[$step]\n"; $pos += $move_by[ $step ]; trace; $pos += $move_by[ $step ]; trace; - warn draw( @trace ); + push @directions, $step; } sub follow { @@ -82,10 +85,12 @@ my $ok_path = qr/[\|\-]/; sub can_turn { - my $step = shift; - die "no step?" unless defined $step; + my $try_step = shift; + die "no step?" unless defined $try_step; + + $try_step %= 4; - my $turn_pos = $pos + $move_by[ $step % 4 ]; + my $turn_pos = $pos + $move_by[$try_step]; my $old = $trace[ $turn_pos ]; $trace[ $turn_pos ] = '?'; @@ -93,40 +98,78 @@ $trace[ $turn_pos ] = $old; if ( $board[ $turn_pos ] =~ $ok_path ) { - warn "OK can_turn $step_name[$step] turn_pos = $turn_pos b($board[$turn_pos]) t($trace[$turn_pos])"; + warn "OK can_turn $try_step $step_name[$try_step] turn_pos = $turn_pos b($board[$turn_pos]) t($trace[$turn_pos])"; + $step = $try_step; return 1; } else { - warn "NOPE can_turn $step_name[$step] turn_pos = $turn_pos b($board[$turn_pos]) t($trace[$turn_pos])"; + warn "NOPE can_turn $try_step $step_name[$try_step] turn_pos = $turn_pos b($board[$turn_pos]) t($trace[$turn_pos])"; return 0; } } -while( 1 ) { +sub show_directions { + return + join('', + map { + substr($step_name[$_],0,1) + } @directions + ) + ; +} - my $next_pos = $pos + $move_by[ $step ]; - warn "in loop - pos = $pos next_pos = $next_pos step = $step $step_name[$step]\n"; +sub shape { - if ( $trace[ $next_pos ] ne 'x' ) { - warn "position $next_pos re-visited, exiting\n"; - last; - } elsif ( $board[ $next_pos ] =~ $ok_path ) { - warn "OK next_pos = $next_pos b($board[$next_pos]) t($trace[$next_pos])\n"; - move; - follow( $step+1 ) if can_turn( $step+1 ); - } else { - warn "find line continuation from $step $step_name[$step]...\n"; - foreach my $o ( -1, 1 ) { - if ( can_turn( $step + $o ) ) { - $step = $step+$o; - warn "new direction: $step $step_name[$step]\n"; - follow( $step ); - last; - } + my ($x,$y) = @_; + + $pos = $y * $ll * 2 + $x * 2; + + warn "<<< shape from $x,$y pos: $pos\n"; + @trace = ($unknown) x ( $#board + 1 ); + @directions = (); + trace; + + my $len = 0; + + while( 1 ) { + + my $next_pos = $pos + $move_by[ $step ]; + warn "# pos: $pos next_pos: $next_pos step: $step $step_name[$step] trace: ",show_directions,"\n"; + + if ( $trace[ $next_pos ] ne $unknown ) { + warn "position $next_pos re-visited, exiting\n"; + last; + } elsif ( $board[ $next_pos ] =~ $ok_path ) { + warn "OK next_pos = $next_pos b($board[$next_pos]) t($trace[$next_pos])\n"; + move; + $len++; + can_turn( $step + 1 ); + } else { + warn "find line continuation from $step $step_name[$step]...\n"; + can_turn( $step - 1 ) || can_turn( $step + 1 ) || die "can't find new direction"; + } + warn draw( @trace ); + + if ( $debug ) { + print "WAIT> press enter | ",show_directions; my $foo = ; } } - warn draw( @trace ); + push @found, { x => $x, y => $y, len => $len, directions => show_directions }; + + warn ">>> ended at $pos, line length: $len, directions traversed: ",show_directions,"\n"; + print "WAIT> press enter"; my $foo = ; + + return $len; } -warn "ended at $pos\n"; +my $shapes = '0,0 1,0 0,3'; + +foreach my $start ( split(/\s/,$shapes) ) { + my $len = shape( split(/,/,$start) ); + warn "## $start has $len elements\n"; +} +print ">>> RESULTS:\n"; +foreach my $r ( @found ) { + printf "%2d,%-2d len: %-4d directions: %s\n", $r->{x}, $r->{y}, $r->{len}, $r->{directions}; +}