Skip to main content
added explanation
Source Link
Neil
  • 185.9k
  • 12
  • 77
  • 295

JavaScript (ES6), 369369 343 bytes

f=s=>(a=s.split`
`.map(s=>[...s]),n=[i=1/0,i,i,i],x=[i=-i,i,i,i]m=Array(8),a.map((b,i)=>b.map((c,j)=>c<'.'&&[i=>c>'#'||[i-j,i-,j+i,j,j-i,j+i]-i,-i-j,-j].map((d,k)=>(d>n[k]||=>d>m[k]||(n[k]=dm[k]=d-1),d<x[k]||(x[k]=d+1))))),[o,p,q,r]=nr,[tt,u,v,w]=xw]=m,g=(i,j,k,l,...p)=>i-k|j-l?a[i][j]=g(i+(k>i)-(k<i),j+(l>j)-(l<j),k,l,...p):1/p[0]?g(k,l,...p):'o',g(o,o-p,o,rp-o,r-qp,q,q+u-p,q-r,tr,r-t,r,-u,t-u,w-tu,wu-v,w-v,v+p,v-w,o-w,o-w,p,p-o),a.map(b=>b.join``).join`
`)

Explanation coming soon! But basic idea seems: The string is split into a character array (I'm unclear as to whether character array input is acceptable). The array is then iterated over and the positions of all the land squares are located. The bounding lines given by the equations x - y = o, x = p, x + y = q, y = r, y - x = t, -x = u, -x - y = v, -y = w are determined such that the maximum possible parameter is chosen where all the land lies beyond the line. This has the effect of enclosing the island in an octagon. The coordinates of the corners of the octagon are readily calculated from the parameters and the cells on its edge are filled in. The array is then joined back into a string. The reason an octagon suffices is as follows:

   /o#     /o#     /o#
 |/o #   |/o #   |/ o#
 *o###   * o #   *  o#
/|o #   /|o #   /| o#
 |o#     |o#     |o#

Consider a corner of the octagon. At some point along the two edges the path will be similarlimited by the land because we constructed the octagon to @Lera'stouch the land as closely as possible. If there is no land at the corner itself, the path could take the alternate routes as shown on the right, but that is still the same number of orthogonal and diagonal steps, so the distance is unchanged.

JavaScript (ES6), 369 bytes

f=s=>(a=s.split`
`.map(s=>[...s]),n=[i=1/0,i,i,i],x=[i=-i,i,i,i],a.map((b,i)=>b.map((c,j)=>c<'.'&&[i,i-j,j,j+i].map((d,k)=>(d>n[k]||(n[k]=d-1),d<x[k]||(x[k]=d+1))))),[o,p,q,r]=n,[t,u,v,w]=x,g=(i,j,k,l,...p)=>i-k|j-l?a[i][j]=g(i+(k>i)-(k<i),j+(l>j)-(l<j),k,l,...p):1/p[0]?g(k,l,...p):'o',g(o,o-p,o,r-o,r-q,q,q+u,q,t,t-u,t,w-t,w-v,v,v+p,v,o,o-p),a.map(b=>b.join``).join`
`)

Explanation coming soon! But basic idea seems to be similar to @Lera's.

JavaScript (ES6), 369 343 bytes

f=s=>(a=s.split`
`.map(s=>[...s]),m=Array(8),a.map((b,i)=>b.map((c,j)=>c>'#'||[i-j,i,j+i,j,j-i,-i,-i-j,-j].map((d,k)=>d>m[k]||(m[k]=d-1)))),[o,p,q,r,t,u,v,w]=m,g=(i,j,k,l,...p)=>i-k|j-l?a[i][j]=g(i+(k>i)-(k<i),j+(l>j)-(l<j),k,l,...p):1/p[0]?g(k,l,...p):'o',g(p,p-o,p,q-p,q-r,r,r-t,r,-u,t-u,-u,u-v,w-v,-w,o-w,-w,p,p-o),a.map(b=>b.join``).join`
`)

Explanation: The string is split into a character array (I'm unclear as to whether character array input is acceptable). The array is then iterated over and the positions of all the land squares are located. The bounding lines given by the equations x - y = o, x = p, x + y = q, y = r, y - x = t, -x = u, -x - y = v, -y = w are determined such that the maximum possible parameter is chosen where all the land lies beyond the line. This has the effect of enclosing the island in an octagon. The coordinates of the corners of the octagon are readily calculated from the parameters and the cells on its edge are filled in. The array is then joined back into a string. The reason an octagon suffices is as follows:

   /o#     /o#     /o#
 |/o #   |/o #   |/ o#
 *o###   * o #   *  o#
/|o #   /|o #   /| o#
 |o#     |o#     |o#

Consider a corner of the octagon. At some point along the two edges the path will be limited by the land because we constructed the octagon to touch the land as closely as possible. If there is no land at the corner itself, the path could take the alternate routes as shown on the right, but that is still the same number of orthogonal and diagonal steps, so the distance is unchanged.

Source Link
Neil
  • 185.9k
  • 12
  • 77
  • 295

JavaScript (ES6), 369 bytes

f=s=>(a=s.split`
`.map(s=>[...s]),n=[i=1/0,i,i,i],x=[i=-i,i,i,i],a.map((b,i)=>b.map((c,j)=>c<'.'&&[i,i-j,j,j+i].map((d,k)=>(d>n[k]||(n[k]=d-1),d<x[k]||(x[k]=d+1))))),[o,p,q,r]=n,[t,u,v,w]=x,g=(i,j,k,l,...p)=>i-k|j-l?a[i][j]=g(i+(k>i)-(k<i),j+(l>j)-(l<j),k,l,...p):1/p[0]?g(k,l,...p):'o',g(o,o-p,o,r-o,r-q,q,q+u,q,t,t-u,t,w-t,w-v,v,v+p,v,o,o-p),a.map(b=>b.join``).join`
`)

Explanation coming soon! But basic idea seems to be similar to @Lera's.