Illuminez une pièce en miroir

13

Objectif

Dans ce concours, vous obtenez une chambre au hasard avec une bougie à l'intérieur. Le but est d'écrire le programme le plus court (c'est le golf) qui détermine quelles parties de la pièce sont illuminées par la bougie, en remplaçant les taches sombres par @des. Le programme devrait prendre une pièce de STDIN, avec la sortie imprimée sur STDOUT.

Exemple d'entrée / pièce

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

La bougie est représentée par une C, et les murs / miroirs sont représentés avec |, -, /ou \. Les murs eux-mêmes sont des miroirs. Les coins de la pièce sont représentés par un +.

Les pièces n'auront jamais de murs en diagonale et la lumière ne pourra jamais s'échapper de la pièce.

De plus, le premier personnage d'une ligne fera toujours partie du mur de la pièce. Le dernier caractère absolu sur chaque ligne sera le mur opposé de la pièce. Aucun personnage entre ces deux ne sera à l'extérieur de la pièce.

Lumière et réflexion

La bougie émet huit faisceaux de lumière (de type laser) dans huit directions de base: N, S, E, W, NE, SE, SW et NW. Ces rayons de lumière rebondissent sur les miroirs comme décrit ci-dessous:

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 -représente la lumière absorbée. La lumière est toujours absorbée par les C ou les +. Il est important de noter que les lumières ne se réfléchissent sur un miroir que lorsqu'il occupe le même espace que le miroir. Ces règles sont beaucoup plus faciles à comprendre lorsque vous dessinez la réflexion sur papier.

Exemple de sortie

En sortie, le programme doit imprimer une image de la pièce éclairée, avec des taches sombres écrites en tant que @, des taches claires laissées vides et des miroirs non affectés. Pour l'exemple ci-dessus, la sortie serait:

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

Cela signifie que si vous retirez les faisceaux de lumière, ils n'atteindront jamais les espaces marqués @.

Plus d'exemples

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

Input:
+-----+
|  \  |
|/ C \+-+
|       |
|  \ - ++
+------+
Output:
+-----+
|  \ @|
|/ C \+-+
|      @|
| @\ -@++
+------+
PhiNotPi
la source
Dans votre exemple, le coin inférieur gauche ne devrait-il pas l'être @également?
Peter Taylor
1
@Peter Taylor: Le faisceau SW frappe cet endroit.
Briguy37
3
Porte quelques similitudes avec le défi très bien reçu des lasers sur Stack Overflow . Assez de similitudes pour rendre les méthodes utilisées intéressantes avec suffisamment de différences pour exiger une réflexion approfondie sur la façon dont elles pourraient être appliquées.
dmckee --- chaton ex-modérateur
Pourrait utiliser plus de cas de validation.
dmckee --- chaton ex-modérateur
@dmckee J'ai ajouté deux autres exemples.
PhiNotPi

Réponses:

2

Python, 292 caractères

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,

Lit dans la pièce, la rend rectangulaire, puis sort de la bougie dans toutes les directions. M contient les caractères miroirs actifs et leur effet ( /\pour les directions cardinales, |-pour les autres)

Peut gérer des pièces jusqu'à 97 caractères de large.

Keith Randall
la source
2

c - 504

Repose sur la fonction par défaut de K&R appelant la sémantique. Mise en œuvre très simple, sauf pour le violon avec rebondir les rayons.

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

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

Validation

$ gcc -g -o candle candle_golfed.c
$ for f in candle_room*; do (./candle < $f) ; done
+------+
|  C   |
|@   @ +--+
| @\      |
+---------+
+------+
|  C   |
|@   @ +--+
|  /@ @ @ |
+---------+
+------+
| @/   |
|@   @ +--+
|  C      |
+---------+
+------+
|  \@ @|
|@   @ +--+
|  C      |
+---------+
+-----+
| @ @ |
|@   @|
|  C  |
|@   @|
| @ @ |
+-----+
dmckee --- chaton ex-modérateur
la source