Perl, 647
Questo è il mio primo tentativo in assoluto di code-golf, e sono un po 'imbarazzato di non aver nemmeno battuto il punteggio C #, ma ho pensato che sarebbe stato interessante (o divertente o semplicemente masochista) fare l'intera cosa come un serie di sostituzioni regex. (Ho anche pensato che sarebbe stato divertente ripassare il mio Perl, ma alla fine mi sono pentito profondamente di non averlo implementato in Ruby o Python.)
Non ho fatto molti test, ma penso che dovrebbe gestire tutti i casi.
La griglia viene immessa tramite STDIN. Ci deve essere almeno una nuova riga nell'input (cioè una singola riga senza una nuova riga non funzionerà).
%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"
Spiegazione: il codice aggiorna iterativamente la stringa della griglia mentre i laser la attraversano. -rappresenta un laser orizzontale, |un laser verticale, +laser incrociati, Kuno \specchio con un laser che rimbalza sulla parte superiore, kuno /specchio con un laser che rimbalza sul fondo, Zuno \specchio con un laser che rimbalza sul fondo e Wuno /specchio con un laser che rimbalza la cima. %è uno /specchio con laser su entrambi i lati, mentre Xè uno \specchio con laser su entrambi i lati. (Questi sono case sensitive. Ho provato a scegliere lettere che sembrano un po 'appropriate - per esempio, keKsono scelte piuttosto ovvie, ma purtroppo l'effetto non è poi così utile. Dovrei davvero mettere queste informazioni in un tavolo, ma sono sfinito in questo momento.)
Gestire i portali nello stesso modo (cioè assegnare ad ogni cifra un set di caratteri extra in base alle possibili posizioni laser di input / output) richiederebbe 144 caratteri (incluso l'originale 9), quindi, invece, quando un laser colpisce un portale "input", Aggiungo il carattere del portale "output" all'insieme di caratteri che emettono un laser nella direzione corretta. (Ciò richiede una differenziazione tra i portali di input e output; qwertyuioper questo ho usato le lettere .)
Un po 'non golfato, con dichiarazioni stampate in modo da poter vedere le sostituzioni in corso (ogni sostituzione rappresenta un "giro" di progressione laser) e con la gbandiera aggiunta alla principale in s///modo che non subisca così tante iterazioni:
# 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"