거북이가 포털을 찾습니다


30

거북이는 음식을 얻기 위해 격자를 따라 움직입니다. 그는 그가 거기에 도착하는 데 얼마나 많은 움직임이 필요한지 알고 싶어합니다.

또한 속도가 느리기 때문에 자신의 영역을 중심으로 텔레 포터를 설치하여 경로가 짧아지면 활용할 수 있습니다. 또는 경로가 길어지면 피하십시오.

거북이 만나기

🐢

그리드상의 거북이 삶 ... 거북이 인접한 정사각형으로 이동할 수

XXXXXXXXXXXX🐢XXXXXXXXXXXX
XXXXXXXX🐢XXXXXXXX

그러나 거북이는

X🌄XXXXXX🌄🐢XX🌄XX🌄XXX

거북이는 딸기를 먹고 싶어서 딸기에 도착하는데 얼마나 걸리는지 알고 싶습니다. 이 예제는 거북이 걸릴 것 회전이 다행히도, 거북이가 순간 이동기를 찾았습니다! 그리드에는 서로 매핑되는 두 개의 텔레포트가 있습니다. 텔레 포터를 밟으면 거북이가 즉시 해당 텔레 포터로 이동합니다. 텔레 포터는 매우 불안정하여 한 번 사용한 후에는 사라져 더 이상 사용할 수 없습니다.

X🌄🍓🐢🌄XX🌄XXXX
5
X🌄🍓🌄🌄XX
🔵🌄🍓🐢🌄🔴X🌄XXXX
거북이가 두 번 위로 올라가는 것이 더 빨라졌습니다. 이제 거북이 최단 경로는2
🔵🌄🐢🌄🔴X🌄XXXX

도전

초기 그리드 구성 출력이 주어지면 거북이가 딸기에 도달하는 데 걸리는 이동 횟수입니다.

규칙

  • 입력 그리드에 솔루션이 있다고 가정 할 수 있습니다

  • 각 그리드는 하나 strawberry와 둘 portals그리고 하나만 가질 것입니다turtle

  • 입력 그리드는 편리한 형식으로 입력 할 수 있습니다

  • 당신 teleporters은 일회용 아이템으로 취급해야 합니다

  • 거북이가 teleporter사각형으로 이동하는 차례 는 이미 해당에 teleporter있습니다. 그는 절대로 움직이지 않고 teleporter계속 움직입니다.

  • 최단 경로는 포털을 사용할 필요가 없습니다.

  • 거북이는 산 타일로 들어갈 수 없습니다

  • 당신은 표현하기 위해 어떤 ASCII 문자 또는 정수를 사용할 수 있습니다 mountains, turtle, empty grid square,strawberry

  • teleporter쌍 을 나타 내기 위해 동일한 문자 또는 두 개의 다른 ASCII 문자 또는 정수를 사용할 수 있습니다

  • 그리드는 동일한 최단 경로 길이를 가진 둘 이상의 경로를 가질 수 있습니다

  • 이것은

규칙에 대한 설명

  • teleporters일회용 아이템으로 취급해야 합니다.

추론 :

🐢X🔵X🍓🌄🌄🌄🌄🌄🔴XXXX

포털을 두 번 입력하고 종료해야만 해결할 수 있습니다. 이 설명을 할 때 두 솔루션 모두 단일 사용 또는 이전에 사용 된 사각형을 시도 할 이유가 없다고 가정하여 작동했습니다. 열심히 일한 솔루션을 깨뜨리지 않기 위해 이것이 가장 좋은 방법이었습니다. 따라서 이것은 유효하지 않은 그리드로 간주됩니다.

목록으로 형식화 된 테스트 케이스

[ ['T', 'X', 'X', 'S', 'X'], ['X', 'X', 'X', 'X', 'X'], ['X', 'X', 'X', 'X', 'X'] ] --> 3
[ ['T', 'M', 'X', 'S', 'X'], ['X', 'M', 'X', 'X', 'X'], ['O', 'X', 'X', 'X', 'O'] ] --> 4
[ ['T', 'M', 'X', 'S', 'O'], ['O', 'M', 'X', 'X', 'X'], ['X', 'X', 'X', 'X', 'X'] ] --> 2
[ ['T', 'M', 'X', 'S', 'X'], ['O', 'M', 'X', 'X', 'X'], ['O', 'X', 'X', 'X', 'X'] ] --> 4
[ ['T', 'M', 'S', 'X', 'O'], ['X', 'M', 'M', 'M', 'M'], ['X', 'X', 'X', 'X', 'O'] ] --> 7
[ ['T', 'X', 'X', 'S', 'X'], ['O', 'M', 'M', 'M', 'X'], ['X', 'X', 'O', 'X', 'X'] ] --> 3

인간을위한 형식의 테스트 케이스

T X X S X
X X X X X
X X X X X --> 3

T M X S X
X M X X X
O X X X O --> 4

T M X S O
O M X X X
X X X X X --> 2

T M X S X
O M X X X
O X X X X --> 4

T M S X O
X M M M M
X X X X O --> 7

T X X S X
O M M M X
X X O X X --> 3

크레딧

설계 및 구조 : Arnauld의 배고픈 마우스

제안 된 과제 편집 조언 : kamil-drakari , beefster

일반 편집 조언 : okx nedla2004 mbomb007


2
텔레 포터를 사용하면 시간이 더 걸리는 테스트 케이스를 추가하는 것이 좋습니다.
Okx

@Okx 지금 생성 및 추가.
akozi

고마워요
akozi

1
@ xnor 나는 이것이 원래의 규칙과 추상화 될 수 있다고 생각합니다. 따라서 일회용 아이템을 포탈하는 것이 더 낫습니까?
akozi

1
관련이 있다고 생각합니다.
찰리

답변:


13

자바 스크립트 (ES7),  140 139  138 바이트

다음 맵핑을 사용하여 입력을 정수 행렬로 가져옵니다.

  • 1 = 🔵 (모든 포털)
  • 0 = (빈)X
  • 1 = 🌄 (산)
  • 2 = 🐢 (거북이)
  • 3 = 🍓 (딸기)
m=>(R=g=(t,X,Y,i)=>m.map((r,y)=>r.map((v,x)=>r[(u=0,t?v-t:(x-X)**2+(y-Y)**2<3?v-3?~v?v:u--:R=R<i?R:i:1)||g(u,x,y,u-~i,r[x]=1),x]=v)))(2)|R

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

방법?

기본 재귀 검색 기능 는 보드에서 특정 타일 를 찾거나 ( 호출 된 경우 현재 위치 에서 도달 할 수있는 타일 을 찾을 수 있습니다 .gtt0(x,y)(X,Y)

에서 현재 경로의 길이를 추적 하고 거북이가 딸기를 찾을 때마다 최상의 결과 을 업데이트합니다 .iRmin(R,i)

거북이의 시작 위치를 찾기 위해 로 먼저 호출됩니다 .t=2

포털에 도달하면 거북이 다른 포털로 순간 이동되도록 호출됩니다 . 우리는 그러한 반복 동안 증가시키지 않습니다 .t=1i

방문한 각 타일은 같은 경로에서 같은 타일에서 거북이가 두 번 움직이지 않도록 임시로 산으로 설정됩니다. 막 다른 곳에 갇히게되면 재귀는 단순히 을 업데이트하지 않고 멈 춥니 다 .R

댓글

m => (                        // m[] = input matrix
  R =                         // initialize R to a non-numeric value
  g = (t, X, Y, i) =>         // g = recursive search function taking t = expected tile,
                              //     (X, Y) = current coordinates, i = path length
    m.map((r, y) =>           // for each row r[] at position y in m[]:
      r.map((v, x) =>         //   for each tile v at position x in r[]:
        r[                    //     this statement will eventually restore r[x] to v
          ( u = 0,            //     u = next tile to look for, or 0 if none
            t ?               //     if we're looking for a specific tile:
              v - t           //       test whether we've found it
            :                 //     else:
              (x - X) ** 2 +  //       compute the squared Euclidean distance between
              (y - Y) ** 2    //       (x, y) and (X, Y)
              < 3 ?           //       if it's less than 3 (i.e. reachable from (X, Y)):
                v - 3 ?       //         if v is not equal to 3:
                  ~v ?        //           if v is not equal to -1:
                    v         //             test if v = 0
                  :           //           else (v = -1):
                    u--       //             set u = -1 to find the other portal
                :             //         else (v = 3):
                  R = R < i ? //           we've found the strawberry: set R = min(R, i)
                      R : i   //
              :               //       else (this tile can't be reached):
                1             //         yield 1
          ) ||                //     if the above result is falsy:
          g(                  //       do a recursive call:
            u,                //         t = u
            x, y,             //         move to (x, y)
            u - ~i,           //         unless u is set to -1, increment i
            r[x] = 1          //         set this tile to a mountain
          ),                  //       end of recursive call
          x                   //     restore r[x] ...
        ] = v                 //     ... to v
    ))                        // end of both map() loops
)(2) | R                      // initial call to g with t = 2; return R

1
"방문한 각 타일은 거북이가 같은 타일에서 두 번 움직이지 않도록 임시로 산으로 설정되어 있습니다." 좋은 답변, 그리고 항상 설명과 함께 답변을 주셔서 감사합니다 :)
akozi

5

파이썬 2 , 441 431 341 바이트

from itertools import*
G=input()
W=len(G[0])
H=len(G)
A=[0]*5
E=enumerate
for y,r in E(G):
 for x,C in E(r):A[C]=[x,y]
for L in count():
 for M in product(*[zip('UDLR'*2,'LRDU    ')]*L):
  x,y=A[0]
  for m in M:
    x+='R'in m;x-='L'in m;y+='D'in m;y-='U'in m
    if(x,y)==A[3]:x,y=A[2]
    if 1-(W>x>-1<y<H)or G[y][x]>3:break
  if[x,y]==A[1]:exit(L)

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

문자 대신 숫자를 사용하지만 (Quintec 덕분에) 텔레 포터 대상에 대해 별도의 값을 사용하여 목록으로 입력하십시오. 이러한 큰 들여 쓰기는 Stack Exchange에서 제거 할 경우 탭 문자 여야합니다. 이것이 훨씬 짧아 질 수 있다고 생각하기 때문에 어떤 팁이나 아이디어라도 특히 환영 합니다.

내 프로그램에 사용 된 숫자에 대한 도전에 사용 된 문자 표는 아래에 있지만 이 프로그램 을 사용할 수도 있습니다 .

Challenge | My program
T         | 0
S         | 1
E         | 2
O         | 3
M         | 4
X         | -1

입력을 문자 사용에서 숫자로 변경하여 Quintec 덕분에 -10 바이트.

-Jonathan Frech, ElPedro 및 Jonathan Allan 덕분에 많은 바이트가있었습니다.


2
각 객체가 문자열 문자 대신 숫자로 표시되는 목록을 가져 와서 몇 개의 문자를 줄일 수 있습니다.
Quintec

@Quintec 감사합니다. 방향에 대해 동일한 작업을 수행하고 싶지만 대각선은 별도로 수행해야합니다. 그래도 여전히 숫자로 옮길 수 있습니다.
nedla2004

1
@ElPedro AHHA I 오프 4를 면도 할 수 같은
조나단 앨런

1
... 그리고 356에
Jonathan Allan

2
@JonathanAllan 및 ElPedro 및 Jonathan French. 여러분 모두의 훌륭한 팁과 함께 제가 생각해 낸 몇 가지 사항을 함께 추가했습니다. (많은 지연 후)
nedla2004

2

파이썬 2 391 397 403 422 바이트

M=input()
from networkx import*
a=b=c=d=0
N,h,w,S=[-1,0,1],len(M),len(M[0]),[]
for i in range(h):
 for j in range(w):
  I,m=(i,j),M[i][j]
  if m>7:c,d=a,b;a,b=I
  if m<0:Z=I
  if m==5:F=I
  S+=[I+I]
S+=[(a,b,c,d),(c,d,a,b)]
print len(shortest_path(from_edgelist([((A+p,B+q),(C,D))for A,B,C,D in S for p,q in[(p,q)for p in N for q in N]if-1<A+p<h and-1<B+q<w and M[C][D]*M[A+p][B+q]]),Z,F))-1

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

문제는 그래프로 변환되며 해결책은 딸기의 거북이에서 가장 짧은 경로를 찾는 것입니다.

Challenge | This code
T         | -1
S         |  5
O         |  8
M         |  0
X         |  1
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.