Ilumina una habitación con espejo

13

Objetivo

En esta competencia, se te da una habitación aleatoria con una vela adentro. El objetivo es escribir el programa más corto (esto es golf) que determina qué partes de la habitación se iluminan con la vela, reemplazando los puntos oscuros con @'s'. El programa debe tomar una habitación de STDIN, con la salida impresa en STDOUT.

Ejemplo de entrada / sala

+------+
|  C   |
|      +--+
|  \      |
+---------+

La vela se representa con una C, y las paredes / espejos están representados con |, -, /, o \. Las paredes mismas son espejos. Las esquinas de la sala están representadas con a +.

Las habitaciones nunca tendrán paredes diagonales, y la luz nunca podrá escapar de la habitación.

Además, el primer personaje en una línea siempre será parte de la pared de la habitación. El último carácter absoluto en cada línea será la pared opuesta de la habitación. Ningún personaje entre estos dos va a estar fuera de la habitación.

Luz y reflejo

La vela emite ocho haces de luz (tipo láser) en ocho direcciones básicas: N, S, E, W, NE, SE, SW y NW. Estos rayos de luz rebotan en los espejos como se describe a continuación:

Old Direction of Travel | Mirror | New Direction
N S E W NE SE SW NW       /        E W N S -- -- -- --
N S E W NE SE SW NW       \        W E S N -- -- -- --
N S E W NE SE SW NW       |        - - - - NW SW NE SW
N S E W NE SE SW NW       -        - - - - SE NE SW NE

A -representa la luz que se absorbe. La luz siempre es absorbida por C's o + 's. Es importante tener en cuenta que las luces se reflejan en un espejo solo cuando ocupa el mismo espacio que el espejo. Estas reglas son mucho más fáciles de entender cuando dibujas el reflejo en papel.

Salida de ejemplo

Como resultado, el programa debe imprimir una imagen de la habitación iluminada, con los puntos oscuros escritos como @, puntos claros en blanco y los espejos no afectados. Para el ejemplo anterior, la salida sería:

+------+
|  C   |
|@   @ +--+
| @\      |
+---------+

Esto significa que, si dibujas los rayos de luz, nunca alcanzarán los espacios marcados con @.

Más ejemplos

Input:
+-----+
|     |
|     |
|  C  |
|     |
|     |
+-----+
Output:
+-----+
| @ @ |
|@   @|
|  C  |
|@   @|
| @ @ |
+-----+

Input:
+-----+
|  \  |
|/ C \+-+
|       |
|  \ - ++
+------+
Output:
+-----+
|  \ @|
|/ C \+-+
|      @|
| @\ -@++
+------+
PhiNotPi
fuente
En su ejemplo, ¿no debería ser la esquina inferior izquierda @también?
Peter Taylor
1
@Peter Taylor: el haz SW llega a ese punto.
Briguy37
3
Tiene algunas similitudes con el muy bien recibido desafío Lasers en Stack Overflow . Suficientes similitudes para hacer que los métodos utilizados sean interesantes con suficientes diferencias para requerir una reflexión considerable sobre cómo podrían aplicarse.
dmckee --- ex-gatito moderador
Podría usar más casos de validación.
dmckee --- ex gatito moderador
@dmckee agregué dos ejemplos más.
PhiNotPi

Respuestas:

2

Python, 292 caracteres

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,

Lee en la habitación, la hace rectangular, luego sale de la vela en todas las direcciones. M contiene los caracteres espejo activos y su efecto ( /\para las direcciones cardinales, |-para los demás)

Puede manejar salas de hasta 97 caracteres de ancho.

Keith Randall
fuente
2

c - 504

Se basa en la función predeterminada de K&R que llama semántica. Implementación muy sencilla, excepto por el violín que hace rebotar los rayos.

#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);}}

Sin golf

//#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');
  }
}

Validación

$ gcc -g -o candle candle_golfed.c
$ for f in candle_room*; do (./candle < $f) ; done
+------+
|  C   |
|@   @ +--+
| @\      |
+---------+
+------+
|  C   |
|@   @ +--+
|  /@ @ @ |
+---------+
+------+
| @/   |
|@   @ +--+
|  C      |
+---------+
+------+
|  \@ @|
|@   @ +--+
|  C      |
+---------+
+-----+
| @ @ |
|@   @|
|  C  |
|@   @|
| @ @ |
+-----+
dmckee --- gatito ex moderador
fuente