Oświetl lustrzany pokój

13

Cel

W tym konkursie dostajesz losowy pokój z jedną świecą w środku. Celem jest napisanie najkrótszego programu (to jest golf), który określa, które części pokoju są oświetlone przez świecę, zastępując ciemne punkty znakami @„”. Program powinien zająć miejsce ze STDIN, a wydruk powinien być wydrukowany do STDOUT.

Przykładowe wejście / pokój

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

Świeca jest przedstawiony z Ci ściany / lusterka są reprezentowane |, -, /lub \. Same ściany są zwierciadłami. Narożniki pokoju są oznaczone symbolem +.

Pokoje nigdy nie będą miały ukośnych ścian, a światło nigdy nie będzie w stanie wydostać się z pokoju.

Ponadto pierwszy znak w linii zawsze będzie częścią ściany poza pokojem. Absolutnym ostatnim znakiem w każdej linii będzie przeciwna ściana pokoju. Żadne postacie między tymi dwoma nie będą poza pokojem.

Światło i odbicie

Świeca emituje osiem (laserowych) wiązek światła w ośmiu podstawowych kierunkach: N, S, E, W, NE, SE, SW i NW. Te promienie światła odbijają się od luster, jak opisano poniżej:

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 -oznacza pochłaniane światło. Światło jest zawsze absorbowane przez litery C lub +. Należy zauważyć, że światła odbijają się od lustra tylko wtedy, gdy zajmuje to samo miejsce co lustro. Reguły te są znacznie łatwiejsze do zrozumienia, gdy narysujesz odbicie na papierze.

Przykładowy wynik

Jako wynik program powinien wydrukować obraz oświetlonego pokoju, z ciemnymi plamami zapisanymi jako @, jasnymi plamami pozostawionymi pustymi i bez zmian lusterek. W powyższym przykładzie wynikiem byłoby:

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

Oznacza to, że jeśli wyciągniesz wiązki światła, nigdy nie dotrą one do oznaczonych miejsc @.

Więcej przykładów

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

Input:
+-----+
|  \  |
|/ C \+-+
|       |
|  \ - ++
+------+
Output:
+-----+
|  \ @|
|/ C \+-+
|      @|
| @\ -@++
+------+
PhiNotPi
źródło
Czy w twoim przykładzie lewy dolny róg nie powinien @też być ?
Peter Taylor
1
@Peter Taylor: Promień SW uderza w to miejsce.
Briguy37
3
Ma pewne podobieństwa do bardzo dobrze przyjętego wyzwania dotyczącego laserów w przepełnieniu stosu . Wystarczająco dużo podobieństw, aby zastosowane w nich metody były interesujące, z wystarczającymi różnicami, które wymagałyby poważnego przemyślenia, jak można je zastosować.
dmckee --- były moderator kotek
Przydałoby się więcej przypadków sprawdzania poprawności.
dmckee --- były moderator kociąt
@dmckee Dodałem jeszcze dwa przykłady.
PhiNotPi,

Odpowiedzi:

2

Python, 292 znaków

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,

Czyta w pokoju, robi prostokąt, a następnie wychodzi ze świecy we wszystkich kierunkach. M zawiera aktywne znaki lustrzane i ich efekt ( /\dla kierunków głównych, |-dla pozostałych)

Może obsługiwać pokoje o szerokości do 97 znaków.

Keith Randall
źródło
2

c - 504

Opiera się na domyślnej funkcji K&R wywołującej semantykę. Bardzo prosta implementacja, z wyjątkiem skrzypiec z odbijaniem promieni.

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

Nie golfił

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

Uprawomocnienie

$ gcc -g -o candle candle_golfed.c
$ for f in candle_room*; do (./candle < $f) ; done
+------+
|  C   |
|@   @ +--+
| @\      |
+---------+
+------+
|  C   |
|@   @ +--+
|  /@ @ @ |
+---------+
+------+
| @/   |
|@   @ +--+
|  C      |
+---------+
+------+
|  \@ @|
|@   @ +--+
|  C      |
+---------+
+-----+
| @ @ |
|@   @|
|  C  |
|@   @|
| @ @ |
+-----+
dmckee --- były kot moderator
źródło