Perl, 647
C'est ma première tentative de code-golf, et je suis un peu gêné de ne pas avoir battu le score C #, mais j'ai pensé qu'il serait intéressant (ou amusant, ou simplement masochiste) de faire le tout en tant que série de substitutions d'expression régulière. (J'ai aussi pensé que ce serait amusant de rafraîchir mon Perl, mais à la fin, je regrettais profondément de ne pas l'avoir implémenté en Ruby ou Python.)
Je n'ai pas fait beaucoup de tests, mais je pense qu'il devrait gérer tous les cas.
La grille est entrée via STDIN. Il doit y avoir au moins une nouvelle ligne dans l'entrée (c'est-à-dire qu'une seule ligne sans nouvelle ligne ne fonctionnera pas).
%s=(d,'[|+#$vk%ZX]',u,'[|+#$^W%KX]',r,'[-G+#>k%KX]',l,'[-G+#<W%ZX]');%o=(d,'[-.*G/k\\\\Z',u,'[-.*G/W\\\\K',r,'[|.*$\\\\/kK',l,'[|.*$\\\\/ZW');for$d(d,u,r,l){$o{$d}.='123456789qwertyuio]'}%u=(d,'.|-+*$G#/Wk%\KZX',u,'.|-+*$G#/kW%\ZKX',r,'.-|+*G$#/Wk%\ZKX',l,'.-|+*G$#/kW%\KZX');@q=split//,"qwertyuio";local$/;$_=<STDIN>;for$i(1..9){$m{$i}=$q[$i-1];$m{$m{$i}}=$i;s/$i/$m{$i}/e}/.*?\n/;$l='.'x((length$&)-1);do{$c=0;for$d(d,u,r,l){%p=(d,"(?<=$s{d}$l)$o{d}",u,"$o{u}(?=$l$s{u})",r,"(?<=$s{r})$o{r}",l,"$o{l}(?=$s{l})");%h=split//,$u{$d};$c+=s!$p{$d}!$h{$&}||($v=$&,($o{$d}=~s/$v// && $s{$d}=~s/]/$m{$v}]/),$v)!es}}while($c);print/\*/?"False\n":"True\n"
Explication: le code met à jour de manière itérative la chaîne de grille lorsque les lasers la traversent. -représente un laser horizontal, |un laser vertical, des +lasers croisés,K un \miroir avec un laser rebondissant sur le dessus, kun /miroir avec un laser rebondissant sur le fond, Zun \miroir avec un laser rebondissant sur le bas et Wun /miroir avec un laser rebondissant sur le dessus haut. %est un /miroir avec des lasers des deux côtés, tandis Xqu'un \miroir avec des lasers des deux côtés. (Ils sont sensibles à la casse. J'ai essayé de choisir des lettres qui semblent quelque peu appropriées - par exemple, ketKsont des choix quelque peu évidents - mais malheureusement l'effet n'est vraiment pas très utile. Je devrais vraiment mettre ces informations dans un tableau, mais je suis épuisé en ce moment.)
La gestion des portails de la même manière (c.-à-d. En affectant à chaque chiffre un ensemble de caractères supplémentaires en fonction des positions laser d'entrée / sortie possibles) nécessiterait 144 caractères (y compris le 9 d'origine), donc à la place, lorsqu'un laser frappe un portail "d'entrée", J'ajoute le caractère de portail "de sortie" à l'ensemble de caractères qui émettent un laser dans la bonne direction. (Cela nécessite une distinction entre les portails d'entrée et de sortie; j'ai utilisé les lettres qwertyuiopour cela.)
Un peu sans golf, avec des déclarations imprimées pour que vous puissiez voir les substitutions se produire (chaque substitution représente un "round" de progression laser), et avec le g drapeau ajouté à la principale s///afin qu'il ne prenne pas autant d'itérations:
# Throughout, d,u,r,l represents lasers going down, up, left, or right
# `sources` are the character classes representing laser "sources" (i.e. any
# character that can, on the next round, cause a laser to enter the space
# immediately adjacent to it in the proper direction)
%sources=(d,'[|+#$vk%ZX]',u,'[|+#$^W%KX]',r,'[-G+#>k%KX]',l,'[-G+#<W%ZX]');
# `open` characters will not block a laser
%open=(d,'[-.*G/k\\\\Z',u,'[-.*G/W\\\\K',r,'[|.*$\\\\/kK',l,'[|.*$\\\\/ZW');
# One of each portal is changed into the corresponding letter in `qwertyuio`.
# At the start, each portal is 'open' and none of them is a source.
for$d(d,u,r,l){$open{$d}.='123456789qwertyuio]'}
# A mapping of 'open' characters to the characters they become when a laser
# goes through them. (This is used like a hash of hashes; see the assignment
# of `%h` below.)
%update=(d,'.|-+*$G#/Wk%\KZX',
u,'.|-+*$G#/kW%\ZKX',
r,'.-|+*G$#/Wk%\ZKX',
l,'.-|+*G$#/kW%\KZX');
@q=split//,"qwertyuio";
local$/;$_=<STDIN>;
for$i(1..9){
$m{$i}=$q[$i-1];
$m{$m{$i}}=$i;
s/$i/$m{$i}/e}
print "After substituting portals:\n";
print;
print "\n";
# Find the number of characters in each line and create a string of `.`'s,
# which will be used to correlate characters above/below one another in the
# grid with each other.
/.*?\n/;
$l='.'x((length$&)-1);
do{
$changes=0;
for$d(d,u,r,l){
# `patterns` is a mapping from each direction to the regex representing
# an update that must occur (i.e. a place where a laser must progress).
# Each pattern is either a lookahead or lookbehind plus the necessary
# "open" character class.
%patterns=(d,"(?<=$sources{d}$l)$open{d}",
u,"$open{u}(?=$l$sources{u})",
r,"(?<=$sources{r})$open{r}",
l,"$open{l}(?=$sources{l})");
%h=split//,$update{$d};
# Match against the pattern for each direction. Note whether any
# matches were found.
$changes+=s!$patterns{$d}!
# If the "open" character for a map is in the `update` map, return
# the corresponding value. Otherwise, the "open" character is a
# portal.
$h{$&} || ($v=$&,
# For portals, remove the input portal from the
# proper "open" list and add the output portal to
# the proper "source" list.
($open{$d}=~s/$v// && $sources{$d}=~s/]/$m{$v}]/),
$v)
# This whole substitution should allow `.` to match
# newlines (see the definition of `$l` above), and the
# replacement must be an expression rather than a string
# to facilitate the portal logic. The `g` allows multiple
# updates per "frame"; it is left out of the golfed code.
!egs
}
# Print the next "frame".
print;
print "\n";
# Continue updating until no "open" spaces are found.
}while($changes);
# Print whether `*` is still present in the input.
print/\*/?"False\n":"True\n"