Le Monde puzzle [#1001]

After a long lag (due to my missing the free copies distributed at Paris-Dauphine!), here is a Sudoku-like Le Monde mathematical puzzle:

A grid of size (n,n) holds integer values such that any entry larger than 1 is the sum of one term in the same column and one term in the same row. What is the maximal possible value observed in such a grid when n=3,4?

This can be solved in R by a random exploration of such possible grids in a simulated annealing spirit:

mat=matrix(1,N,N)
goal=1

targ=function(mat){ #check constraints
  d=0
  for (i in (1:(N*N))[mat>1]){
    r=(i-1)%%N+1;c=(i-1)%/%N+1
    d=d+(min(abs(mat[i]-outer(mat[-r,c],mat[r,-c],"+")))>0)} 
  return(d)}

cur=0
for (t in 1:1e6){
  i=sample(1:(N*N),1);prop=mat
  prop[i]=sample(1:(2*goal),1)
  d=targ(prop)
  if (10*log(runif(1))/t<cur-d){ 
      mat=prop;cur=d} 
  if ((d==0)&(max(prop)>goal)){
     goal=max(prop);maxx=prop}}

returning a value of 8 for n=3 and 37 for n=4. However, the method is quite myopic and I tried instead a random filling of the grid, using each time the maximum possible sum for empty cells:

goal=1
for (v in 1:1e6){
  mat=matrix(0,N,N)
  #one 1 per row/col
  for (i in 1:N) mat[i,sample(1:N,1)]=1
  for (i in 1:N) if (max(mat[,i])==0) mat[sample(1:N,1),i]=1
  while (min(mat)==0){
   parm=sample(1:(N*N)) #random order
   for (i in parm[mat[parm]==0]){
    r=(i-1)%%N+1;c=(i-1)%/%N+1
    if ((max(mat[-r,c])>0)&(max(mat[r,-c])>0)){
      mat[i]=max(mat[-r,c])+max(mat[r,-c])
      break()}}}
    if (goal<max(mat)){
    goal=max(mat);maxx=mat}}

which recovered a maximum of 8 for n=3, but reached 48 for n=4. And 211 for n=5, 647 for n=6… For instance, here is the solution for n=4:

[1,]    1    5   11   10
[2,]    2    4    1    5
[3,]   48    2   24    1
[4,]   24    1   22   11

While the update in the above is random and associated with the first term in the permutation, it may be preferable to favour the largest possible term at each iteration, which I tried as

while (min(mat)==0){
parm=sample(1:(N*N))
val=0*parm
for (i in parm[mat[parm]==0]){
    r=(i-1)%%N+1;c=(i-1)%/%N+1
        if ((max(mat[-r,c])>0)&(max(mat[r,-c])>0)){
      val[i]=max(mat[-r,c])+max(mat[r,-c])}
      }
#largest term
i=order(-val)[1];mat[i]=val[i]}

For n=4, I did not recover the maximal value 48, but achieved larger values for n=5 (264) and n=6 (2256).

As an aside, the R code sometimes led to a strange error message linked with the function sample(), which is that too large a bound in the range produces the following

> sample(1:1e10,1)
Error: cannot allocate vector of size 74.5 Gb

meaning that 1:1e10 first creates a vector for all the possible values. The alternative

> sample.int(1e10,1)
[1] 7572058778

works, however. And only breaks down for 10¹².

3 Responses to “Le Monde puzzle [#1001]”

  1. I’m confused– it doesn’t appear that you’ve demonstrated (mathematically) that any of your methods guarantee the true maximum value is returned, or at least not without performing a complete exhaustive search.

    • Dear Carl, there is no need to get confused: my approach to those Le Monde puzzles is to write a piece of R code that looks at simulation based solutions, but they are often exploratory and short from optimal! You are thus quite right to state that the code does not guarantee the true maximum. Thanks,
      Xi’an

  2. […] article was first published on R – Xi'an's Og, and kindly contributed to […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s