C# 7 - 414bytes414 369 bytes
using C=System.Console;class P{static void Main(){string D="",L;int W=0,H=0,i,j=0,k,q;for(;(L=C.ReadLine())!=null;D+=L,H++)W=L.Length;int[]P()=>new[]{-i,-j,i,j,i+j,j-i,-i-j,i-j};int[]B=null;for(;j<H;j++)for(i=0;i<W;i++)if(D[W*j+i]<36)for(B=B??P(),k=8;k-->0;)B[k]=B[k]<(q=P()[k]+1)?q:B[k];for (j=0;j<H;j++,C.WriteLine(L))for(L="",i=0;i<W;L+=q>8?'o':D[W*j+i],i++)for(q=k=8;k-->0;)q*=B[k]<P()[k]?0:B[k]==P()[k]?2:1;}}
Edit: switched to 1D looping, computing i
and j
on the fly
using C=System.Console;class P{static void Main(){string D="",L;int W=0,H=0,i,j,z,k,q;for(;(L=C.ReadLine())!=null;H+=W=L.Length)D+=L+="\n";int[]P()=>new[]{i=z%W,j=z/W,-i,-j,i+j,j-i,-i-j,i-j};int[]B=null;for(z=H;z-->0;)if(D[z]%7<1)for(B=B??P(),k=8;k-->0;)if(B[k]<(q=P()[k]+1))B[k]=q;for (;++z<H;C.Write(q>8?'o':D[z]))for(q=k=8;k-->0;)q*=B[k]<P()[k]?0:B[k]==P()[k]?2:1;}}
Complete program, takes input to standard in, prints it to standard out, uses #
, .
, and o
. ComputesFor each cell, it computes a 'profile' (which is the distance over 8 directions), and findsrecords a maximum of each of these. It then writes out the whole map again, and replaces any cell which is both on a boundary and not outside of any with a 'o'. The commented code below explains how it all works.
Note: that for once in my life I'm using something from the current decade, and this code requires C# 7 to compile. If you do not have C# 7, there is one line that will need to be replaced, which is clearly marked in the code.
using C=System.Console;
class P
{
static void Main()
{
// \n 10
// # 35
// . 46
// o 111
string D="", // the whole map
L; // initally each line of the map, later each line of output
int W=0, // width
H=0, // length (width * height)
i, // x-index
j=0j, // y-index
kz, // generalposition purposein countermap (decomposed into i and j by and for P)
k, // bound index
q; // tempbound storedistance, and later cell condition (0 -> outside, 8 -> inside, >8 -> on boudary)
for(;(L=C.ReadLine())!=null; // read a line, while we can
D+=L,H++) // add the lineH+=W=L.Length) to// record the mapwidth, and increment height
W=L.Length;D+=L+="\n"; // recordadd a \n to the widthline (the rest of the code treats this as a . cell), and add the line to the map
// create profile for point
// converts 1d to 2d very cheaply
// each indexentry describes the distance in one of the 8 directions: we want to maximise these to find the 'outer bounds'
// these 8 bounds describe 8 lines, together an octogen
int[]P()=>new[]{-ii=z%W,-jj=z/W,-i,-j,i+j,j-i,-i-j,i-j}; // new C#7 local method syntax (if you don't have C#7, you can test this code with the line below instead)
//i=0;Systemz=0;System.Func<int[]>P=()=>new[]{-ii=z%W,-jj=z/W,-i,-j,i+j,j-i,-i-j,i-j}; // old lambda syntax (staticmust checkerpre-assign isz worseto formake lambda,static mustchecker ensurehappy)
i is assigned)
int[]B=null; // our current bounds, initially null (must only call P() when on a #)
// TODO: swap j/i loops, reuse j=H in below
for(;j<H;j++) // for each line
for(i=0;i<W;i++z=H;z-->0;) // for each cell
if(D[W*j+i]<36D[z]%7<1) // if this cell is #
for(B=B??P(),
// init B when we first hit a #
k=8;k-->0;) // for each bound
//B[k]=B[k]<P()[k]+1?P()[k]+1:B[k]; // update if necessary
B[k]=B[k]<(B[k]<(q=P()[k]+1)?q:B[k];)B[k]=q; // update bound if necessary (add one so that we define the bound _outside_ the hashes)
for (j=0;j<H;j++, // for each line
C.WriteLine(L)) // print line of resultz=-1
for(L="", // line of result
i=0;i<W;(;++z<H; // for each cell
L+=q>8C.Write(q>8?'o':D[W*j+i],D[z])) // addprint tothe linecell (if q > 8, then we are on the bounds, otherwise, spit out whatever we were before)
i++) // must do this after and independant of D[W*j+i]
// check we are 'inside'not all'outside' any of the bounds, and that we are 'on' atleast one of them
for(q=k=8;k-->0;) // for each bound
q*=B[k]<P()[k]?0: // outside bound (q=0)
B[k]==P()[k]?2: // on bound (if q != 0, then q becomes > 8)
1; // inside (preserve q)
}
}