#!/usr/bin/perl5.6

use strict;
our (@empty_square, @full_square);
chomp(my @puzzle = <>);

sub is_square {
  my @array = @_;

  # make sure all of the rows of the array are the same length. if so,
  # return that length. if not, return undef.

  my $len = length $array[0];
  return if grep { length $_ != $len } @array;

  return $len;
}

sub layout_crossword {
  my @puzzle = @_;

  # make sure all of the rows are the same length

  my $len = is_square (@puzzle) or
    die "All rows of the puzzle must be the same length";

  # make sure the empty square and the full square are really square,
  # and the same dimensions

  my $e_len = is_square (@empty_square) or
    die "All rows of the empty square must be the same length";

  my $f_len = is_square (@full_square) or
    die "All rows of the full square must be the same length";

  die "All rows of the empty & full squares must be the same length"
    unless ($e_len == $f_len);

  die "The empty & full squares must have the same number of rows"
    unless ($#empty_square == $#full_square);

  # make every character in the puzzle into either a . or an X

  s/[^.]/X/g for @puzzle;

  # split the puzzle into an array of arrays, where the elements of
  # the outer array are rows in the puzzle, and the elements of the
  # inner array are columns

  my $puzzle = [map { [split //, $_] } @puzzle];
  my $num = 1;

  # loop through the puzzle, identifying the cells at which entries
  # start, and put a number in each of those cells

  my $rows = $#{$puzzle};
  my $cols = $len-1;

  foreach my $row (0..$rows) {
    foreach my $col (0..$cols) {

      # can't start an entry at an X cell

      next if ($puzzle->[$row]->[$col] eq 'X');

      # if this cell is a . and the cell to the left is an X (or the
      # edge of the puzzle), then start a new "across" entry -- but
      # only if there's at least one . to the right

      if ((($puzzle->[$row]->[$col-1] eq 'X' || $col == 0) &&
            $puzzle->[$row]->[$col+1] eq '.') ||

          # if this cell is a . and the cell below is an X (or the edge
          # of the puzzle), then start a new "down" entry -- but only
          # if there's at least one . below

          (($puzzle->[$row-1]->[$col] eq 'X' || $row == 0) &&
            $puzzle->[$row+1]->[$col] eq '.')) {

        # got one

        $puzzle->[$row]->[$col] = $num++;
      }
    }
  }

  # figure out what row of the square the numbers will go in, and how
  # much room there is for numbers

  my $num_row = 0;
  $num_row++ until ($empty_square[$num_row] =~ /(\.+)/);

  my $num_len = length ($1);

  # make sure the numbers will fit in the open square

  my $need_len = length (sprintf "%d", $num-1);

  die "Open square not big enough for a ${need_len}-digit number"
    unless ($num_len >= $need_len);

  # check for overlap -- if the top and bottom rows of the empty and
  # full squares are all the same, then they can overlap

  my @empty = @empty_square;
  my @full  = @full_square;

  my @right;
  my $bottom;

  if ($empty[0] eq $empty[-1] && $empty[-1] eq $full[0] &&
      $full[0] eq $full[-1]) {

    # yup -- remove the bottom row from each cell, and save it to draw
    # the very bottom row of the puzzle

    $bottom = pop @empty;
    pop @full;
  }

  # similarly, if the left and right columns of the empty and full
  # squares are all the same, they can overlap as well

  my $empty_l = join ("", map { substr ($empty[$_],  0, 1) } (0..$#empty));
  my $empty_r = join ("", map { substr ($empty[$_], -1, 1) } (0..$#empty));

  my $full_l = join ("", map { substr ($full[$_],  0, 1) } (0..$#full));
  my $full_r = join ("", map { substr ($full[$_], -1, 1) } (0..$#full));

  if ($empty_l eq $empty_r && $empty_r eq $full_l && $full_l eq $full_r) {

    # yup -- remove the last column from each cell (that is, the last
    # character in each row) and save it to draw the rightmost column
    # in the puzzle

    chop $empty[$_] for (0..$#empty);
    chop $full[$_]  for (0..$#full);
    chop $bottom;

    @right = split (//, $empty_l);
  }

  # replace the cells of our array with the pictures of the squares

  foreach my $row (0..$rows) {
    foreach my $col (0..$cols) {

      # X's become full squares

      if ($puzzle->[$row]->[$col] eq 'X') {

        $puzzle->[$row]->[$col] = [@full];

      } else {

        # .'s become empty squares, and anything else is an empty square
        # with a number inside it

        my $prev = $puzzle->[$row]->[$col];
        $puzzle->[$row]->[$col] = [@empty];

        if ($prev ne '.') {

          # got a numbered square, so put the number in the proper
          # place

          $puzzle->[$row]->[$col]->[$num_row] =~
            s/\.+/sprintf "%-${num_len}d", $prev/e;
        }

        # turn all [other] .'s in the empty square into spaces

        $puzzle->[$row]->[$col]->[$_] =~ s/\./ /g
          for ($num_row..$#empty);
      }
    }

    # put the right edge back on the row, if it was removed by overlap

    push (@{$puzzle->[$row]}, [@right]) if @right;
  }

  # put it all together... for each row, loop through all of the lines
  # in the cell, and join each line across all columns to make a
  # single line of output

  $cols++ if @right;

  my @out;

  foreach my $row (0..$rows) {
    foreach my $line (0..$#empty) {
      push (@out,
            join ("", map { $puzzle->[$row]->[$_]->[$line] } (0..$cols)));
    }
  }

  # put the bottom row back on the puzzle, if it was removed by
  # overlap

  push (@out, $bottom x $len) if $bottom;
  $out[-1] .= $right[0] if (@right && $bottom);

  # done

  return @out;
}

my @out = layout_crossword (@puzzle);
print "$_\n" for @out;
