Google Answers Logo
View Question
 
Q: Algorithm Question ( No Answer,   0 Comments )
Question  
Subject: Algorithm Question
Category: Computers > Algorithms
Asked by: jbchh-ga
List Price: $200.00
Posted: 09 Dec 2004 00:46 PST
Expires: 23 Dec 2004 11:54 PST
Question ID: 440208
Solve one of the two problems below in the language of your choice.
definitions:
In this section we give some definitions. We consider only square n ×
n matrices filled with integers 0, . . . , n2 ? 1, each exactly once;
for example a 3 × 3 matrix filled with the nine numbers 0, 1, 2, 3, 4,
5, 6, 7, 8 as follows
0 1 2
3 4 5
6 7 8
A 2 × 2 submatrix of a matrix is simply a choice of two consecutive
rows and two consecutive columns, it gives four matrix entries, we are
interested in the sum of the values in the submatrix. (For technical
reasons, we also need to consider the last and first rows of the
matrix consecutive, and the last and first columns consecutive as
well.)

Q1)Initial question: Write a program to enumerate all integer 4×4
matrices filled with numbers 0, . . . , 15 as above so that all the
sums of all possible 2 × 2 submatrices are equal to each other (and
are equal to 30, it turns out). One such matrix is
0  15  1  14
13  2  12  3
4  11  5  10
9  6   8  7 
To eliminate some of the symmetries, you may assume that the top left
element of the matrix is always 0

More challenging question: Repeat for larger even-sized matrices, such as 
6 × 6.
Research-level question: Devise a description of all such matrices
(for n = 4 or for general n). Is there a pattern that allows you to
generate them all without an explicit search?

Q2)Initial question: Given a 5 × 5 matrix as above, for each 2 × 2
submatrix compute its sum. The difference between the largest and the
smallest sum is called the discrepancy of the matrix. For example, the
discrepancy of
0    1   2   3   4
5    6   7   8   9
10  11  12  13  14
15  16  17  18  19
20  21  22  23  24
is (18 + 19 + 23 + 24) ? (0 + 1 + 5 + 6) = 76, while the discrepancy of
0   24  1   23  2
22  3   21  4   20
5   19  6   18  7
17  8   16  9   15
10  14  11  13  12
would have been 10 (54 ? 44), except that the four corner elements are
considered a single 2 × 2 contiguous submatrix, giving a sum of 0 + 2
+ 10 + 12 = 24 and thus discrepancy 54?24 = 30. It is known that (a)
there is no such
matrix of discrepancy zero (this is what makes odd-size matrices
different from even-size matrices) and (b) there exists such a matrix
of discrepancy 10.

Write a program to find what is the minimum possible discrepancy for
5×5 matrices and to enumerate all matrices with this minimum
discrepancy.

More challenging question: Repeat for larger odd-sized matrices, such as 7 × 7.
Research-level question: What is the minimum number, for general n?
How to construct matrices with discrepancy 2n is known.

i need to solve it as soon as possible

Clarification of Question by jbchh-ga on 09 Dec 2004 01:11 PST
solve two problems, the price will be $200. if only one of them, i
will reduce the price to $100.

Request for Question Clarification by leapinglizard-ga on 09 Dec 2004 04:11 PST
The research-level questions are open-ended and not necessarily
solvable. I might be able to offer some preliminary results for each,
but I doubt I'll be able to solve them on short notice. Is it alright
if I only complete the first two parts of each question?

leapinglizard

Clarification of Question by jbchh-ga on 09 Dec 2004 21:24 PST
hi leapinglizard
It's ok to solve the Research-level questions on short notice.
Do you mean you will only complete the the Initial question and challenging 
question of Q1 or you will solve the Q1 and Q2?
if you can complete Q1 and Q2 (two Initial questions and two challenging 
questions), i will pay you $200.

thank you

Clarification of Question by jbchh-ga on 09 Dec 2004 21:30 PST
hi leapinglizard
I also want to know what kind of language you want to use.
thank you

Request for Question Clarification by leapinglizard-ga on 10 Dec 2004 04:53 PST
I'm primarily a C programmer, but I also use Java and Python. Is C acceptable?

leapinglizard

Request for Question Clarification by leapinglizard-ga on 10 Dec 2004 04:54 PST
Regarding your earlier question: yes, I'm working on both Q1 and Q2.

leapinglizard

Clarification of Question by jbchh-ga on 10 Dec 2004 15:18 PST
hi leapinglizard
c is ok, but i prefer C++
if c is comfortable to you to solve the problems, use c.
if you think C++ is ok for you to do it, i recommend you C++.
thank you.

Clarification of Question by jbchh-ga on 10 Dec 2004 17:52 PST
hi leapinglizard
I forget to tell you that both problems require backtracking search
and you can use a language that has facilities for backtracking. (feel
free to let me know if you see how to avoid an exhaustive search)
thank you
Answer  
There is no answer at this time.

The following answer was rejected by the asker (they received a refund for the question).
Subject: Re: Algorithm Question
Answered By: leapinglizard-ga on 11 Dec 2004 11:26 PST
 
Dear jbchh,

My solutions are below. I wrote the programs in C, but they also compile
under C++. I adhered to the ISO standard to ensure that they'll run on
any platform. In a Unix-compatible environment, you can compile them
with the following instructions.

  gcc border_fill.c -o border
  gcc diagonal_fill.c -o diagonal

To run the programs, execute the following.

  ./border 4
  ./diagonal 6

In addition to writing explanatory material below, I have added inline
comments to each program. If you have trouble compiling or executing
these programs, or if you have any concerns at all about my answer,
don't hesitate to let me know with a Clarification Request.

Regards,

leapinglizard




Q1.


Initial Question

With the upper left corner fixed at 0, there are 15! = 2,004,310,016
ways to fill a 4-by-4 matrix. Although it would not take unreasonably
long to run two billion iterations of a routine that fills the matrix
and checks its submatrix sums, we can significantly reduce the size of
the search space. We observe that if three cells a, b, c of a submatrix
have been chosen such that

  a+b+c < T

for some required total T, the fourth cell d is decided by

  a+b+c+d = T

  d = T-a-b-c.

The program below exploits this fact by filling the right and bottom
borders of the 4-by-4 matrix. Once these cells have been set,
the remainder of the matrix is strictly decided by the submatrix
requirement. Our program only has to check whether the matrix values are
unique and drawn from the range [1, N^2-1] for an N-by-N matrix. If we
imagine that the right and bottom borders of the matrix form a reversed
letter L --

  . . . x
  . . . x
  . . . x
  x x x x

-- then we first check the cell in the crook of the L.

  . . . x
  . . . x
  . . X x
  x x x x

If its value is unique and in the proper range, we check the cells to
the left. Once the row is complete, we move to the next row above.

  . . . x
  . . . x
  x x x x
  x x x x

The number of configurations we have to check is just the number of ways
there are to fill the right and bottom borders of a 4-by-4 matrix. Since
the four corners of the matrix constitute a 2-by-2 submatrix and the
top left corner is already 0, the remaining three corners must add up to
30. There are 19 combinations of unique integers in the range [1, 15] that
sum to 30, and 6 ways to order these combinations, for a total of 6*19 =
114 permutations. Once the corners have been set, two cells remain along
each border. Using the remaining 16-4 = 12 numbers, we can fill these in

  12*11*10*9 = 11,880

ways, for a grand total of

  114*11,880 = 1,354,320

configurations.

The only backtracking we have to do in our program is in the course of
selecting these 1.5 million border configurations, which is accomplished
by the depth-first recursive functions bottom() and right(). Once
a configuration has been found, the remaining values are verified
deterministically by the fill() function, which returns early if it finds
an invalid cell. Upon running our program, we learn that the number of
balanced 4-by-4 matrices with one fixed cell is 1272.


/*-------------------begin border_fill.c */
#include<stdlib.h>
#include<stdio.h>

int msg(char *s, int code) {            /* error-message helper */
    printf("%s\n", s);
    return code;
}

int **mm, n, sum, max, *used, *stack, ix, fail;

int clear(int top) {                    /* resets used numbers */
    while (top >= 0)
        used[stack[top--]] = 0;
    return 0;
}

int fill() {                            /* fills from bottom right corner */
    int r, c, t, top = -1;
    for (r = n-2; r > 0; r--) {         /* assume bottom border is done */
        for (c = n-2; c >= 0; c--) {    /* assume right border is done */
            t = sum - mm[r][c+1] - mm[r+1][c+1] - mm[r+1][c];
            if (t < 0 || t > max || used[t])
                return clear(top);      /* attempt to form desired sum */
            used[stack[++top] = mm[r][c] = t] = 1;
        }
        if (mm[r][0] + mm[r+1][0] + mm[r+1][n-1] + mm[r][n-1] != sum)
            return clear(top);          /* check backward at front of row */
    }
    if (mm[1][0] + mm[0][0] + mm[0][n-1] + mm[1][n-1] != sum)
        return clear(top);              /* in second row, check upward too */
    for (c = n-2; c > 0; c--) {         /* check top row */
        t = sum - mm[0][c+1] - mm[1][c+1] - mm[1][c];
        if (t < 0 || t > max || used[t])
            return clear(top);          /* attempt to form sum */
        if (t + mm[0][c+1] + mm[n-1][c+1] + mm[n-1][c] != sum)
            return clear(top);          /* check upward */
        used[stack[++top] = mm[0][c] = t] = 1;
    }
    if (sum-mm[0][1] != mm[0][0]+mm[1][0]+mm[1][1])
        return clear(top);              /* check backward and down */
    if (sum-mm[0][1] != mm[0][0]+mm[n-1][0]+mm[n-1][1])
        return clear(top);              /* check backward and up */
    ix++;                               /* if all is well, increment counter */
    /*  uncomment this block for silent enumeration 
    if (ix % 100 == 0)
        printf("%d\n", ix);
    return 0; 
    */ 
    printf("\n%5d. ", ix);              /* print solution number */
    for (c = 0; c < n; c++)             /* display top row */
        printf(" %2d", mm[0][c]);
    printf("\n");
    for (r = 1; r < n; r++) {           /* display remaining rows */
        printf("       ");
        for (c = 0; c < n; c++)
            printf(" %2d", mm[r][c]);
        printf("\n");
    }
    return clear(top);
}

int right(int r) {                      /* fill right border */
    int i;
    if (r == n-1) 
        return fill();
    for (i = 1; i <= max; i++)          /* avoid top and bottom corners */
        if (!used[i]) {
            used[mm[r][n-1] = i] = 1;
            right(r+1);
            used[i] = 0;
        }
    return 0;
}
    
int bottom(int c) {                     /* fill bottom border */
    int i;
    if (c == n-1)
        return right(1);
    for (i = 1; i <= max; i++)          /* avoid left and right corners */
        if (!used[i]) {
            used[mm[n-1][c] = i] = 1;
            bottom(c+1);
            used[i] = 0;
        }
    return 0;
}
    
int main(int argc, char *argv[]) {
    int i, j, k; 
    if (argc != 2)                      /* must pass exactly one argument */
        return msg("please specify N for an N-by-N matrix", 0);
    n = atoi(argv[1]); 
    if (n%2 != 0 || n < 2 || n > 4)     /* check for manageable size */
        return msg("N must be an even number between 2 and 4, inclusive", 0);
    mm = (int **) calloc(n, sizeof(int *));
    for (i = 0; i < n; i++)             /* allocate matrix */
        mm[i] = (int *) calloc(n, sizeof(int));
    ix = 0;
    max = n*n-1;                        /* allocate stack and flag array */
    stack = (int *) calloc(max, sizeof(int));
    used = (int *) calloc(max, sizeof(int));
    used[mm[0][0] = 0] = 1;             /* set upper left corner to 0 */
    sum = 2*n*n - 2;
    printf("looking for %d-by-%d matrices with submatrix sums == %d\n",n,n,sum);
    for (i = 1; i <= max; i++)
        for (j = 1; j <= max; j++) {    /* try two corner values */
            if (i == j)
                continue;               /* compute the third corner */
            if ((k = sum-i-j) <= 0 || k > max || k == i || k == j)
                continue;               /* check for valid range */
            used[mm[0][n-1] = i] = 1;   /* if sum is good, set corners */
            used[mm[n-1][n-1] = j] = 1;
            used[mm[n-1][0] = k] = 1;
            bottom(1);                  /* start filling at bottom border */
            used[i] = used[j] = used[k] = 0;
        }
    printf("found %d matrices\n", ix);
    return 0;
}
/*-------------------end border_fill.c */


More Challenging Question

The 6-by-6 case does not use the same submatrix sum as the 4-by-4. We
can generalize the calculation of the 2-by-2 submatrix sum as follows. In
an N-by-N matrix, the N^2 values

  0, 1, ..., N^2 - 2, N^2 - 1

have the sum

  N^2                 N^4 - N^2
  --- * (N^2 - 1)  =  --------- .
   2                      2

The number of 2-by-2 submatrices is

              N^2
  (N/2)^2  =  --- .
               4

If the matrix is balanced, then each submatrix sum has the value of the
total matrix sum divided by the number of submatrices:

  N^4 - N^2      4      N^2 - 1   2
  ---------  *  ---  =  ------- * -  =  2N^2 - 2 .
      2         N^2        1      1

We confirm that for N = 4, this value is

  2*4*4 - 2  =  32 - 2  =  30,

and for N = 6, the submatrix sums in a balanced matrix must be

  2*6*6 - 2  =  72 - 2  = 70.

The program described above takes less than a second to find all balanced
4-by-4 matrices with one fixed cell, but it is far too slow to look for
balanced 6-by-6 matrices. Indeed, we have not had the patience to wait
for it to produce a single such matrix. To see why this is so, consider
the number of ways there are to choose the bottom and left borders of a
6-by-6 matrix. Once the corners have been set, four empty cells remain
along each border. Using the remaining 36-4 = 32 numbers, there are

  32*31*30*29*28*27*26*25 = 424,097,856,000

ways to fill these. And that's without considering the permutations of
three corner values summing to 70, of which there are 612, for a total of

  612 * 424,097,856,000  =  259,547,887,872,000

ways to fill the right and bottom borders. Valid configurations are
rather sparse in this space, leaving many iterations between each
balanced matrix.

To write a program that can solve the 6-by-6 case in reasonable time,
we used a depth-first recursion that mitigates backtracking by filling
the matrix in a more efficient order. As before, we rely on the fact
that deciding three cells of a submatrix decides the fourth. Instead
of blindly choosing values for the right and bottom borders, however,
we fill the matrix in diagonal stripes. The longest such diagonal runs
from the bottom left corner to the top right, consisting of exactly 6
cells. The remaining diagonals run parallel to it.

We start filling diagonals at the top left and proceeed toward the bottom
right. Since the top left corner is fixed at 0, we begin by choosing
two unique values in the range [1, 35].

  x X . . . .
  X . . . . .
  . . . . . .
  . . . . . .
  . . . . . .
  . . . . . .

These choices decide the value of the fourth cell in the top left
submatrix. If it is not among the previously used numbers, we can set
it and proceed to the next diagonal.

  x x . . . .
  x X . . . .
  . . . . . .
  . . . . . .
  . . . . . .
  . . . . . . 

After choosing a value for the leftmost cell in this diagonal, we have
obtained three values of a submatrix, thereby deciding the fourth.`

  x x . . . .
  x x . . . . 
  X X . . . .
  . . . . . .
  . . . . . .    
  . . . . . .

The middle cell in this diagonal has already been set. By choosing a
value for the rightmost cell, we once again force the fourth cell in
a submatrix.
  
  x x X . . .
  x x X . . .
  x x . . . .
  . . . . . .
  . . . . . .
  . . . . . .

We always set values two at a time by proceeding in this fashion. Another
advantage is that we eliminate many matrix configurations after filling
a small part of the upper left corner. Our first program, in comparison,
has to fill 14 cells of a 6-by-6 matrix before it gets around to checking
for validity. Our new program can in many cases recognize invalidity
and backtrack before it plunges so deeply into a fruitless part of the
state space.

Even with these improvements, it takes a non-trivial amount of time to
find all balanced 6-by-6 matrices with one fixed cell. After 3 hours and
15 minutes of real execution time on a 1.6 GHz Athlon CPU, we learn that
the number of matrices satisfying these conditions is 1,224,576.


/*-------------------begin diagonal_fill.c */
#include<stdlib.h>
#include<stdio.h>

int msg(char *s, int code) {            /* error-message helper */
    printf("%s\n", s);
    return code;
}

int **mm, *used, n, max, sum, ix;

int dr[] = {0, 0, 1, 1};                /* vertical displacement */
int dc[] = {0, 1, 0, 1};                /* horizontal displacement */

int getsum(int r, int c) {              /* computes sum rightward, downward */
    int i, t = 0, tt;
    for (i = 0; i < 4; i++) {
        tt = mm[(r+dr[i]+n)%n][(c+dc[i]+n)%n];
        if (tt != -1)                   /* check for sentinel value */
            t += tt;
    }
    return t;
}

int min(int a, int b) {                 /* returns lesser of two integers */
    if (a < b)
        return a;
    return b;
}

void diag(int r, int c, int di, int t_sum) {
    int i, j, rem, rr, cc;              /* diagonals stretch SW to NE */
    if (di == 0) {                      /* first diagonal drawn at NW corner */
        if (r < 0 || c == n) {          /* last diagonal at SE corner */
            if (r == n-2) {             /* check for completion */
                ix++;
                /*  uncomment this block for silent enumeration
                if (ix % 100 == 0)
                    printf("%d\n", ix);
                return;
                */
                printf("\n%5d. ", ix);  /* print solution number */
                for (j = 0; j < n; j++) /* display top row */
                    printf(" %2d", mm[0][j]);
                printf("\n");
                for (i = 1; i < n; i++) {
                    printf("       ");  /* display remaining rows */
                    for (j = 0; j < n; j++)
                        printf(" %2d", mm[i][j]);
                    printf("\n");
                }
                return;
            }
            if (c == n) {               /* wrapping from right to bottom */
                c = 2+r;
                r = n-1;
            }
            else {                      /* wrapping from top to left */
                r = c;
                c = 0;
            }
        }
        t_sum = getsum(r, c);           /* compute sum rightward, downward */
        if (t_sum > sum)
            return;
    }
    if (di == 4) {                      /* have we gone around the submatrix? */
        if (t_sum == sum)
            diag(r-1, c+1, 0, -1);      /* if so, move along diagonal */
        return;
    }
    rr = (r+dr[di])%n;                  /* visit next cell in submatrix */
    cc = (c+dc[di])%n;
    if (mm[rr][cc] != -1) {             /* cell already set? */ 
        diag(r, c, di+1, t_sum);        /* if so, move to next cell */
        return;
    }
    rem = sum-t_sum;                    /* how much more to complete sum? */
    if (di == 3) {                      /* last cell forces value */
        if (rem <= max && !used[rem]) { /* check for valid range */
            used[rem] = 1;              /* mark */
            mm[rr][cc] = rem;           /* set */
            diag(r-1, c+1, 0, -1);      /* recurse */
            mm[rr][cc] = -1;            /* unset */ 
            used[rem] = 0;              /* unmark */
        }
        return;
    }
    if (t_sum >= sum)                   /* bail out if partial sum is invalid */
        return;
    for (i = min(rem, max); i > 0; i--) {
        if (used[i])                    /* seek unused values */
            continue;
        used[i] = 1;                    /* mark */ 
        mm[rr][cc] = i;                 /* set */
        diag(r, c, di+1, t_sum+i);      /* recurse */
        mm[rr][cc] = -1;                /* unset */
        used[i] = 0;                    /* unmark */
    }
}
    
int main(int argc, char *argv[]) {
    int i, j; 
    if (argc != 2)                      /* must pass exactly one argument */
        return msg("please specify N for an N-by-N matrix", 0);
    n = atoi(argv[1]);
    if (n%2 != 0 || n < 2 || n > 6)     /* check for manageable size */
        return msg("N must be an even number between 2 and 6, inclusive", 0);
    sum = 2*n*n - 2;
    mm = (int **) calloc(n, sizeof(int *));
    for (i = 0; i < n; i++) {           /* allocate matrix */
        mm[i] = (int *) calloc(n, sizeof(int));
        for (j = 0; j < n; j++)
            mm[i][j] = -1;              /* initialize cells to sentinel */
    }
    used = (int *) calloc(n*n, sizeof(int));
    max = n*n-1;
    used[mm[0][0] = 0] = 1;             /* set upper left corner to 0 */
    ix = 0;
    printf("looking for %d-by-%d matrices with submatrix sums == %d\n", n,n,sum);
    diag(0, 0, 0, -1);                  /* start filling from top left */
    printf("found %d matrices\n", ix);
    return 0;
}
/*-------------------end diagonal_fill.c */



Q2.


This is a trick question. There is no need to write a program that
enumerates matrices of minimum discrepancy, since their total number
can be calculated directly with a simple formula. The "research-level"
exercise effectively makes the "initial" and "challenging" ones redundant.


Research-Level Question
    
    
Let us describe the construction of an N-by-N matrix of minimum
discrepancy such that N is odd and N >= 5. We are given N^2 values

  0, 1, ..., N^2 - 2, N^2 - 1

with which to uniquely fill the N^2 cells of the matrix.

The smallest sum that can be formed by any four of these values is

  0 + 1 + 2 + 3  =  6.

The greatest possible sum is

  (N^2 - 4) + (N^2 - 3) + (N^2 - 2) + (N^2 - 1)  =   4N^2 - 10.

Since the values in each sum do not overlap for N >= 5, and because a
matrix of such size can accommodate several 2-by-2 submatrices without
overlap, it is certainly possible to fill the matrix so that it contains
submatrices having each of these sums. The resulting discrepancy is

  4N^2 - 10 - 6  =  4N^2 - 16.

For N = 5 and N = 7, this yields minimum discrepancies of

  4*5*5 - 16  =  100 - 16  =  84

and

  4*7*7 - 16  =  196 - 16  =  180,

respectively.

Now let us calculate the number of ways to form such a matrix if the
upper left corner is set to 0. We begin by observing that submatrices
consisting of the values

  {0, 1, 2, 3}

and

  {N^2 - 4, N^2 - 3, N^2 - 2, N^2 - 1}

are necessary in a matrix of minimum discrepancy. No other values can
form submatrices having sums 6 and N^2 - 10. These submatrices are also
sufficient, for once they have been placed, the remaining cells of the
matrix can take any values without affecting the smallest and largest
submatrix sums.

If the upper left corner is already 0, the submatrix of smallest sum must
be in one of four positions, with the values composing it arranged in one
of 3! = 6 ways. Suppose we have chosen one of these 4*6 = 24 possibilities.

  0 1 . . .
  2 3 . . .
  . . . . .
  . . . . .
  . . . . .

We now wish to place one of the 4! = 24 submatrices of greatest sum
somewhere in the matrix. Of the N^2 possible locations for the upper
left corner of such a submatrix, four are occupied by the submatrix of
smallest sum. Thus, N^2 - 4 possible locations are left.

Once we have placed the submatrices of smallest and greatest sum, N^2 - 8
cells remain to be filled by the N^2 - 8 other values. This can be done
in (N^2 - 8)! ways.

In total, then, the number of possible configurations for an N-by-N
matrix of minimum discrepancy such that N is odd and N >= 5, with one
fixed cell, is the following.

  24 * 24 * (N^2 - 4) * (N^2 - 8)!
  
  =  576 * (N^2 - 4) * (N^2 - 8)!

For N = 5, this formula yields

  576 * 21 * 355,687,428,096,000  =  4,302,395,130,249,216,000.
  
For N = 7, the value is

  576 * 45 * 33,452,526,613,163,807,108,170,062,053,440,751,665,152,000,000,000
  =  867,089,489,813,205,880,243,768,008,425,184,283,160,739,840,000,000,000.

To construct every such configuration would be a long and thankless chore.

Request for Answer Clarification by jbchh-ga on 11 Dec 2004 15:01 PST
hi leapinglizard
can you answer these questions separately like initial and challenging
questions of Q1 that you answered and please answer the initial and
challenging questions of Q2. (please don't answer the two research
questions together)

Q1:

1)Initial question: Write a program to enumerate all integer 4×4
matrices filled with numbers 0, . . . , 15 as above so that all the
sums of all possible 2 × 2 submatrices are equal to each other. To
eliminate some of the symmetries, you may assume that the top left
element of the matrix is always 0

2)challenging question: Repeat for larger even-sized matrices, such as 6 × 6.

3)Research-level question: Devise a description of all such
matrices(for n = 4 or for general n). Is there a pattern that allows
you to generate them all without an explicit search?

Q2:

1)Write a program to find what is the minimum possible discrepancy for
5×5 matrices and to enumerate all matrices with this minimum
discrepancy.

2)challenging question: Repeat for larger odd-sized matrices, such as 7 × 7.

3)Research-level question: What is the minimum number, for general n?
How to construct matrices with discrepancy 2n is known.

on the other hand, I use Microsoft Visual C++ 6.0 to compile the two
programs of Q1. There is no error but when I execute the program, the
console window only show this

please specify N for an N-by-N matrix
Press any key to continue

thank you

Clarification of Answer by leapinglizard-ga on 11 Dec 2004 16:13 PST
I have not answered the research-level questions together. Above, you
will find the answer to Q2 only. In my answer, I explain why it is
unnecessary to enumerate the configurations of minimum discrepancy,
since their number can be calculated directly. The last two
calculations show the number of such configurations for matrices of
size 5 and 7. These are the answers to the first two parts of Q2. The
entire question is answered quite separately from Q1.

When you run the programs for Q1, you must pass a single argument, as
I state at the beginning of my answer. This argument is the size of
the matrix. Just type the name of the compiled program on the command
line, followed by a space and the size of the matrix. See the examples
above.

leapinglizard

Clarification of Answer by leapinglizard-ga on 11 Dec 2004 16:38 PST
Whoops, hang on a minute. I misread Q2 as asking for the maximum
discrepancy, whereas it actually wants the minimum. The discrepancy of
a given matrix is the greatest difference between the sums of any two
submatrices, so we want to minimize the maximum. It's a bit confusing,
isn't it? My answer to Q2 makes sense if you replace "minimum" with
"maximum" everywhere, but then of course it's not answering the same
question. You can throw out my answer to Q2 and keep the answer to Q1,
which is correct. Let me get back to you with Q2.

leapinglizard

Request for Answer Clarification by jbchh-ga on 11 Dec 2004 17:26 PST
hi leapinglizard
I can't find your Research Question of Q1.

I am using windows xp. Can you explain how to run it on the command
line step by step.
thank you

Request for Answer Clarification by jbchh-ga on 11 Dec 2004 21:58 PST
hi leapinglizard
There is a suggestion for the 6×6 problem. If some entry of the matrix
is fully determined by the elements that have already been chosen,
just fill in the entry without "searching" for the right value.

Request for Answer Clarification by jbchh-ga on 16 Dec 2004 12:26 PST
hi leapinglizard
I need the answer before Dec/22, and I need the time to compile them.

1)
I am using Microsoft Visual C++ 6.0 and Windows XP. You said I must
pass a single argument. How should I do to enter a single argument
because the console window shows this:

please specify N for an N-by-N matrix
Press any key to continue

If I press any key, the window will close.

your instructions:

  gcc border_fill.c -o border
  gcc diagonal_fill.c -o diagonal

To run the programs, execute the following.

  ./border 4
  ./diagonal 6

However, it is not work for me. Can you tell me how to do it step by step

2)
You miss the Research question of Q1 and Q2. I need them ASAP.

thank you

Clarification of Answer by leapinglizard-ga on 16 Dec 2004 16:27 PST
1)

I can't tell you how to pass an argument to an executable on your
particular platform. You really should know how to do this if you're
using a compiler at all.

However, I'll prepare a version of the program that, instead of taking
an argument on the command line, prompts the user to enter it during
execution.


2) You said you didn't need the research-level questions answered. In
any case, they are open-ended problems that don't necessarily have an
answer. It is possible that one can do no better than offer some
preliminary results.


In regard to your earlier suggestion, you'll find that I have
addressed precisely that point in my answer to Q1. I discuss at
length, and illustrate with diagrams, how certain parts of a solution
are forced by earlier moves.


leapinglizard

Request for Answer Clarification by jbchh-ga on 16 Dec 2004 22:34 PST
hi leapinglizard
1)
You said you would prepare a version of the program that when I
execute the program, it will show like this "please enter the size of
the matrix:", and then I can enter 4 in the border_fill program and 6
in the diagonal_fill program, right?

2)
I said It's ok to solve the Research-level questions on short notice
before you answered the question. I didn't mean that you can throw
them away.

I hope you can complete the answer before Dec/19, and then I can
arrange the answer. If you can't do it, please let me know.
thank you

Clarification of Answer by leapinglizard-ga on 21 Dec 2004 03:30 PST
2) 

I'm not sure you understand the meaning of the phrase "short notice".
However, I was quite sure I understood you to say that you did not
require solutions for the research-level questions. By the way,
research is something that takes months and years to complete, not
merely days or weeks.


1)

Here are new versions of border_fill and diagonal_fill that don't take
an argument on the command line, but prompt for the matrix size during
execution.


/*-------------------begin border_fill.c */
#include<stdlib.h>
#include<stdio.h>

int msg(char *s, int code) {            /* error-message helper */
    printf("%s\n", s);
    return code;
}

int **mm, n, sum, max, *used, *stack, ix, fail;

int clear(int top) {                    /* resets used numbers */
    while (top >= 0)
        used[stack[top--]] = 0;
    return 0;
}

int fill() {                            /* fills from bottom right corner */
    int r, c, t, top = -1;
    for (r = n-2; r > 0; r--) {         /* assume bottom border is done */
        for (c = n-2; c >= 0; c--) {    /* assume right border is done */
            t = sum - mm[r][c+1] - mm[r+1][c+1] - mm[r+1][c];
            if (t < 0 || t > max || used[t])
                return clear(top);      /* attempt to form desired sum */
            used[stack[++top] = mm[r][c] = t] = 1;
        }
        if (mm[r][0] + mm[r+1][0] + mm[r+1][n-1] + mm[r][n-1] != sum)
            return clear(top);          /* check backward at front of row */
    }
    if (mm[1][0] + mm[0][0] + mm[0][n-1] + mm[1][n-1] != sum)
        return clear(top);              /* in second row, check upward too */
    for (c = n-2; c > 0; c--) {         /* check top row */
        t = sum - mm[0][c+1] - mm[1][c+1] - mm[1][c];
        if (t < 0 || t > max || used[t])
            return clear(top);          /* attempt to form sum */
        if (t + mm[0][c+1] + mm[n-1][c+1] + mm[n-1][c] != sum)
            return clear(top);          /* check upward */
        used[stack[++top] = mm[0][c] = t] = 1;
    }
    if (sum-mm[0][1] != mm[0][0]+mm[1][0]+mm[1][1])
        return clear(top);              /* check backward and down */
    if (sum-mm[0][1] != mm[0][0]+mm[n-1][0]+mm[n-1][1])
        return clear(top);              /* check backward and up */
    ix++;                               /* if all is well, increment counter */
    /*  uncomment this block for silent enumeration
    if (ix % 100 == 0)
        printf("%d\n", ix);
    return 0;
    */
    printf("\n%5d. ", ix);              /* print solution number */
    for (c = 0; c < n; c++)             /* display top row */
        printf(" %2d", mm[0][c]);
    printf("\n");
    for (r = 1; r < n; r++) {           /* display remaining rows */
        printf("       ");
        for (c = 0; c < n; c++)
            printf(" %2d", mm[r][c]);
        printf("\n");
    }
    return clear(top);
}

int right(int r) {                      /* fill right border */
    int i;
    if (r == n-1)
        return fill();
    for (i = 1; i <= max; i++)          /* avoid top and bottom corners */
        if (!used[i]) {
            used[mm[r][n-1] = i] = 1;
            right(r+1);
            used[i] = 0;
        }
    return 0;
}

int bottom(int c) {                     /* fill bottom border */
    int i;
    if (c == n-1)
        return right(1);
    for (i = 1; i <= max; i++)          /* avoid left and right corners */
        if (!used[i]) {
            used[mm[n-1][c] = i] = 1;
            bottom(c+1);
            used[i] = 0;
        }
    return 0;
}

int main() {
    int i, j, k;
    printf("please enter matrix size (2 or 4): ");
    scanf("%d", &n);
    if (n%2 != 0 || n < 2 || n > 4)     /* check for manageable size */
        return msg("N must be an even number between 2 and 4, inclusive", 0);
    mm = (int **) calloc(n, sizeof(int *));
    for (i = 0; i < n; i++)             /* allocate matrix */
        mm[i] = (int *) calloc(n, sizeof(int));
    ix = 0;
    max = n*n-1;                        /* allocate stack and flag array */
    stack = (int *) calloc(max, sizeof(int));
    used = (int *) calloc(max, sizeof(int));
    used[mm[0][0] = 0] = 1;             /* set upper left corner to 0 */
    sum = 2*n*n - 2;
    printf("looking for %d-by-%d matrices with submatrix sums == %d\n",n,n,sum);
    for (i = 1; i <= max; i++)
        for (j = 1; j <= max; j++) {    /* try two corner values */
            if (i == j)
                continue;               /* compute the third corner */
            if ((k = sum-i-j) <= 0 || k > max || k == i || k == j)
                continue;               /* check for valid range */
            used[mm[0][n-1] = i] = 1;   /* if sum is good, set corners */
            used[mm[n-1][n-1] = j] = 1;
            used[mm[n-1][0] = k] = 1;
            bottom(1);                  /* start filling at bottom border */
            used[i] = used[j] = used[k] = 0;
        }
    printf("found %d matrices\n", ix);
    return 0;
}
/*-------------------end border_fill.c */


/*-------------------begin diagonal_fill.c */
#include<stdlib.h>
#include<stdio.h>

int msg(char *s, int code) {            /* error-message helper */
    printf("%s\n", s);
    return code;
}

int **mm, *used, n, max, sum, ix;

int dr[] = {0, 0, 1, 1};                /* vertical displacement */
int dc[] = {0, 1, 0, 1};                /* horizontal displacement */

int getsum(int r, int c) {              /* computes sum rightward, downward */
    int i, t = 0, tt;
    for (i = 0; i < 4; i++) {
        tt = mm[(r+dr[i]+n)%n][(c+dc[i]+n)%n];
        if (tt != -1)                   /* check for sentinel value */
            t += tt;
    }
    return t;
}

int min(int a, int b) {                 /* returns lesser of two integers */
    if (a < b)
        return a;
    return b;
}

void diag(int r, int c, int di, int t_sum) {
    int i, j, rem, rr, cc;              /* diagonals stretch SW to NE */
    if (di == 0) {                      /* first diagonal drawn at NW corner */
        if (r < 0 || c == n) {          /* last diagonal at SE corner */
            if (r == n-2) {             /* check for completion */
                ix++;
                /*  uncomment this block for silent enumeration
                if (ix % 100 == 0)
                    printf("%d\n", ix);
                return;
                */
                printf("\n%5d. ", ix);  /* print solution number */
                for (j = 0; j < n; j++) /* display top row */
                    printf(" %2d", mm[0][j]);
                printf("\n");
                for (i = 1; i < n; i++) {
                    printf("       ");  /* display remaining rows */
                    for (j = 0; j < n; j++)
                        printf(" %2d", mm[i][j]);
                    printf("\n");
                }
                return;
            }
            if (c == n) {               /* wrapping from right to bottom */
                c = 2+r;
                r = n-1;
            }
            else {                      /* wrapping from top to left */
                r = c;
                c = 0;
            }
        }
        t_sum = getsum(r, c);           /* compute sum rightward, downward */
        if (t_sum > sum)
            return;
    }
    if (di == 4) {                      /* have we gone around the submatrix? */
        if (t_sum == sum)
            diag(r-1, c+1, 0, -1);      /* if so, move along diagonal */
        return;
    }
    rr = (r+dr[di])%n;                  /* visit next cell in submatrix */
    cc = (c+dc[di])%n;
    if (mm[rr][cc] != -1) {             /* cell already set? */
        diag(r, c, di+1, t_sum);        /* if so, move to next cell */
        return;
    }
    rem = sum-t_sum;                    /* how much more to complete sum? */
    if (di == 3) {                      /* last cell forces value */
        if (rem <= max && !used[rem]) { /* check for valid range */
            used[rem] = 1;              /* mark */
            mm[rr][cc] = rem;           /* set */
            diag(r-1, c+1, 0, -1);      /* recurse */
            mm[rr][cc] = -1;            /* unset */
            used[rem] = 0;              /* unmark */
        }
        return;
    }
    if (t_sum >= sum)                   /* bail out if partial sum is invalid */
        return;
    for (i = min(rem, max); i > 0; i--) {
        if (used[i])                    /* seek unused values */
            continue;
        used[i] = 1;                    /* mark */
        mm[rr][cc] = i;                 /* set */
        diag(r, c, di+1, t_sum+i);      /* recurse */
        mm[rr][cc] = -1;                /* unset */
        used[i] = 0;                    /* unmark */
    }
}

int main(int argc, char *argv[]) {
    int i, j;
    printf("please enter matrix size (2, 4, or 6): ");
    scanf("%d", &n);
    if (n%2 != 0 || n < 2 || n > 6)     /* check for manageable size */
        return msg("N must be an even number between 2 and 6, inclusive", 0);
    sum = 2*n*n - 2;
    mm = (int **) calloc(n, sizeof(int *));
    for (i = 0; i < n; i++) {           /* allocate matrix */
        mm[i] = (int *) calloc(n, sizeof(int));
        for (j = 0; j < n; j++)
            mm[i][j] = -1;              /* initialize cells to sentinel */
    }
    used = (int *) calloc(n*n, sizeof(int));
    max = n*n-1;
    used[mm[0][0] = 0] = 1;             /* set upper left corner to 0 */
    ix = 0;
    printf("looking for %d-by-%d matrices with submatrix sums == %d\n", n,n,sum);
    diag(0, 0, 0, -1);                  /* start filling from top left */
    printf("found %d matrices\n", ix);
    return 0;
}
/*-------------------end diagonal_fill.c */

Request for Answer Clarification by jbchh-ga on 21 Dec 2004 22:02 PST
Hi leapinglizard
Sorry about that I have to tell you that I applied for refund in
Dec/19. I don't understand why you still work on the question. I asked
Answers-Support before I applied for the refund. They told me that the
Researcher is notified automatically when a refund is requested so I
didn't inform you. I was waiting for clarification of answer from you
and I request you could complete the answer before Dec.19 because I
needed to arrange the answer. I told you if you couldn't do it, please
let me know. Unfortunately, I was waiting for 4 days. There was no
reply from you.

By the way, you only post the solutions of Q1 without the short notice
of Research-level questions. I think you don't need to go on to work
on Q2 because I applied for the refund and the holiday is coming.
sorry.

Clarification of Answer by leapinglizard-ga on 21 Dec 2004 22:20 PST
I'm sorry about the misunderstanding.

leapinglizard
Reason this answer was rejected by jbchh-ga:
I am unsatisfied with my answer due to three reasons.

1) This is obviously unfinished answer. Even if he posted additional
information, this was still unfinished answer. The researcher missed
the short notice for research-level question of Q1 and the whole Q2.

2) I was washed-out to request for answer clarification from the
researcher again and again. First of all, the researcher said he would
work on both of Q1 and Q2 before he posted the answer. However, the
answer of Q2 was this was a trick question and there was no need to
write a program. After request for answer clarification, the
researcher still clarified the Q2 was unnecessary to do it. After the
researcher read it carefully. He realized he misread Q2. Second, I
said it was ok to solve the research-level questions on short notice
before the researcher answered the question. I didn’t mean that he
could throw them away. I did not ask him to write solutions for the
research-level questions. I just ask him for short notice.

3) I was waiting for clarification of answer from the researcher and I
request he could complete the answer before Dec.19 because I needed to
arrange the answer. I told him if he couldn't do it, please let me
know. Unfortunately, I was waiting for 4 days. There was no reply from
the researcher. Because of my time pressure and the refund policy
which is after 30 days refunds are no longer possible and then the
holiday is coming, I decide to apply for a full refund.

Thank you

Comments  
There are no comments at this time.

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy