X Marks the Spot
Python 3, 577 519 515 490 475 467 454 bytes
def c(g,d):
R,L,V,e,b=range,list,len,'-|+','#';t,g=(lambda g,d:sum([[(i,j)for j in R(V(L(g.split('\n')[i])))if g.split('\n')[i][j]==d]for i in R(V(g.split('\n')))],[]))(g,d),[L(i)for i in g.split('\n')]
for a,r in t:
for j in R(a-3,a+4):
if V(g)>j>-1:n=g[j][r];g[j][r]='+'if n in e else'#'if n in(d,b)else'|'
for j in R(r-5,r+6):
if V(g[a])>j>-1:n=g[a][j];g[a][j]='+'if n in e else'#'if n in(d,b)else'-'
return'\n'.join(''.join(l)for l in g)
I'm not sure how much farther I can golf this.
Usage:
c(g, d)
Where g
is the input grid and d
is the crosshair-marking character.
Perl, 370 bytes
sub r{$h=pop;($=[$n=pop].=$"x(1+"@_"-length$=[$n]))=~s!(.{@_})(.)!"$1".($2=~/[-|+]/?'+':$2=~/[X#]/?'#':$h)!e}map{chop;push@c,[$-,pos]while/X/g;$-++}@==<>;($x,$y)=@$_,3-$x>$a?$a=3-$x:0,$x+5-@=>$b?$b=$x+5-@=:0,6-$y>$c?$c=6-$y:0 for@c;@==($",@=)for 1..$a;$_=$"x$c.$_ for@=;map{($x,$y)=@$_;$_&&r$y+$c+$_-1,$x+$a,'-'for-5..5;$_&&r$y+$c-1,$x+$_+$a,'|'for-3..3}@c;print@=,$,=$/
Usage, save above as xmarks.pl
:
perl xmarks.pl <<< 'X'
I'm not sure how much smaller I can make this, but I'm sure I'll come back to it later! I might post an explanation if anyone is interested too.
Handles input of X
and non-square inputs as well now.
CoffeeScript, 345 336 327 bytes
Z=(s,c)->s in'X#'&&'#'||s in'-|+'&&'+'||c
X=(s)->l=u=0;o=(r.split ''for r in s.split '\n');c in'X#'&&(i-x&&(o[y][i]=Z o[y][i],'-';i<l&&l=i)for i in[x-5..x+5];i-y&&((o[i]?=[])[x]=Z o[i][x],'|';i<u&&u=i)for i in[y-3..y+3])for c,x in r for r,y in o;((o[y][x]||' 'for x in[l...o[y].length]).join ''for y in[u...o.length]).join '\n'
X
is the function to call.
Explained:
# get new char. s - old char. c - '|' or '-'
Z=(s,c)->s in'X#'&&'#'||s in'-|+'&&'+'||c
X=(s)->
# leftmost and upmost positions
l=u=0
# split input into 2D array
o=(r.split ''for r in s.split '\n')
# for every 'X' or '#'
c in'X#'&&(
# for positions to left and right
i-x&&(
# draw horisontal line
o[y][i]=Z o[y][i],'-'
# update leftmost position
i<l&&l=i
)for i in[x-5..x+5]
# for positions above and below
i-y&&(
# add row if necessary and draw vertical line
(o[i]?=[])[x]=Z o[i][x],'|'
# update upmost position
i<u&&u=i
)for i in[y-3..y+3]
)for c,x in r for r,y in o
# concatenate into string, replacing empty chars with spaces
((o[y][x]||' 'for x in[l...o[y].length]).join ''for y in[u...o.length]).join '\n'
Executable:
<script src="http://coffeescript.org/extras/coffee-script.js"></script>
<script type="text/coffeescript">
Z=(s,c)->s in'X#'&&'#'||s in'-|+'&&'+'||c
X=(s)->l=u=0;o=(r.split ''for r in s.split '\n');c in'X#'&&(i-x&&(o[y][i]=Z o[y][i],'-';i<l&&l=i)for i in[x-5..x+5];i-y&&((o[i]?=[])[x]=Z o[i][x],'|';i<u&&u=i)for i in[y-3..y+3])for c,x in r for r,y in o;((o[y][x]||' 'for x in[l...o[y].length]).join ''for y in[u...o.length]).join '\n'
################################################################################
# tests follow
s = ['''
mdhyyyyyyyhhhddmmm
mdyyssoo oooosyyyhhhdmm
hsso oossoooooyyhhdhhdmmm
yoooooo oo ssysssyhhdyyyhmmmm
myso oso o oyo hhhdhhyhyhhm mm m
mhsyhhys oss yyyhhhsosyhhmmmmdmmm
mhyhhhy y ssyhoho o shhdmmmmdmmmm
hhyyyh s oo syysyyhhdysso oyhdhhhmmmmm
dhysyys sdysoXoyyyyhhso syshm mmm
hhyhyo o osss y shhyyhd mmmmmm
yyhyyyss o oyyyydmmdmmmmmmmmm mm
ysyhyhhho s osy sdm m mddmmddhydmmm
h oshhhyyyddhoo ooyysshdmdohdmmdmddsshmmm
y oyhhhdhhsyhsssshdddsss hdddyyyhddm
dyyshyyhssyyhyyyyddhhmmdmmmdy syssoosyhdm
hsyyhhhhsoo sooyyhhdoohdhhyhyysoo osdm
doyhhhyyyyhhhysyyy oossyyssso osydm
soyhyyhhhhhhyhyyyooos ohdddm
msoyyyyyyyhyyyyo ooo syyd
ho oyyysooo osso osyd
dhyyysssyyyyyysoosdm
mmdddddmmm
'''
'''
000000000000
000000000000
0000X0000000
0000000X0000
000000000000
000000000000
000000000000
000000000000
000000000000
000000000000
000000000000
000000000000
'''
'''
00000000000000000
00000000000000000
00000000000000000
00000X000X0000000
00000000000000000
00000000000000000
00000000000000000
00000000000000000
00000000000000000
00000000000000000
00000000000000000
00000000000000000
'''
'X'
'XX\nXX'
]
document.write '<pre>'
document.write '\n\n',X x for x in s
</script>