| Bytes | Lang | Time | Link |
|---|---|---|---|
| 076 | Dyalog APL | 250826T223618Z | Aaron |
| 267 | Haskell | 250826T025334Z | Hayden B |
| 277 | Python3 | 250822T215802Z | Ajax1234 |
| 229 | Python 2.7 | 140421T071006Z | Abhijit |
| 014 | JavaScript | 140420T212703Z | Zaq |
| 233 | Python 3 | 140420T090829Z | cjfaure |
| 085 | Perl | 140420T074635Z | mniip |
| 067 | GolfScript | 140420T095826Z | Howard |
Dyalog APL, 76 bytes
Takes the building matrix on the right and on the left 0 for shadows casted to the right, and 1 for shadows casted to the left.
{(⊂' .X')⌷⍨¨1+(2×o)⌈⊃∨/⍺{(1+⍣⍺-2⊃⍵)⌽(1-⊃⍵)⊖⌽⍣⍺⊢s↑∘.≥⍨⍳1+⊃s-⍵}¨⍸o←'X'=⍵⊣s←⍴⍵}
⊣s←⍴⍵ # Save the shape of the input in (s)hape for later
o←'X'=⍵ # Find where the input is an `X` and save in (o)riginal
⍸ # Get the coordinates of those locations where an `X` was
⍺{ }¨ # Apply to each, passing along the outer function's left arg to this inner function
1+⊃s-⍵ # Get the first (y-axis) element of the difference from this coordinate and the shape and add one
∘.≥⍨⍳ # Get the greater-than outer-product of the indices of that number -- this makes a triangle of 1's in a matrix
s↑ # Take from this triangle as much as the original (s)hape to extend this matrix to the original size
⌽⍣⍺⊢ # Optionally flip this matrix around depending on if the left arg is 0 or 1
(1-⊃⍵)⊖ # Rotate vertically backwards by this y-coordinate to move to the right height
(1+⍣⍺-2⊃⍵)⌽ # and rotate horizontally backwards by this x-coordinate to move to the right distance, optionally adjusting by 1 depending on the left arg
⊃∨/ # Or-over to combine all the shadows
⌈ # Get the max between that
(2×o) # and twice the (o)riginal so that buildings cover shadows
1+ # Add 1 for indexing's sake
(⊂' .X')⌷⍨¨ # Then select those indices from the magic string
💎
Created with the help of Luminespire.
Haskell, 267 bytes
x#y=unlines$map a$g$map a$lines y where a|x<0=reverse|1>0=id
g y=y!replicate(length $ head y)0
[]!_=[]
(y:z)!s=fst r:z!snd r where r=unzip$h y s 0
h[]_ _=[(' ',0)]
h(b:c)(s:t)i|b=='X'=(b,s+1):h c t z|i>0=('.',0):h c t(i-1)|1>0=(' ',0):h c t 0where z|s+2>i=s+1|1>0=i-1
Where (#) is the solution.
I'm not exactly that experienced in Haskell, so I'm not used to using the ever-so-useful list operations (I began to define my own version of unzip until I remembered it exists). Anyway, I'd be very glad to see if anyone can help golf this further.
Python3, 277 bytes
E=enumerate
def f(b,V):
B=[*zip(*(b:=[[i[::-1],i][V]for i in b]))]
for x,_ in E(b):
for y,_ in E(b[0]):b[x][y]='.'if[i for i,a in E(B[:y+1])if'X'==a[-1]and(C:=a.count('X'))>=len(B[0])-x and C-len(B[0])+x>=y-i-1]and b[x][y]!='X'else b[x][y]
return[[i[::-1],i][V]for i in b]
Python 2.7 - 229
p,s,M,J,L=input(),__import__('sys').stdin.readlines(),map,''.join,len
n,s,r,f=L(s),M(str.strip,M(J,zip(*s[::-1]))),0,[]
for l in s[::p]:f,r=f+[(l+'.'*(r-L(l))+' '*n)[:n]],max(r-1,L(l))
print'\n'.join(M(J,zip(*f[::p])[::-1]))
Ungolfed Version
def shadow(st, pos):
_len = len(st)
st = map(str.strip, map(''.join,zip(*st[::-1])))
prev = 0
res = []
for line in st[::[1,-1][pos-1]]:
res +=[(line+'.'*(prev-len(line)) + ' '*_len)[:_len]]
prev = max(prev - 1, len(line))
return '\n'.join(map(''.join,zip(*res[::[1,-1][pos-1]])[::-1]))
JavaScript - 14
eval(prompt())
The flag on the first line is for(p='';l=prompt();)console.log(p=l.replace(/ /g,function(a,b){return p[b+1]=='.'||p[b]=='.'||l[b+1]=='X'?'.':a})); for shadows facing the left or for(p='';l=prompt();)console.log(p=l.replace(/ /g,function(a,b){return p[b-1]=='.'||p[b]=='.'||l[b-1]=='X'?'.':a})); for shadows to the right.
This might abuse the "whatever is convenient for you" rule for the flag :P
Edit: without abuse (127):
c=prompt();for(p='';l=prompt();)console.log(p=l.replace(/ /g,function(a,b){return p[b+c]=='.'||p[b]=='.'||l[b+c]=='X'?'.':a}));
The flag for this is 1 or -1
Python 3 - 233
Well, that turned out longer than expected...
1 for shadows going right, -1 for shadows going left.
d,x=int(input()),[1]
while x[-1]:x+=[input()]
x,o,l,h=list(zip(*x[1:-1]))[::d],[],0,len(x)-1
for i in x:o+=[''.join(i[:len(i)-l])+''.join(i[len(i)-l:]).replace(' ','.')];l=max(l-1,i.count('X'))
for i in zip(*o[::d]):print(''.join(i))
EDIT: Didn't see the either side padding in the rules. Ehehe. ^^'
Perl - 85
BEGIN{$d=-<>}$d?s/X /X./g:s/ X/.X/g;s/ /substr($p,$+[0]+$d,1)eq'.'?'.':$&/ge;$p=$_;
EDIT: I totally forgot about the -p flag this needs to be run with. Added 2 to char count.
The flag specified at the first line is 0 for shadows going left and 2 for shadows going right.
GolfScript, 67 characters
n%(~:S\zip\%.0=\{.' '3$);+{{\(@[\].~<=}%+}:M~'X'/'.'*@@M}%S%zip\;n*
1/-1 for shadows going right/left. Run the example online:
X.
X..
X...
X.... XX. XXXXXX. X.X.X.
X..... XX.. XXXXXX.. X.X.X..
XXX. X......XX... XXXXXX... X.X.X...
XXX.. X......XX....XXXXXX.... X.X.X....