6 각형 미로 시간!


27

또 다른 미로 도전에 대한 시간이지만, 당신이 알고있는 것처럼.

이 도전에 대한 규칙은 대부분의 미로 도전과 약간 다릅니다. 타일 ​​유형은 다음과 같이 정의됩니다.

  • S: 당신이 시작하는 미로의 위치
  • E: 가려고하는 위치
  • 0: 교차 할 수없는 벽
  • +: 교차 할 수있는 바닥

왼쪽, 오른쪽, 왼쪽, 오른쪽, 왼쪽 아래 또는 오른쪽 아래 6 가지 방향으로 이동할 수 있습니다.

\ /
-S-
/ \

미로는 포장되지 않습니다. 목표는에서 얻을 수있는 최단 경로 문자열을 찾을 수 있습니다 S에를 E.

입력:

입력은 표시된 미로와 같이 공백으로 구분 된 선입니다. 후행 공백이 줄을 따라 가지 않습니다.

산출:

문자열의 R, L그리고 F어디에

  • R 60도 오른쪽 (시계 방향)으로 회전
  • L 왼쪽으로 (시계 반대 방향) 60도 회전
  • F 당신이 가리키는 방향으로 한 공간 이동

당신은 가리키는 시작 left-up

가장 짧은 경로는 방문한 위치 수가 아닌 생성 된 문자열의 길이로 계산됩니다. 프로그램은 솔루션으로 최단 경로를 인쇄해야합니다.

미로를 풀 수 없다면 출력해야합니다 Invalid maze!.

( >>>출력입니다)

     0 0 0 0
    0 + 0 + 0
   0 0 0 + + 0
  0 + 0 + 0 + 0
 0 0 + + 0 0 + 0
0 0 + 0 + 0 0 + 0
 E 0 + 0 0 + + 0 
  + + 0 + 0 + 0
   0 0 0 0 0 +
    + 0 + + +
     0 S 0 0

>>>RFRFFLFLFRFFLFFFLFLFFRFLFLFRFRFRF

  + 0 0 0 0 0 0
 0 0 0 0 0 + + 0
0 0 E 0 + 0 0 + 0
 0 0 0 0 0 0 0 +
  0 + 0 0 + + +
   0 0 + + 0 0
    S + 0 0 0

>>>Invalid maze!

0 E S

>>>LF


 E + 0
0 + + +
 0 0 S
  + +

>>>FFLF

  E
 0 +
0 + +
 0 +
  S

>>>RFFLFF

 0 E + 0 0
0 + 0 0 + +
 + 0 + + + 0
  + 0 + 0 + 0
   + + + 0 S

>>>FFLFLFFRFRFFRFF

 E 0 + + 0
0 + 0 + + 0
 + + + 0 + 0
  + 0 0 0 0 0
   + + + + 0
    + 0 S 0

>>>FLFFRFFRFLF

(일부 미로에는 길이는 같지만 여기에 나열되지 않은 다른 솔루션이 있습니다.)


27
Hexagony 솔루션을 기대하고 있습니다.
bkul

3
Hexagony 솔루션에 500 포인트 현상금을 수여합니다.
lirtosiast

@ lirtosiast2 년 후, 육각형은이 문제에 대한 확장이라고 생각합니다.)
J Atkin

몇 년 더 기다리 자.
user202729

후행 줄 바꿈이있을 수 있습니까?
user202729

답변:


17

파이썬 2, 291 바이트

def f(M):
 Y=map(max,M).index("S");X=M[Y].find("S");V={()};Q=[(0,0,0,1,"")]
 while Q:
    try:x,y,u,v,p=s=Q.pop(0);c=(Y>=y<=X-2*x)*ord(M[Y-y][X-2*x-y])
    except:c=0
    if c==69:return p
    if{c%2*s[:4]}-V:V|={s[:4]};Q+=(x+u,y+v,u,v,p+"F"),(x,y,-v,u+v,p+"R"),(x,y,u+v,-u,p+"L")
 return"Invalid maze!"

f미로를 행 목록으로 사용하고 솔루션이있는 경우 솔루션을 반환하는 함수 입니다.

설명

행한다는 너비 우선에서 최단 경로 찾기 위해 위치 / 방향 쌍의 그래프를 검색 S하는 방법에 대해 E.

흥미로운 점은 6 각형 그리드에서 위치와 방향을 표현하는 간단한 방법을 찾는 것입니다. 간단한 방법으로 "스텝핑"(예 : 특정 방향으로 이동) 및 회전이 가능합니다. 여기서 "진정한"육각형 그리드의 좌표를 나타 내기 위해 복잡한 숫자를 사용하고 싶은 유혹이 있지만, 여러 가지 이유로별로 좋은 생각이 아닙니다. 가장 심각한 이유는 우리가 √3을 연결해야한다는 사실입니다. 부동 소수점 숫자를 사용할 때 절대 정밀도가 필요한 경우 (예 : 이미 방문한 상태를 추적하기 위해) 부동 소수점 숫자를 사용하면 작동하지 않는 곳 (60 ° = √3 / 2) JavaScript 콘솔을 실행하고 입력하여 Math.sqrt(3)*Math.sqrt(3) == 3직접 확인할 수 있습니다.

그러나 약간의 트릭을 사용할 수 있습니다! 복소수를 사용하는 대신 , 유사한 정맥에서 육각형 수 를 실수 수 a + bh로 정의합니다 . 여기서 h 는 복소수를 다룰 때 허수 i 와 비슷한 역할을합니다 . 복소수와 마찬가지로 쌍 ( a , b )를 평면의 점과 연관시킬 수 있습니다 . 여기서 실제 축은 오른쪽을 가리키고 가상 축은 60 °를 가리키고, 실제와 허수 부는 각각 1과 같습니다. 이 좌표계를 미로의 셀에 매핑하는 것은 쉽지 않습니다.

그림 1

i 와 달리 상수 hh 2 = h -1 관계에 의해 정의됩니다 ( h를 구하면 약간의 통찰력이 나타날 수 있습니다). 육각수 첨가하고, 승산, 상기 관계를 이용하여, 많은 복소수 등일 수있다 : ( +의 BH ) + ( C + DH ) = ( +의 C ) + ( B + D ) (H) , 및 ( +의 BH ) · ( c + dh ) = ( ac - bd
) + ( ad + bc + bd ) h . 이러한 연산은 복잡한 대응 물과 동일한 기하학적 해석을 갖습니다. 덧셈은 벡터 덧셈이고 곱셈은 스케일링과 회전입니다. 특히 6 각 숫자를 시계 반대 방향으로 60 ° 회전하려면 h :
( a + bh ) · h = -b + ( a + b ) h를 곱하고 같은 숫자를 시계 방향으로 60 ° 회전하려면 나눕니다. 하여 H :
( + BH ) / H = ( +bh ) · (1- h ) = (a + b)- . 예를 들어, 시계 반대 방향으로 h를 6 번 곱하여 오른쪽으로 1, (1, 0), 완전한 원을 가리키는 단위 육각형 숫자를 취할 수 있습니다 :
(1, 0) · h = (0, 1 ); (0, 1) · h = (-1, 1); (-1, 1) · h = (-1, 0); (-1, 0) · h = (0, -1); (0, -1) · h = (1, -1);
(1, -1) · h = (1, 0).

이 프로그램은이 방식으로 6 각형 숫자를 사용하여 미로의 현재 위치와 현재 방향을 나타내고 지정된 방향으로 진행하며 방향을 왼쪽과 오른쪽으로 회전시킵니다.


31

헥사 고니 , 2437 바이트

대망의 프로그램은 다음과 같습니다.

(.=$>({{{({}}{\>6'%={}{?4=$/./\_><./,{}}{<$<\?{&P'_("'"#<".>........_..\></</(\.|/<>}{0/'$.}_.....><>)<.$)).><$./$\))'"<$_.)><.>%'2{/_.>(/)|_>}{{}./..>#/|}.'/$|\})'%.<>{=\$_.\<$))<>(|\4?<.{.%.|/</{=....$/<>/...'..._.>'"'_/<}....({{>%'))}/.><.$./{}{\>$\|$(<><$?..\\<.}_>=<._..\(/.//..\}\.)))))<...2/|$\){}/{..><>).../_$..$_>{0#{{((((/|#.}><..>.<_.\(//$>))<(/.\.\})'"#4?#\_=_-..=.>(<...(..>(/\")<((.\=}}}\>{}{?<,|{>/...(...>($>{)<.>{=P&/(>//(_.)\}=#=\4#|)__.>"'()'\.'..".(\&P'&</'&\$_></}{)<\<0|\<.}.\"\.(.(.(/(\..{.>}=P/|><.(...(..."/<.{"_{{=..)..>})<|><$}}/\}}&P<\(/._...>\$'/.>}/{}}{)..|/(\'.<(\''"")$/{{}})<..'...}}>3#./\$<}|.}|..$.><${{}/>.}}{{<>(""''/..>){<}\?=}{\._=/$/=_>)\{_\._..>)</{\=._.....>(($>}}<.>5#.\/}>)<>-/(.....{\<>}}{{/)\$>=}}}))<...=...(\?{{{?<\<._...}.><..\}}/..>'P&//(\......(..\})"'/./&P'&P{}}&P'<{}\{{{({{{(.\&P=<.><$"&1}(./'"?&'&"\.|>}{?&"?&'P&/|{/&P''</(\..>P&{/&/}{}&'&},/"&P'&?<.|\}{&?"&P'&P'<._.>"&}\(>))<\=}{}<.{/}&?"&"&/"&"?&}\.|>?&"?&{{}}?&//x'&{((<._\($|(}.\/}{/>=&'P&"&/".{3?<.|\"&P'&P}{}&P'<.>&{}}?&"&'P&\=}}<.}/2?".?''5?"/?1{(}\."..../{},<../&//&"&P'&P'&"&"</{}}{{/>"?1''?.'({/}}{}<..>?&"?&}}$>)|P/<.>"&'P&'P&"&"&{/........._/"\$#1}/._.........|,($<'"}'?/_$P#"$0'${)$})$)|........(>/\.#1?<$<|.....>?&}$>=?&"?&/1$..>I;n;v;a;l;i;d;P0;m;a\|\"(}}({=/..$_...\"&P=},}}&P'<.|><....................;...>1"(}}){=/_....>'P&'P&}}_?&/#.>}?4'%\/<...@;1P;e;z<._><>"))'?=<.$$=..\&P}{&</\"><_'|/'&=}<.>{{.<.........|>(/>3")}}){=/=/_.>}P&"?/"<).}_.>?4{=:<.|_...........\$\2$'>4")}}({/."\{&P'&?/><.?|>P...."/=(>(/./(}{{\..>(<>(<>?5'"((..'/...#,</,}{{\.......;.F>..\(...}....._.._..._..._........__..'$......\.<R..$.>))<$}{{&P'&?}<.\$$.\...................$\.<>L\.\(('_"\>}P&"?&{/__/=(.(<.>_)..<...>....\..._.<.....&?=\}=&?"&<.."'>.\>))<.|>))\.|$.>&"?&{{}=P&}?&=}/{\.>&{{P/{">)<|\{<(|\(_(<>\_\?"&P'&P}{{{&<=_.>\&\?"&?<|'{/(/>{{/_>.{/=/\\.>'P&"?&"?&"?/._(\)\\>?&"/_|.>/.$/|$..\\><..\&?}{{}&P'&<}.._>{<|\{}<._$>-")<.>_)<|{)$|..>}=P&"?&"?/...{"./>'P&/=_\{?(/>(<>\(|)__.\&?}}{}&P<}.$.\&P'&P'&<\})))&=<\)<'.'_,><.>"?&'P&'/.|>?&{{}?&"?/>&"?&"?&}}<.".(\\\&?={&P<{..\"&?"&P'&<.?....|.$'\$/\"/.,.>{}{}=/..>&'P&}{{}P/\{}&P{(&?"&?"<'.(\&?"&<}..\?"&?"&<.>P&={}}?&}}P&'P&/.'.>&"?/..>P&}}{{P/\}&P'&?={&?<$}=\"."\P'<{..\'&P'&<....>'P&{}P&"?&{{<\\..>&/$.>}{?&"?/|'$&.P&$P\$'&P={(/..\P\\.\{&?"&?\...\?{{}=<$&P'&P<.,./<?\...{}=P\"&<.>=P&""'?&'P&'/$.#1.>{?1#=$\&'P/\}&P'&?={(,}<._?_&\&?{=&{*=}4<.>P&"?&"?&'P&/1_$>}?&}}=?&){?/\{}&P'&?={&?#<$

온라인으로 사용해보십시오!

"판독 가능"버전 :

                             ( . = $ > ( { { { ( { } } { \ > 6 ' % = { } { ? 4 = $ / .
                            / \ _ > < . / , { } } { < $ < \ ? { & P ' _ ( " ' " # < " .
                           > . . . . . . . . _ . . \ > < / < / ( \ . | / < > } { 0 / ' $
                          . } _ . . . . . > < > ) < . $ ) ) . > < $ . / $ \ ) ) ' " < $ _
                         . ) > < . > % ' 2 { / _ . > ( / ) | _ > } { { } . / . . > # / | }
                        . ' / $ | \ } ) ' % . < > { = \ $ _ . \ < $ ) ) < > ( | \ 4 ? < . {
                       . % . | / < / { = . . . . $ / < > / . . . ' . . . _ . > ' " ' _ / < }
                      . . . . ( { { > % ' ) ) } / . > < . $ . / { } { \ > $ \ | $ ( < > < $ ?
                     . . \ \ < . } _ > = < . _ . . \ ( / . / / . . \ } \ . ) ) ) ) ) < . . . 2
                    / | $ \ ) { } / { . . > < > ) . . . / _ $ . . $ _ > { 0 # { { ( ( ( ( / | #
                   . } > < . . > . < _ . \ ( / / $ > ) ) < ( / . \ . \ } ) ' " # 4 ? # \ _ = _ -
                  . . = . > ( < . . . ( . . > ( / \ " ) < ( ( . \ = } } } \ > { } { ? < , | { > /
                 . . . ( . . . > ( $ > { ) < . > { = P & / ( > / / ( _ . ) \ } = # = \ 4 # | ) _ _
                . > " ' ( ) ' \ . ' . . " . ( \ & P ' & < / ' & \ $ _ > < / } { ) < \ < 0 | \ < . }
               . \ " \ . ( . ( . ( / ( \ . . { . > } = P / | > < . ( . . . ( . . . " / < . { " _ { {
              = . . ) . . > } ) < | > < $ } } / \ } } & P < \ ( / . _ . . . > \ $ ' / . > } / { } } {
             ) . . | / ( \ ' . < ( \ ' ' " " ) $ / { { } } ) < . . ' . . . } } > 3 # . / \ $ < } | . }
            | . . $ . > < $ { { } / > . } } { { < > ( " " ' ' / . . > ) { < } \ ? = } { \ . _ = / $ / =
           _ > ) \ { _ \ . _ . . > ) < / { \ = . _ . . . . . > ( ( $ > } } < . > 5 # . \ / } > ) < > - /
          ( . . . . . { \ < > } } { { / ) \ $ > = } } } ) ) < . . . = . . . ( \ ? { { { ? < \ < . _ . . .
         } . > < . . \ } } / . . > ' P & / / ( \ . . . . . . ( . . \ } ) " ' / . / & P ' & P { } } & P ' <
        { } \ { { { ( { { { ( . \ & P = < . > < $ " & 1 } ( . / ' " ? & ' & " \ . | > } { ? & " ? & ' P & /
       | { / & P ' ' < / ( \ . . > P & { / & / } { } & ' & } , / " & P ' & ? < . | \ } { & ? " & P ' & P ' <
      . _ . > " & } \ ( > ) ) < \ = } { } < . { / } & ? " & " & / " & " ? & } \ . | > ? & " ? & { { } } ? & /
     / x ' & { ( ( < . _ \ ( $ | ( } . \ / } { / > = & ' P & " & / " . { 3 ? < . | \ " & P ' & P } { } & P ' <
    . > & { } } ? & " & ' P & \ = } } < . } / 2 ? " . ? ' ' 5 ? " / ? 1 { ( } \ . " . . . . / { } , < . . / & /
   / & " & P ' & P ' & " & " < / { } } { { / > " ? 1 ' ' ? . ' ( { / } } { } < . . > ? & " ? & } } $ > ) | P / <
  . > " & ' P & ' P & " & " & { / . . . . . . . . . _ / " \ $ # 1 } / . _ . . . . . . . . . | , ( $ < ' " } ' ? /
 _ $ P # " $ 0 ' $ { ) $ } ) $ ) | . . . . . . . . ( > / \ . # 1 ? < $ < | . . . . . > ? & } $ > = ? & " ? & / 1 $
  . . > I ; n ; v ; a ; l ; i ; d ; P 0 ; m ; a \ | \ " ( } } ( { = / . . $ _ . . . \ " & P = } , } } & P ' < . |
   > < . . . . . . . . . . . . . . . . . . . . ; . . . > 1 " ( } } ) { = / _ . . . . > ' P & ' P & } } _ ? & / #
    . > } ? 4 ' % \ / < . . . @ ; 1 P ; e ; z < . _ > < > " ) ) ' ? = < . $ $ = . . \ & P } { & < / \ " > < _ '
     | / ' & = } < . > { { . < . . . . . . . . . | > ( / > 3 " ) } } ) { = / = / _ . > } P & " ? / " < ) . } _
      . > ? 4 { = : < . | _ . . . . . . . . . . . \ $ \ 2 $ ' > 4 " ) } } ( { / . " \ { & P ' & ? / > < . ? |
       > P . . . . " / = ( > ( / . / ( } { { \ . . > ( < > ( < > ? 5 ' " ( ( . . ' / . . . # , < / , } { { \
        . . . . . . . ; . F > . . \ ( . . . } . . . . . _ . . _ . . . _ . . . _ . . . . . . . . _ _ . . ' $
         . . . . . . \ . < R . . $ . > ) ) < $ } { { & P ' & ? } < . \ $ $ . \ . . . . . . . . . . . . . .
          . . . . . $ \ . < > L \ . \ ( ( ' _ " \ > } P & " ? & { / _ _ / = ( . ( < . > _ ) . . < . . . >
           . . . . \ . . . _ . < . . . . . & ? = \ } = & ? " & < . . " ' > . \ > ) ) < . | > ) ) \ . | $
            . > & " ? & { { } = P & } ? & = } / { \ . > & { { P / { " > ) < | \ { < ( | \ ( _ ( < > \ _
             \ ? " & P ' & P } { { { & < = _ . > \ & \ ? " & ? < | ' { / ( / > { { / _ > . { / = / \ \
              . > ' P & " ? & " ? & " ? / . _ ( \ ) \ \ > ? & " / _ | . > / . $ / | $ . . \ \ > < . .
               \ & ? } { { } & P ' & < } . . _ > { < | \ { } < . _ $ > - " ) < . > _ ) < | { ) $ | .
                . > } = P & " ? & " ? / . . . { " . / > ' P & / = _ \ { ? ( / > ( < > \ ( | ) _ _ .
                 \ & ? } } { } & P < } . $ . \ & P ' & P ' & < \ } ) ) ) & = < \ ) < ' . ' _ , > <
                  . > " ? & ' P & ' / . | > ? & { { } ? & " ? / > & " ? & " ? & } } < . " . ( \ \
                   \ & ? = { & P < { . . \ " & ? " & P ' & < . ? . . . . | . $ ' \ $ / \ " / . ,
                    . > { } { } = / . . > & ' P & } { { } P / \ { } & P { ( & ? " & ? " < ' . (
                     \ & ? " & < } . . \ ? " & ? " & < . > P & = { } } ? & } } P & ' P & / . '
                      . > & " ? / . . > P & } } { { P / \ } & P ' & ? = { & ? < $ } = \ " . "
                       \ P ' < { . . \ ' & P ' & < . . . . > ' P & { } P & " ? & { { < \ \ .
                        . > & / $ . > } { ? & " ? / | ' $ & . P & $ P \ $ ' & P = { ( / . .
                         \ P \ \ . \ { & ? " & ? \ . . . \ ? { { } = < $ & P ' & P < . , .
                          / < ? \ . . . { } = P \ " & < . > = P & " " ' ? & ' P & ' / $ .
                           # 1 . > { ? 1 # = $ \ & ' P / \ } & P ' & ? = { ( , } < . _ ?
                            _ & \ & ? { = & { * = } 4 < . > P & " ? & " ? & ' P & / 1 _
                             $ > } ? & } } = ? & ) { ? / \ { } & P ' & ? = { & ? # < $

Esoteric IDE에서 테스트 : TIO는 일부 더 큰 테스트 사례에서 시간 초과 될 수 있지만 모두 확인되었습니다. Timwi 덕분에 IDE 없이는 불가능했을 것입니다.

약간의 빈 공간이 있으므로이를 세로 28이 아닌 가로 28 육각형에 맞출 수 있었을 것입니다.하지만 큰 작업이 될 것이므로 시도하지 않을 것입니다.

기본 설명

더 크고 자세한 버전을 보려면 이미지를 클릭하십시오.

기능

기능
참고 : 나눗셈은 일반적으로 정확하지만 때로는 대략적인 추측 일 수 있습니다.

이 코드는 Hexagony가 허용하는 한 "기능적"입니다. 이 코드에는 위의 다이어그램에서 레이블이 붙은 8 개의 주요 기능이 있으며 그 이름은 호출되는 숫자로 표시됩니다 (따라서 명령 포인터 번호는 숫자 mod 6입니다). (거칠게) 호출 순서는 다음과 같습니다 (따옴표로 묶인 이름은 나중에 설명 할 메모리의 위치입니다).

  • S : 출발 기능 - 다음 세 가지 패스 "경로 스택"시작 「참조 어레이 "까지 입력 한 설정을 판독하고 F, RL주 처리 준비. 명령 포인터 0은 기능 0으로 이동하고 실행은 기능 1로 이동합니다.
  • 1 (-11) : 주요 기능-2를 사용하여 경로를 가져오고 3을 사용하여 유효성을 확인하고 유효한 경우 -110 / -10 기능을 두 번 사용한 후 4를 세 번 이동하여 새 경로를 "경로에 복사합니다. 스택 ", 자신으로 돌아와 마무리. 경로가 끝 위치에있는 경우 기능 5를 호출 할 수 있습니다.
  • 2 : 처리 할 준비가 된 "경로 스택"에서 다음 경로를 가져옵니다. 스택에 경로가 남아 있지 않으면 함수 -1을 호출합니다. 기능 1로 돌아갑니다.
  • 3 : 이동 번호뿐만 아니라 한 쌍의 값을 가져 와서 "참조 배열"을 검사하여 현재 경로가 유효한 위치에서 종료되었는지 확인합니다. 유효한 위치는 처음 3 개의 이동 내에서 시작하거나 +2 개의 이동 내에서 처음 도달 한 것입니다. 기능 1로 돌아갑니다.
  • -10 / -110 : 현재 경로를 복사합니다. 기능 1로 돌아갑니다.
  • 0 : 기능 1이로 이동 방향을 관리하도록 도와줍니다 F. 기능 1로 돌아갑니다.
  • 4 : 현재 경로의 사본을 가져 와서 기능 1과 상호 링크하면 경로가 F, R또는 L추가 된 동일한 경로로 변경 됩니다. 기능 1로 돌아갑니다.
  • 5 : 경로를 가져와 올바른 경로 (예 :)를 인쇄 FFLF한 다음 프로그램을 종료합니다.
  • -1 : 인쇄 Invalid maze!하고 종료합니다.
  • (이중 화살표) : 공간이 부족하여 기능 1 / -11이 기능 -1 위의 공간으로 이동해야합니다.

기억

메모리 레이아웃
참고 : 다이어그램에 대해 Esoteric IDE에 다시 감사합니다

메모리는 세 가지 주요 부분으로 구성됩니다.

  • 참조 배열 : 그리드는 각 단계마다 값을 사용하여 2 열로 저장됩니다.
    • 0이 하나 나타냅니다 , 0더 이동 전에 어떤 방향으로 장소를 종료하는 데 필요한 것보다 액세스 한 또는 유효한 장소.
    • 1은 +아직 도달하지 않은 것을 나타냅니다 .
    • (높은 숫자)는 어떤 방향 으로든 장소를 나가기에 충분한 움직임이 있었던 움직임 번호를 나타냅니다.
    • 10은 또한 개행을 나타냅니다. 즉, 공백이 아닌 마지막 공백 문자를 즉시 ​​따르는 것으로 가정하면 도달하지 않습니다.
  • 레일 : 왼쪽에 -1단일이 포함 -2되어 있으며 메모리 포인터가 코어 처리 영역으로 빠르게 돌아갈 수 있습니다.
  • 경로 스택 : 경로 ID별로 순서대로 테스트되지 않은 각 경로를 저장합니다 (이것은 이동 번호와 직접 관련되므로 짧은 경로가 먼저 테스트 됨). 경로는 다음과 같이 저장됩니다.
    경로 레이아웃
    • 썩음 : 현재 경로의 끝에서 회전 : 왼쪽에서 0, 시계 방향으로 5
    • 이동 : 현재 이동 번호 (지침-1)
    • 경로 : 전류 경로와 급 저장 F, R, L1, 2, 3각각
    • x / y : 현재 경로의 끝에서 좌표 : x + 1 -1s 바로 다음 y 값 위로 (참조 데이터에서 레일을 분리하기 위해 y = 0은 1로 처리되지만)

다른 중요한 메모리 위치 :

  1. 의 x / y E가 여기에 저장됩니다.
  2. 이 공간은 메모리 안팎의 경로를 전환하는 데 사용됩니다.
  3. 이 위치는 처리 중 각 경로가 저장되는 중심입니다.

다음 단계는 가장 짧은 미로 경로를 찾기 위해 프로그램을 통해 프로그램을 실행하는 것입니다.
Veskah

누군가가 게시 할 것임을 알고 있습니다. 마지막으로 ... / 나는 또한 다른 계획을 가지고 있는데 아마도 당신보다 적은 코드를 사용해야합니다. 실제로 구현할 시간이 없습니다.
user202729 2016

@ user202729는 그것에 대해 듣는 것이 흥미로울 것입니다. 이 방법은 아마도 적어도 2 크기로 골프를 칠 수는 있지만 거의 확실히 더 나은 것이 있습니다.
boboquack

1
@lirtosiast를 기다리고 있습니다.
J Atkin

1
지연에 대한 사과드립니다.
lirtosiast

6

파이썬 3, 466 바이트

깊이 우선 검색 또는 무언가를 사용하면 아마도 더 작아 졌을 것입니다. 이 괴물은 Dijkstra를 사용하며 매우 빠르지 만 매우 깁니다.

이 코드는 S미로와 함께 여러 줄 문자열을 가져 와서 결과를 반환 하는 함수 를 정의합니다 .

def F(M,L,c):y=M[:M.index(c)].count("\n");return L[y].index(c),y
def S(M):
 L=M.split("\n");Q=[("",)+F(M,L,"S")+(0,)];D={};R=range;H=len;U=R(2**30)
 while Q:
  C,*Q=sorted(Q,key=H);w,x,y,d=C
  for e in R(H(L)>y>-1<x<H(L[y])>0<H(D.get(C[1:],U))>H(w)and(L[y][x]in"+SE")*6):D[C[1:]]=w;E=(d+e)%6;Q+=[(w+",R,RR,RRR,LL,L".split(",")[e]+"F",x+[-1,1,2,1,-1,-2][E],y+[-1,-1,0,1,1,0][E],E)]
 J=min([D.get(F(M,L,"E")+(d,),U)for d in R(6)],key=H);return[J,"Invalid maze!"][J==U]

다음은 코드 테스트입니다.

언 골프

def find_char(maze, lines, char):
    y = maze[:maze.index(char)].count("\n")
    return lines[y].index(char), y
def solve(maze):
    lines = maze.split("\n")
    x, y = find_char(maze, lines, "S")
    queue = [("", x, y, 0)]
    solutions = {}
    very_long = range(2**30)
    x_for_direction = [-1,1,2,1,-1,-2]
    y_for_direction = [-1,-1,0,1,1,0]
    rotations = ["","R","RR","RRR","LL","L"]
    while len(queue) > 0:
        queue = sorted(queue, key=len)
        current, *queue = queue
        route, x, y, direction = current
        if 0 <= y < len(lines) and 0 <= x < len(lines[y]) and lines[y][x] in "+SE" and len(solutions.get(current[1:], very_long)) > len(route):
            solutions[current[1:]] = route
            for change in range(6):
                changed = (direction + change) % 6
                queue += [(route + rotations[change] + "F", x + x_for_direction[changed], y + y_for_direction[changed], changed)]
    end_x, end_y = find_char(maze, lines, "E")
    solution = min([solutions.get((end_x, end_y, direction), very_long) for direction in range(6)], key=len)
    return "Invalid maze!" if solution == very_long else solution

와, 아주 좋아요 글쓰기에 시간이 얼마나 걸렸습니까?
J Atkin

1
@JAtkin 글쎄, 파일은 1.5 시간 전에 만들어졌지만 실제로 코드 작업에 얼마나 많은 시간을 소비했는지는 확실하지 않습니다. 또한 오전 3시이므로 생산성이 최대입니다.
PurkkaKoodari 1

니스, 나는 2 시간 이상을 보냈고, 나의 대부분은 이미 표준 미로 용으로 작성되었습니다.
J Atkin

ungolfed 버전이 있습니까?
J Atkin

1
@JAtkin 시작시에 돌아서야 할 수도 있기 때문에 필요합니다. 시작 위치가 없으면 작동합니다 L,,R.
PurkkaKoodari

3

그루비, 624 바이트 전부!

시간 큰 공으로 구르는 공을 얻으십시오. 여러 줄 문자열을 인수로 취합니다.Q

Q={a->d=[0]*4
a.eachWithIndex{x,y->f=x.indexOf('S');e=x.indexOf('E');
if(f!=-1){d[0]=f;d[1]=y}
if(e!=-1){d[2]=e;d[3]=y}}
g=[]
s={x,y,h,i,j->if(h.contains([x, y])|y>=a.size()||x>=a[y].size()|x<0|y<0)return;k = a[y][x]
def l=h+[[x, y]]
def m=j
def n=1
if(h){
o=h[-1]
p=[x,y]
q=[p[0]-o[0],p[1]-o[1]]
n=[[-2,0]:0,[-1,-1]:1,[1,-1]:2,[2,0]:3,[1,1]:4,[-1,1]:5][q]
r=n-i
m=j+((r==-5|r==5)?' LR'[(int)r/5]:['','R','RR','LL','L'][r])+'F'}
if(k=='E')g+=m
if(k=='+'|k=='S'){s(x-2,y,l,n,m)
s(x+2,y,l,n,m)
s(x+1,y+1,l,n,m)
s(x+1,y-1,l,n,m)
s(x-1,y+1,l,n,m)
s(x-1,y-1,l,n,m)}}
s(d[0],d[1],[],1,'')
print(g.min{it.size()}?:"Invalid maze!")}

언 골프 버전 :

def map =
        """
  + 0 0 0 0 0 0
 0 0 0 0 0 + + 0
0 0 E 0 + 0 0 + 0
 0 0 0 0 0 0 0 +
  0 + 0 0 + + +
   0 0 + + 0 0
    S + 0 0 0""".split('\n').findAll()
//map =
//        """
// 0 + +
//E + 0 S 0
// 0 0 0 +
//  + + +""".split('\n').findAll()

//map = [""]// TODO remove this, this is type checking only
//map.remove(0)
//reader = System.in.newReader()
//line = reader.readLine()
//while (line != '') {
//    map << line
//    line = reader.readLine()
//}

startAndEnd = [0, 0, 0, 0]
map.eachWithIndex { it, idx ->
    s = it.indexOf('S'); e = it.indexOf('E');
    if (s != -1) {
        startAndEnd[0] = s; startAndEnd[1] = idx
    }
    if (e != -1) {
        startAndEnd[2] = e; startAndEnd[3] = idx
    }
}

def validPaths = []
testMove = { x, y, visited ->// visited is an array of x y pairs that we have already visited in this tree
    if (visited.contains([x, y]) || y >= map.size() || x >= map[y].size() || x < 0 || y < 0)
        return;


    def valueAtPos = map[y][x]
    def newPath = visited + [[x, y]]

    if (valueAtPos == 'E') validPaths += [newPath]
    if (valueAtPos == '+' || valueAtPos == 'S') {
        println "$x, $y passed $valueAtPos"
        testMove(x - 2, y, newPath)
        testMove(x + 2, y, newPath)

        testMove(x + 1, y + 1, newPath)
        testMove(x + 1, y - 1, newPath)

        testMove(x - 1, y + 1, newPath)
        testMove(x - 1, y - 1, newPath)
    }
}

//if (!validPath) invalid()
testMove(startAndEnd[0], startAndEnd[1], [])
println validPaths.join('\n')

//println validPath

def smallest = validPaths.collect {
    def path = ''
    def orintation = 1
    it.inject { old, goal ->
        def chr = map[goal[1]][goal[0]]
        def sub = [goal[0] - old[0], goal[1] - old[1]]
        def newOrin = [[-2, 0]: 0, [-1, -1]: 1, [1, -1]: 2, [2, 0]: 3, [1, 1]:4, [-1, 1]:5][sub]
        def diff = newOrin - orintation// 5L -5R
        def addedPath= ((diff==-5||diff==5)?' LR'[(int)diff/5]:['', 'R', 'RR', 'LL', 'L'][diff]) + 'F'//(diff == 0) ? '' : (diff > 0 ? 'R'*diff : 'L'*(-diff)) + 'F'
//        println "old:$old, goal:$goal chr $chr, orintation $orintation, sub:$sub newOrin $newOrin newPath $addedPath diff $diff"
        path += addedPath
        orintation = newOrin
        goal
    }
    path
}.min{it.size()}
//println "paths:\n${smallest.join('\n')}"
if (smallest)
    println "path $smallest"
else
    println "Invalid maze!"

3

C #을 600 574 바이트

완전한 프로그램, STDIN의 입력을 받아 STDOUT으로 출력.

편집 : 랩 처리에 1 바이트를 추가 한 버그가있었습니다 (주어진 테스트 사례에서 중단되지 않았습니다). 그래서 보완하기 위해 골프를 조금 더했습니다.

using Q=System.Console;struct P{int p,d;static void Main(){string D="",L;int w=0,W=0,o,n=1;for(;(L=Q.ReadLine())!=null;D+=L)w=(o=(L+="X").Length+1)>w?o:w;for(;W<D.Length;)D=D.Insert(W+1,"".PadLeft(D[W++]>87?w-W%w:0));P[]K=new P[W*6];var T=new string[W*6];P c=K[o=0]=new P{p=D.IndexOf('S')};for(System.Action A=()=>{if(c.p>=0&c.p<W&System.Array.IndexOf(K,c)<0&&D[c.p]%8>0){T[n]=T[o]+L;K[n]=c;n=D[c.p]==69?-n:n+1;}};o<n;o++){c=K[o];L="R";c.d=++c.d%6;A();L="L";c.d=(c.d+4)%6;A();L="F";c=K[o];c.p+=new[]{~w,1-w,2,1+w,w-1,-2}[c.d%6];A();}Q.WriteLine(n>0?"Invalid maze!":T[-n]);}}

지도를 읽고 시작 (하여 각 줄에 추가 하여 끝을 알 수 있으며 돌아가서 많은 공간을 추가하여 직사각형을 만들 수 있으며 오른쪽을 따라 한 줄의 공백으로 저장할 수 있습니다. 아래 설명 된대로 래핑 검사를 수행합니다.) 이 시점에서 사각형의 너비를 계산하고 맵의 전체 길이를 확인합니다.

다음으로, 너비 우선 검색을위한 모든 것을 초기화합니다. 검색에서 탐색해야하는 모든 상태를 저장하는 하나, 각 상태로가는 경로를 기록하는 두 개의 큰 배열이 생성됩니다. 헤드와 테일 포인터가 어딘가에 미리 설정되어 초기 상태가 적법한 배열에 추가됩니다. 모든 것은 1- 색인입니다.

그런 다음 꼬리가 머리에 닿을 때까지 반복하거나 최소한 머리에 충돌 한 것으로 보입니다 . 우리가 방문한 각 주에 대해 우리는 왼쪽이나 오른쪽으로 회전 한 같은 위치에 새로운 상태를 추가하려고 시도한 다음 앞으로 이동 한 상태를 추가하려고 시도합니다. 방향은 0"왼쪽"에 해당하는 초기 방향 (기본값은 ) 으로 색인됩니다 .

상태를 대기열에 넣으려고 할 때 오른쪽에 공백 열이 있기 때문에 상태가 바인드되어 있지만 랩핑되어 있지는 않습니다. "여기에있을 수 있습니까?" 확인하십시오 (공백이 허용되지 않습니다). 상태가 대기열에 있으면 E셀 에 있는지 확인 하고, 그렇다면 셀 헤드를 빼기로 설정하여 주 루프가 종료되고 프로그램의 마지막 줄에 인쇄하도록 지시합니다. 실패 메시지가 아닌 해당 경로를 확장합니다 (확장 할 상태가 부족한 경우 (꼬리가 머리에 충돌 함)).

using Q=System.Console;

// mod 8 table (the block of zeros is what we are after - it's everywhere we /can't/ go)
//   0 (space)
// O 0
// X 0
// S 3
// + 3
// E 5

struct P
{
    int p,d;
    static void Main()
    {
        // it's probably a bad thing that I have my own standards for naming this stupid read sequence by now
        string D="", // map
        L; // line/path char

        int w=0, // width
        W=0, // full length
        o, // next state to expand
        n=1; // next state to fill

        for(;(L=Q.ReadLine())!=null;D+=L) // read in map
            w=(o=(L+="X").Length+1)>w?o:w; // assertain max length (and mark end, and remove any need for wrap checking)

        // now we need to add those trailing spaces...
        for(;W<D.Length;)
            D=D.Insert(W+1,"".PadLeft(D[W++]>87?w-W%w:0)); // inject a load of spaces if we hit an X

        P[]K=new P[W*6]; // create space for due states (can't be more states than 6*number of cells)
        var T=new string[W*6]; // create space for routes (never done it this way before, kind of exciting :D)
        P c=K[o=0]=new P{p=D.IndexOf('S')}; // set first state (assignment to c is just to make the lambda shut up about unassigned variables)

        // run bfs
        for(

            System.Action A=()=> // this adds c to the list of states to be expanded, if a whole load of checks pass
            {
                if(//n>0& // we havn't already finished - we don't need this, because we can't win on the first turn, so can't win unless we go forward, which we check last
                   c.p>=0&c.p<W& // c is within bounds
                   System.Array.IndexOf(K,c)<0&& // we havn't seen c yet (the && is to prevent the following lookup IOBing)
                   D[c.p]%8>0) // and we can move here (see table at top of code)
                {
                    T[n]=T[o]+L; // store route
                    K[n]=c; // store state
                    n=D[c.p]==69?-n:n+1; // check if we are at the end, if so, set n to be negative of itself so we know, and can look up the route (otherwise, increment n)
                }
            }

            ;o<n;o++) // o<n also catches n<0
        {
            c=K[o]; // take current
            L="R"; // say we are going right
            c.d=++c.d%6; // turn right
            A(); // go!

            L="L"; // say we are going left
            c.d=(c.d+4)%6; // turn left
            A(); // go!

            L="F"; // say we - you get the picture
            c=K[o];
            c.p+=new[]{~w,1-w,2,1+w,w-1,-2}[c.d%6]; // look up direction of travel (~w = -w-1)
            A();
        }

        // check if we visited the end
        Q.WriteLine(n>0?"Invalid maze!":T[-n]); // if n<0, then we found the end, so spit out the corresponding route, otherwise, the maze is invlida
    }
}

이 사이트의 대부분의 그래프 검색과 마찬가지로 C # 구조체를 잘 사용하고 있으며 기본적으로 리터럴 값으로 비교합니다.


2

파이썬 2, 703 바이트

다른 두 버전만큼 좋지는 않지만 적어도 haha로 작동합니다. M미로로 설정 합니다.

나는 미로를 해결 한 경험이 없기 때문에 무차별 대입 접근 방식을 사용합니다. 가장 짧은 것부터 회전을 계산 한 다음 그 중에서 가장 짧은 결과를 선택합니다.

z=zip;d=z((-1,1,-2,2,-1,1),(-1,-1,0,0,1,1));E=enumerate;D={};t=tuple;o=list;b=o.index
for y,i in E(M.split('\n')):
 for x,j in E(o(i)):
  c=(x,y);D[c]=j
  if j=='S':s=c
  if j=='E':e=c
def P(s,e,D,p):
 p=o(p);p.append(s);D=D.copy();D[s]=''
 for i in d:
  c=t(x+y for x,y in z(s,i))
  if c not in p and c in D:
   if D[c]=='E':L.append(p+[c])
   if D[c]=='+':P(c,e,D,p)
def R(p):
 a=[0,1,3,5,4,2];h=d[0];x=p[0];s=''
 for c in p[1:]:
  r=t(x-y for x,y in z(c,x));n=0
  while h!=r:n+=1;h=d[a[(b(a,b(d,h))+1)%6]]
  s+=['L'*(6-n),'R'*n][n<3]+'F';x=t(x+y for x,y in z(x,h))
 return s
L=[];P(s,e,D,[])
try:l=len(min(L))
except ValueError:print"Invalid maze!"
else:print min([R(i)for i in L if len(i)==l],key=len)

지저분한 언 골프 버전 :

maze = """
     0 0 0 0
    0 + 0 + 0
   0 0 0 + + 0
  0 + 0 + 0 + 0
 0 0 + + 0 0 + 0
0 0 + 0 + 0 0 + 0
 E 0 + 0 0 + + 0 
  + + 0 + 0 + 0
   0 0 0 0 0 +
    + 0 + + +
     0 S 0 0
     """
directions = [(-1, -1), (1, -1),
              (-2, 0), (2, 0),
              (-1, 1), (1, 1)]


maze_dict = {}
maze_lines = maze.split('\n')
for y, row in enumerate(maze_lines):
    if row:
        for x, item in enumerate(list(row)):
            coordinates = (x, y)
            maze_dict[coordinates] = item
            if item == 'S':
                start = coordinates
            elif item == 'E':
                end = coordinates

list_of_paths = []


def find_path(start, end, maze_dict, current_path=None):
    if current_path is None:
        current_path = []
    current_path = list(current_path)
    current_path.append(start)
    current_dict = maze_dict.copy()
    current_dict[start] = '0'

    for direction in directions:
        new_coordinate = (start[0] + direction[0], start[1] + direction[1])

        if new_coordinate in current_path:
            pass

        elif new_coordinate in current_dict:
            if current_dict[new_coordinate] == 'E':
                list_of_paths.append(current_path + [new_coordinate])
                break
            elif current_dict[new_coordinate] == '+':
                find_path(new_coordinate, end, current_dict, current_path)


find_path(start, end, maze_dict)


def find_route(path):

    heading_R = [0, 1, 3, 5, 4, 2]
    heading = (-1, -1)
    current_pos = path[0]
    current_heading = directions.index(heading)
    output_string = []
    for coordinate in path[1:]:
        required_heading = (coordinate[0] - current_pos[0], coordinate[1] - current_pos[1])

        count_R = 0
        while heading != required_heading:
            count_R += 1
            heading_index = directions.index(heading)
            heading_order = (heading_R.index(heading_index) + 1) % len(heading_R)
            heading = directions[heading_R[heading_order]]

        if count_R:
            if count_R > 3:
                output_string += ['L'] * (6 - count_R)
            else:
                output_string += ['R'] * count_R

        output_string.append('F')
        current_pos = (current_pos[0] + heading[0], current_pos[1] + heading[1])
    return ''.join(output_string)


routes = []
try:
    min_len = len(min(list_of_paths))
except ValueError:
    print "Invalid maze!"
else:
    for i in list_of_paths:
        if len(i) == min_len:
            routes.append(find_route(i))

    print 'Shortest route to end: {}'.format(min(routes, key=len))

당신은 if heading != required_heading: while heading != required_heading: 단지 다음으로 대체 할 수 있습니다while heading != required_heading:
J Atkin

하하 덕분에 그래, 나는 golfed 버전을 할 때 난 그냥 몇 자 면도로 관리 한 이후, 단지 내가 지금 조금을 다하겠습니다, 원래의 코드를 업데이트하지 않았다는 것을 포함하여 몇 가지를 발견했던
피터

좋은! (15 자 작성)
J Atkin

<이것은 인식 할 수없는 HTML 태그이므로 SE는 비슷하지 않습니다.>
CalculatorFeline
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.