Illumina una stanza specchiata


13

Obbiettivo

In questa competizione, ti viene data una stanza a caso con dentro una candela. L'obiettivo è scrivere il programma più breve (questo è il golf) che determina quali parti della stanza sono illuminate dalla candela, sostituendo le macchie scure con quelle @di. Il programma dovrebbe prendere una stanza da STDIN, con l'output stampato su STDOUT.

Esempio di input / room

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

La candela è rappresentato con un C, e le pareti / specchi sono rappresentati con |, -, /o \. Le pareti stesse sono specchi. Gli angoli della stanza sono rappresentati con a +.

Le stanze non avranno mai pareti diagonali e la luce non potrà mai uscire dalla stanza.

Inoltre, il primo personaggio su una linea sarà sempre parte del muro fuori dalla stanza. L'ultimo carattere assoluto su ogni riga sarà la parete opposta della stanza. Nessun personaggio tra questi due sarà fuori dalla stanza.

Luce e riflessione

La candela emette otto fasci di luce (simili a laser) in otto direzioni di base: N, S, E, W, NE, SE, SW e NW. Questi raggi di luce rimbalzano sugli specchi come descritto di seguito:

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 -rappresenta la luce che viene assorbita. La luce viene sempre assorbita da C o +. È importante notare che le luci si riflettono su uno specchio solo quando occupa lo stesso spazio dello specchio. Queste regole sono molto più facili da capire quando si disegna il riflesso sulla carta.

Esempio di output

Come output, il programma dovrebbe stampare un'immagine della stanza illuminata, con punti scuri scritti come una @, punti luce lasciati vuoti e specchi non interessati. Per l'esempio sopra, l'output sarebbe:

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

Ciò significa che, se hai estratto i raggi di luce, questi non raggiungeranno mai gli spazi contrassegnati da @.

Più esempi

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

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

Nel tuo esempio, non dovrebbe essere anche l'angolo in basso a sinistra @?
Peter Taylor,

1
@Peter Taylor: il raggio SW colpisce quel punto.
Briguy37,

3
Presenta alcune somiglianze con la ben accolta sfida dei laser su Stack Overflow . Abbastanza somiglianze per rendere interessanti i metodi ivi utilizzati con abbastanza differenze da richiedere un considerevole pensiero su come potrebbero essere applicati.
dmckee --- ex gattino moderatore

Potrebbe usare più casi di validazione.
dmckee --- ex gattino moderatore

@dmckee Ho aggiunto altri due esempi.
PhiNotPi

Risposte:


2

Python, 292 caratteri

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,

Legge nella stanza, la rende rettangolare, quindi esce dalla candela in tutte le direzioni. M contiene i personaggi specchio attivi e il loro effetto ( /\per le direzioni cardinali, |-per gli altri)

Può gestire stanze con una larghezza massima di 97 caratteri.


2

c - 504

Si affida alla funzione predefinita di K&R che chiama la semantica. Implementazione molto diretta, tranne per le cose violino con il rimbalzo dei raggi.

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

Validazione

$ gcc -g -o candle candle_golfed.c
$ for f in candle_room*; do (./candle < $f) ; done
+------+
|  C   |
|@   @ +--+
| @\      |
+---------+
+------+
|  C   |
|@   @ +--+
|  /@ @ @ |
+---------+
+------+
| @/   |
|@   @ +--+
|  C      |
+---------+
+------+
|  \@ @|
|@   @ +--+
|  C      |
+---------+
+-----+
| @ @ |
|@   @|
|  C  |
|@   @|
| @ @ |
+-----+
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.