Beleuchtet einen gespiegelten Raum

13

Tor

In diesem Wettbewerb erhalten Sie einen zufälligen Raum mit einer Kerze im Inneren. Das Ziel ist es, das kürzeste Programm (Golf) zu schreiben, das bestimmt, welche Teile des Raumes von der Kerze beleuchtet werden, indem die dunklen Flecken durch @'s ersetzt werden. Das Programm sollte einen Raum von STDIN einnehmen, wobei die Ausgabe auf STDOUT gedruckt wird.

Beispiel Eingabe / Raum

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

Die Kerze ist mit a bezeichnet C, und die Wände / Spiegel sind mit dargestellt |, -, /, oder \. Die Wände selbst sind Spiegel. Die Ecken des Raumes sind mit einem dargestellt +.

Räume werden niemals diagonale Wände haben und Licht wird niemals aus dem Raum entweichen können.

Außerdem wird das erste Zeichen in einer Zeile immer Teil der Wand außerhalb des Raums sein. Das absolut letzte Zeichen in jeder Zeile ist die gegenüberliegende Wand des Raums. Keine Charaktere zwischen diesen beiden werden außerhalb des Raumes sein.

Licht und Reflexion

Die Kerze sendet acht (laserähnliche) Lichtstrahlen in acht Hauptrichtungen aus: N, S, E, W, NE, SE, SW und NW. Diese Lichtstrahlen werden wie folgt von den Spiegeln reflektiert:

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 steht -für das Licht, das absorbiert wird. Licht wird immer von C oder + absorbiert. Es ist wichtig zu beachten, dass das Licht nur dann von einem Spiegel reflektiert wird, wenn es denselben Raum wie der Spiegel einnimmt. Diese Regeln sind viel einfacher zu verstehen, wenn Sie die Reflexion auf Papier zeichnen.

Beispielausgabe

Als Ausgabe sollte das Programm ein Bild des beleuchteten Raums mit dunklen Flecken als @, leeren hellen Flecken und unbeeinflussten Spiegeln drucken. Für das obige Beispiel wäre die Ausgabe:

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

Dies bedeutet, dass wenn Sie die Lichtstrahlen herausziehen, diese niemals die mit gekennzeichneten Stellen erreichen @.

Mehr Beispiele

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

Input:
+-----+
|  \  |
|/ C \+-+
|       |
|  \ - ++
+------+
Output:
+-----+
|  \ @|
|/ C \+-+
|      @|
| @\ -@++
+------+
PhiNotPi
quelle
Sollte in Ihrem Beispiel nicht auch die linke untere Ecke sein @?
Peter Taylor
1
@ Peter Taylor: Der SW-Strahl trifft diesen Punkt.
Briguy37
3
Trägt einige Ähnlichkeiten mit der sehr gut angenommenen Laser-Herausforderung beim Stapelüberlauf . Genug Gemeinsamkeiten, um die darin verwendeten Methoden interessant zu machen, mit genügend Unterschieden, um sich einige Gedanken darüber zu machen, wie sie angewendet werden könnten.
dmckee --- Ex-Moderator Kätzchen
Könnte mehr Validierungsfälle verwenden.
dmckee --- Ex-Moderator Kätzchen
@ dmckee Ich habe zwei weitere Beispiele hinzugefügt.
PhiNotPi

Antworten:

2

Python, 292 Zeichen

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,

Liest im Raum, macht ihn rechteckig und geht dann in alle Richtungen aus der Kerze heraus. M enthält die aktiven Spiegelzeichen und ihre Wirkung ( /\für die Himmelsrichtungen, |-für die anderen)

Kann Räume mit einer Breite von bis zu 97 Zeichen bearbeiten.

Keith Randall
quelle
2

c - 504

Verlässt sich auf die K & R-Standardfunktionsaufrufsemantik. Sehr unkomplizierte Implementierung, bis auf das Geigenspiel mit den Strahlen.

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

Validierung

$ gcc -g -o candle candle_golfed.c
$ for f in candle_room*; do (./candle < $f) ; done
+------+
|  C   |
|@   @ +--+
| @\      |
+---------+
+------+
|  C   |
|@   @ +--+
|  /@ @ @ |
+---------+
+------+
| @/   |
|@   @ +--+
|  C      |
+---------+
+------+
|  \@ @|
|@   @ +--+
|  C      |
+---------+
+-----+
| @ @ |
|@   @|
|  C  |
|@   @|
| @ @ |
+-----+
dmckee --- Ex-Moderator Kätzchen
quelle