Perl, 647
To jest moja pierwsza próba gry w golfa kodowego i jestem trochę zawstydzona, że nawet nie pobiłam wyniku C #, ale pomyślałam, że byłoby to interesujące (lub zabawne lub po prostu masochistyczne), aby zrobić to wszystko jako seria podstawień wyrażeń regularnych. (Pomyślałem również, że fajnie byłoby odświeżyć mój Perl, ale pod koniec głęboko żałowałem, że nie wdrożyłem go w Ruby ani Python).
Nie przeprowadziłem wielu testów, ale myślę, że powinno poradzić sobie z każdą sprawą.
Siatka jest wprowadzana przez STDIN. Na wejściu musi znajdować się co najmniej jedna nowa linia (tzn. Pojedynczy wiersz bez nowej linii nie będzie działać).
%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"
Objaśnienie: kod iteracyjnie aktualizuje ciąg siatki, gdy lasery przez niego przechodzą. -przedstawia poziomy laser, |pionowy laser, +skrzyżowane laserów Kdo \lustra za pomocą lasera odbijając się od górnej, kjak /lustro za pomocą lasera odbija się od dna, Zna \zwierciadło laserem odbijając się od dołu i Wz /lustra z laserem odbijając szczyt. %jest /lustrem z laserami po obu stronach, podczas gdy Xjest \lustrem z laserami po obu stronach. (Rozróżniana jest wielkość liter. Próbowałem wybrać litery, które wyglądają nieco odpowiednio - na przykład kiKsą dość oczywistymi wyborami - ale niestety efekt naprawdę nie jest taki pomocny. Powinienem naprawdę umieścić te informacje w tabeli, ale jestem teraz wyczerpany).
Obsługa portali w ten sam sposób (tj. Przypisanie każdej cyfrze zestawu dodatkowych znaków na podstawie możliwych pozycji lasera wejściowego / wyjściowego) wymagałaby 144 znaków (w tym oryginalnej 9), więc zamiast tego, gdy laser uderzy w portal „wejściowy”, Dodam znak portalu „wyjściowy” do zestawu znaków, które emitują laser we właściwym kierunku. (Wymaga to rozróżnienia między portalami wejściowymi i wyjściowymi; użyłem qwertyuiodo tego liter .)
Nieco golfa, z drukowanymi instrukcjami, dzięki czemu można zobaczyć, że zachodzą podstawienia (każde zastąpienie reprezentuje jedną „rundę” postępu laserowego), a gflaga jest dodana do głównej, s///aby nie wymagała tylu iteracji:
# 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"