펄, 647
이것은 코드 골프에 대한 첫 번째 시도이며, 나는 C # 점수를 이길 수조차 없었지만 조금 당황 스럽지만 전체 작업을 일련의 정규식 대체. (또한 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"
설명 : 코드는 레이저가 통과 할 때 그리드 문자열을 반복적으로 업데이트합니다. -
수평 레이저 나타내는 |
수직 레이저 +
교차 레이저 레이저의 위쪽에서 반사 거울 레이저가 바닥에서 반사 거울 바닥 튀는 레이저로 미러 및 레이저 오프 튀는와 거울 상단. A는 동안, 양쪽 레이저 미러 A는 양면 거울은 레이저. . (이 내가 다소 적절한 모양 문자 선택하려고 대소 문자를 구분합니다 - 예를 들어를, 그리고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"