Perl, 647
Đây là lần thử đầu tiên của tôi ở môn đánh gôn, và tôi hơi xấu hổ, tôi thậm chí không đánh bại điểm C #, nhưng tôi nghĩ sẽ rất thú vị (hoặc vui, hoặc chỉ là bạo dâm) để làm toàn bộ điều này như một loạt thay thế regex. (Tôi cũng nghĩ sẽ rất vui khi đánh lên Perl của mình, nhưng cuối cùng tôi đã rất hối hận vì đã không thực hiện nó trong Ruby hoặc Python.)
Tôi đã không thực hiện nhiều thử nghiệm, nhưng tôi nghĩ nó nên xử lý mọi trường hợp.
Lưới được nhập thông qua STDIN. Phải có ít nhất một dòng mới trong đầu vào (nghĩa là một hàng không có dòng mới sẽ không hoạt động).
%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"
Giải thích: mã lặp lại cập nhật chuỗi lưới khi các laser đi qua nó. -đại diện cho một tia laser nằm ngang, |một tia laser thẳng đứng, +tia laser chéo, Kmột \chiếc gương với tia laser bật ra khỏi đỉnh, kmột /chiếc gương với tia laser bật ra khỏi đáy, Zmột \chiếc gương có tia laser bật ra khỏi đáy và Wmột /chiếc gương bị tia laser bật ra đỉnh. %là một /tấm gương với laser ở cả hai bên, trong khi Xlà một \tấm gương với laser ở cả hai bên. (Đây là những trường hợp nhạy cảm. Tôi đã cố gắng chọn các chữ cái có vẻ phù hợp - ví dụ, kvàKlà một số lựa chọn rõ ràng - nhưng thật không may, hiệu quả thực sự không hữu ích. Tôi thực sự nên đặt thông tin này vào một bảng, nhưng tôi đã kiệt sức ngay bây giờ.)
Xử lý các cổng theo cùng một cách (nghĩa là gán cho mỗi chữ số một bộ ký tự phụ dựa trên các vị trí laser đầu vào / đầu ra có thể) sẽ cần 144 ký tự (bao gồm cả 9 gốc), do đó, khi laser chạm vào cổng "đầu vào", Tôi thêm ký tự cổng thông tin "đầu ra" vào tập hợp các ký tự phát ra tia laser theo hướng thích hợp. (Điều này không yêu cầu phân biệt giữa cổng đầu vào và đầu ra; Tôi đã sử dụng các chữ cái qwertyuiocho việc này.)
Một phần nào đó không được đánh gôn, với các câu lệnh in để bạn có thể thấy sự thay thế xảy ra (mỗi lần thay thế đại diện cho một "vòng" tiến trình laser) và với gcờ được thêm vào chính s///để nó không mất quá nhiều lần lặp:
# 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"