Illuminate a Mirrored Room
Python, 292 chars
import sys
R=''
for x in sys.stdin:R+='%-97s\n'%x[:-1].replace(' ','@')
M={'/':'-98/d','\\':'98/d'}
for d in(-98,-1,1,98,99,97,-97,-99):
if d>98:M={'|':'d^2','-':'-d^2'}
p=R.find('C')
while 1:
p+=d
if R[p]in' @':R=R[:p]+' '+R[p+1:]
elif R[p]in M:d=eval(M[R[p]])
else:break
print R,
Reads in the room, makes it rectangular, then walks out from the candle in all directions. M contains the active mirror characters and their effect (/\
for the cardinal directions, |-
for the others)
Can handle rooms up to 97 characters wide.
c -- 504
Relies on K&R default function calling semantics. Very straight forward implementation except for the fiddle stuff with bouncing the rays.
#define N M[x+y*97]
#define Y abs(y)
#define O M[c]==
#define E else break;
int j[]={-98,-97,-96,-1,1,96,97,98},c,x,y,p,s,M[9409];main(){for(;
(c=getchar())!=-1;){if(c==10)x=0,++y;else{if(c==67)p=x+y*97;if(c==32)
c=64;N=c;++x;}}for(x=0;x<8;++x){y=j[x];c=p;do{c+=y;if(O'@')M[c]=32;s=y/Y;
if(O 92)if(y%2){y=s*(98-Y);}E if(O'/')if(y%2){y=s*-(98-Y);}E if(O'|')
if(~y%2){y=s*(97+(97-Y));}E if(O'-')if(~y%2){y=s*-(97+(97-Y));}E}while
(!(O'+')&&!(O'C'));}for(y=0;x=0,N!=0;++y){for(;N!=0;++x)putchar(N);
putchar(10);}}
Ungolfed
//#include <stdio.h>
int j[]={ -98, -97, -96, /* Increments to move around the array */
-1, 1,
96, 97, 98},
c, x, y, p, s, /* take advantage of static initialization to zero */
M[9409]; /* treat as 97*97 */
main(){
/* read the map */
while((c=getchar())!=-1/*Assume the deffinition of EOF*/){
/* putchar(c); */
if (c=='\n')
x=0,++y;
else {
if (c=='C') p=x+y*97; /* set start position */
if (c==' ') c='@'; /* The room starts dark */
M[x+y*97]=c; ++x;
}
}
/* printf("Start position is %d (%d, %d)\n",p,p%97,p/97); */
/* Now loop through all the direction clearing '@' cells as we
* encounter them
*/
for(x=0;x<8;++x){
y=j[x];c=p; /* y the increment, c the position */
/* printf("\tposition %d (%d, %d) '%c'\n",c,c%97,c/97,M[c]); */
/* printf("\tdirection = %d (%d, %d)\n",y,-(abs(y)-97),(y+98)/97-1); */
do {
c+=y;
/* printf("\t\tposition %d (%d, %d) '%c'\n",c,c%97,c/97,M[c]); */
/* We ought to do bounds checking here, but we rely on *
* the guarantee that the room will be bounded instead. */
if(M[c]=='@') M[c]=' ';
/* The reflections are handles
* + Stop or not stop based on the even/oddness of the increment
* + New direction is a little fiddly, look for yourself
*/
s=y/abs(y); /* sign of y (need for some reflections) */
if (M[c]=='\\') if (y%2){ y=s* (98-abs(y)); }else break;
if (M[c]=='/') if (y%2){ y=s*-(98-abs(y)); }else break;
if (M[c]=='|') if (~y%2){y=s* (97+(97-abs(y)));}else break;
if (M[c]=='-') if (~y%2){y=s*-(97+(97-abs(y)));}else break;
/* printf("\t\t\tdirection = %d (%d, %d)\n",y,97-abs(y),(y+98)/97-1); */
} while (!(M[c]=='+')&&!(M[c]=='C'));
/* printf("\t...hit a %c. Done\n",M[c]); */
}
/* print the result */
for(y=0;x=0,M[x+y*97]!=0;++y){
for(;M[x+y*97]!=0;++x)
putchar(M[x+y*97]);
putchar('\n');
}
}
Validation
$ gcc -g -o candle candle_golfed.c
$ for f in candle_room*; do (./candle < $f) ; done
+------+
| C |
|@ @ +--+
| @\ |
+---------+
+------+
| C |
|@ @ +--+
| /@ @ @ |
+---------+
+------+
| @/ |
|@ @ +--+
| C |
+---------+
+------+
| \@ @|
|@ @ +--+
| C |
+---------+
+-----+
| @ @ |
|@ @|
| C |
|@ @|
| @ @ |
+-----+