Perl, 647
Dies ist mein erster Versuch, Code-Golf zu spielen, und es ist mir ein bisschen peinlich, dass ich nicht einmal den C # Score geschlagen habe, aber ich dachte, es wäre interessant (oder lustig oder einfach nur masochistisch), das Ganze als zu tun Serie von Regex-Substitutionen. (Ich dachte auch, es würde Spaß machen, mein Perl aufzufrischen, aber am Ende bereute ich zutiefst, es nicht in Ruby oder Python implementiert zu haben.)
Ich habe nicht viel getestet, aber ich denke, es sollte jeden Fall behandeln.
Das Gitter wird über STDIN eingegeben. Die Eingabe muss mindestens eine neue Zeile enthalten (dh eine einzelne Zeile ohne neue Zeile funktioniert nicht).
%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"
Erläuterung: Der Code aktualisiert die Rasterzeichenfolge iterativ, wenn die Laser sie durchlaufen. -stellt einen horizontalen Laser, |einen vertikalen Laser, +gekreuzte Laser, Keinen \Spiegel mit einem Laser, der von der Oberseite abprallt, keinen /Spiegel mit einem Laser, der von der Unterseite abprallt, Zeinen \Spiegel mit einem Laser, der von der Unterseite abprallt, und Weinen /Spiegel mit einem Laser, der von der Unterseite abprallt, dar die Spitze. %ist ein /Spiegel mit Lasern auf beiden Seiten, während Xein \Spiegel mit Lasern auf beiden Seiten ist. (Hierbei wird zwischen Groß - und Kleinschreibung unterschieden. Ich habe versucht, Buchstaben auszuwählen, die angemessen aussehen, z. B. kundKsind etwas offensichtliche Entscheidungen - aber leider ist der Effekt wirklich nicht so hilfreich. Ich sollte diese Informationen wirklich in eine Tabelle aufnehmen, aber ich bin im Moment erschöpft.)
Die gleiche Behandlung von Portalen (dh die Zuweisung eines zusätzlichen Zeichensatzes für jede Ziffer basierend auf den möglichen Eingabe- / Ausgabe-Laserpositionen) würde 144 Zeichen erfordern (einschließlich der ursprünglichen 9). Wenn also ein Laser auf ein "Eingabe" -Portal trifft, Ich füge das "Ausgabe" -Portalzeichen zu der Gruppe von Zeichen hinzu, die einen Laser in die richtige Richtung aussenden. (Dies erfordert eine Unterscheidung zwischen Eingabe- und Ausgabeportalen. Ich habe die Buchstaben qwertyuiodafür verwendet.)
Etwas unerfreulich, mit Print-Anweisungen, damit Sie sehen können, wie die Substitutionen ablaufen (jede Substitution stellt eine "Runde" der Laser-Progression dar), und mit dem gFlag, das zum Main hinzugefügt wurde, s///damit es nicht so viele Iterationen dauert:
# 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"