print map "$_\n",layout_crossword(
  '.....',
  ' ..XX.',
  '  .....',
  '   .XX..',
  '    .....',
);





sub layout_crossword{
  my @input=@_;
  my @output;

  # Fill the output with full squares, and convert strings into arrays.
  # If full/empty borders are the same, remove this loop
  #   and uncomment the call to fill_square() below
  for my $i(0..$#input){
    $input[$i]=[split //,$input[$i]];
    for my $j(0..$#{$input[$i]}){
      fill_square(\@output,$i,$j,\@full_square) if $input[$i][$j] ne ' ';
    }
  }

  # Find all the empty squares, and populate them
  my $num=0;
  for my $i(0..$#input){
    for my $j(0..$#{$input[$i]}){
      my $c=$input[$i][$j];
      if($c eq 'X'){
        # It's a filled square

        # We don't need this, because we filled the entire puzzle earlier.
        # Doing it here even spoils the effect of different full/empty borders

        # fill_square(\@output,$i,$j,\@full_square);
      }elsif($c eq ' '){
        # This square doesn't exist
      }elsif(
           # The previous column is not empty, and the next is empty
           (!$i || $input[$i-1][$j] ne '.') && $input[$i+1][$j] eq '.'

           # or the previous row is not empty, and the next is empty
        || (!$j || $input[$i][$j-1] ne '.') && $input[$i][$j+1] eq '.'
      ){
        # It's a square with a number in it

        ++$num;
        fill_square(\@output,$i,$j,\@empty_square,$num);
      }else{
        # It's a completely empty square

        fill_square(\@output,$i,$j,\@empty_square);
      }
    }
  }

  @output;
}


sub fill_square{
  my($output,$i,$j,$square,$num)=@_;

  # Work out the dimensions of a square (assumes each row is the same length!)
  my $rows=@$square;
  my $cols=length $square->[0];

  # Work out the position within the entire puzzle 
  my $off_r=$i*($rows-1);
  my $off_c=$j*($cols-1);

  # Copy each square row into the puzzle
  for my $r(0..$rows-1){
    my $line=$square->[$r];
    if($num){
      #
      my $l=length $num;
      $line=~s/\.{$l}/$num/
        and $num='';
    }

    # Convert remaining dots to spaces
    $line=~y/./ /;

    # Splice the line into the puzzle
    # $_ is aliased to the string here to reduce typing
    local *_=\$output->[$off_r+$r];
    $_.=' 'x($off_c-length);
    substr($_,$off_c,$cols)=$line; 
  }
}

