22
\$\begingroup\$

Input:

1
      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    

Output:

      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....

Input:

2
         XX
         XX
         XX
         XX
         XX
     XX  XX
     XX  XX
     XX  XX
     XX  XX

Output:

        .XX
       ..XX
      ...XX
     ....XX
    .....XX
   ..XX..XX
  ...XX..XX
 ....XX..XX
.....XX..XX

Specification:

  • You must take as input
    1. A flag signifying whether the light is coming from the top left or top right. This can be 1 or 2, -1 or 1, 0 or 65536, or whatever is convenient for you, as long as both flags are integers.
    2. Rows composed of either X or , all of the same length in characters (i.e. padded with )
      • All Xs will either be on the last row or have an X under them (meaning no floating buildings)
  • You must output the rows (buildings) with shadows added. This is done with the following procedure:
    • If the light is coming from the top left, draw a right triangle of .s with the same height and width as the height of the building, starting from one space past its right edge and going rightwards.
    • Otherwise, if it's from the top right, do the same thing but start from one space past its left edge and pointing left.
    • Remember, do not alter Xs by changing them to .s; leave them as they are.
    • There will always be "room" for your shadows, i.e. if there's a 3-space tall building at the end there will be at least 3 spaces of padding after it.
  • This is , so the shortest code in bytes will win!
\$\endgroup\$
7
  • 1
    \$\begingroup\$ Can I use {} and {-1*} as flag values? \$\endgroup\$ Commented Apr 20, 2014 at 7:28
  • \$\begingroup\$ @Jan Yes, yes you can. You could even use potato and while(1){}. As quoted in the question, "whatever is convenient." \$\endgroup\$
    – Doorknob
    Commented Apr 20, 2014 at 11:48
  • 2
    \$\begingroup\$ :( I was going to solve this in (.NET-flavoured) regex, but I think I found a bug in Regex.Replace which I can't work around... do I have two problems now? \$\endgroup\$ Commented Apr 20, 2014 at 12:18
  • 3
    \$\begingroup\$ @Doorknob Someone is going to abuse this rule to just have their entire code in the input. \$\endgroup\$ Commented Apr 20, 2014 at 14:04
  • 2
    \$\begingroup\$ @Synthetica That is one of the "standard loopholes." \$\endgroup\$
    – Doorknob
    Commented Apr 20, 2014 at 14:06

5 Answers 5

11
\$\begingroup\$

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.

\$\endgroup\$
6
\$\begingroup\$

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....
\$\endgroup\$
4
\$\begingroup\$

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. ^^'

\$\endgroup\$
3
\$\begingroup\$

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

\$\endgroup\$
5
  • \$\begingroup\$ Fine, I fixed the rules. :-P \$\endgroup\$
    – Doorknob
    Commented Apr 20, 2014 at 21:45
  • \$\begingroup\$ Aaww, that's no fun :-( This does make "both flags are integers" conflict with your comment "You could even use potato...", unless potato is an integer. :-P \$\endgroup\$
    – Zaq
    Commented Apr 20, 2014 at 21:51
  • \$\begingroup\$ c=+prompt() or else b+c will concatenate as a string. \$\endgroup\$
    – nderscore
    Commented Apr 21, 2014 at 2:05
  • \$\begingroup\$ Optimized a few things and got this down to 119: for(c=p=+(P=prompt)(d='.');l=P();)console.log(p=l.replace(/ /g,function(a,b){return p[b]==d|p[b+=c]==d|l[b]=='X'?d:a})) (demo) \$\endgroup\$
    – nderscore
    Commented Apr 21, 2014 at 2:24
  • \$\begingroup\$ Save another byte on converting c to a number by subtracting instead. b-c or b-=c in my code above. (demo) \$\endgroup\$
    – nderscore
    Commented Apr 21, 2014 at 2:40
1
\$\begingroup\$

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]))
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.