Perl, 647
นี่เป็นครั้งแรกที่ฉันพยายามเล่นกอล์ฟและฉันค่อนข้างเขินที่ไม่ได้คะแนน C # แต่ฉันคิดว่ามันน่าสนใจ (หรือสนุกหรือแค่ร้ายกาจ) เพื่อทำสิ่งต่างๆทั้งหมดในฐานะ ชุดของการแทน regex (ฉันก็คิดว่ามันคงจะสนุกที่ได้แปรง Perl แต่ตอนท้ายฉันเสียใจอย่างมากที่ไม่ได้ใช้มันใน Ruby หรือ Python)
ฉันไม่ได้ทำการทดสอบมากนัก แต่ฉันคิดว่ามันควรจะจัดการทุกกรณี
ตารางการป้อนข้อมูลผ่านทาง STDIN ต้องมีการขึ้นบรรทัดใหม่อย่างน้อยหนึ่งรายการ (เช่นแถวเดียวที่ไม่มีบรรทัดใหม่จะไม่ทำงาน)
%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"
คำอธิบาย: โค้ดจะอัพเดตสตริงกริดอย่างซ้ำ ๆ ตามที่เลเซอร์ส่งผ่าน -
แสดงให้เห็นถึงเลเซอร์แนวนอน|
เลเซอร์แนวตั้ง+
เลเซอร์ข้ามกระจกด้วยเลเซอร์ใหญ่ปิดด้านบนK
\
k
/
กระจกด้วยเลเซอร์ใหญ่ปิดด้านล่าง,Z
\
กระจกด้วยเลเซอร์ใหญ่ปิดด้านล่างและกระจกด้วยเลเซอร์ใหญ่ปิด ด้านบน. เป็นกระจกที่มีเลเซอร์ทั้งสองด้านในขณะที่เป็นกระจกที่มีเลเซอร์ทั้งสองด้าน (สิ่งเหล่านี้ต้องตรงตามตัวพิมพ์ใหญ่ - เล็ก) ฉันพยายามเลือกตัวอักษรที่ค่อนข้างเหมาะสม - ตัวอย่างเช่นและW
/
%
/
X
\
k
K
เป็นตัวเลือกที่ค่อนข้างชัดเจน - แต่น่าเสียดายที่เอฟเฟกต์นั้นไม่มีประโยชน์จริงๆ ฉันควรใส่ข้อมูลนี้ลงในตารางจริงๆ แต่ตอนนี้ฉันหมดแรงไปแล้ว)
การจัดการพอร์ทัลในวิธีเดียวกัน (เช่นการกำหนดตัวเลขแต่ละตัวให้มีชุดอักขระพิเศษตามตำแหน่งเลเซอร์อินพุต / เอาท์พุตที่เป็นไปได้) จะต้องมี 144 อักขระ (รวมถึงต้นฉบับ 9) ดังนั้นเมื่อเลเซอร์เข้าสู่พอร์ทัล "อินพุต" ฉันเพิ่มอักขระพอร์ทัล "เอาท์พุท" ในชุดของอักขระที่เปล่งแสงเลเซอร์ในทิศทางที่เหมาะสม (สิ่งนี้ต้องการความแตกต่างระหว่างอินพุตและเอาต์พุตพอร์ทัลฉันใช้ตัวอักษรqwertyuio
สำหรับสิ่งนี้)
ค่อนข้างไม่ตีกอล์ฟพร้อมคำสั่งการพิมพ์เพื่อให้คุณสามารถเห็นการแทนที่เกิดขึ้น (การแทนที่แต่ละรายการแสดงถึงหนึ่งรอบของการก้าวหน้าของเลเซอร์) และมีการg
เพิ่มธงลงในหลักs///
เพื่อที่จะไม่ต้องทำซ้ำหลายครั้ง:
# 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"