그 뱀은 어디로가요?


35

다음과 같은 수의 열과 행으로 2 차원 배열을 취하는 함수 (가능한 한 적은 바이트 사용)를 작성하십시오.

  • 0 빈 블록을 나타내고
  • 1 뱀 블록을 나타냅니다.

이 함수는 뱀이 이동 한 가능한 경로 수를 반환해야합니다.

예 1 :

입력:

[
  [1,1,1,1,1],
  [0,0,0,0,1],
  [0,0,0,0,1],
]

산출: 2

위의 예 2에서 답은 다음 중 하나이므로 함수가 반환됩니다 .

여기에 이미지 설명을 입력하십시오

예 2 :

입력:

[
  [1,1,1,1],
  [0,0,1,1],
  [0,0,1,1],
]

산출: 6

이 예에서 6답은 다음 중 하나이므로 함수가 반환됩니다 .

여기에 이미지 설명을 입력하십시오

노트 :

입력을 평가할 때 다음을 가정 할 수 있습니다.

  • 열을 나타내는 배열의 크기는 항상 동일하므로 배열은 사각형입니다.
  • 하나 이상의 유효한 경로가 있습니다.
  • 뱀은 가장자리를 통과 할 수 없습니다 (일부 버전의 뱀에서 발생할 수 있음).
  • 뱀은 항상 최소 2 개의 블록을 가질 것입니다.
  • 뱀은 대각선으로 움직일 수 없습니다.
  • 경로가 지시됩니다. (따라서 다른 위치에서 끝나는 두 경로가 동일하게 보이지 않으면 동일한 경로가 아니므로 총계에 합산됩니다)

13
PPCG에 오신 것을 환영합니다! 좋은 첫 번째 도전.
Laikoni

5
사소한 메모 : 뱀에는 항상 2 개 이상의 블록이 있으므로 "항상 하나 이상의 행과 하나의 열이 있어야합니다"는 중복됩니다.
Stewie Griffin

2
제안 된 테스트 사례 : @StewieGriffin 및 [[0,0,1,1],[0,0,1,1],[0,0,1,1]]. 대부분의 답변은 16 줄, 그러나 사람은 15 제공
케빈 Cruijssen

2
지금까지의 모든 사람 (나를 포함하여)은 서로 다른 위치에서 끝나는 두 경로가 같지만 정확하게 동일하게 보이는 것은 동일한 경로 가 아니라고 가정 한 것 같습니다. 나는 이것이 명시 적으로 지정되어야한다고 생각합니다.
Arnauld

2
@Arnauld-맞습니다. 서로 다른 위치에서 끝나지만 정확히 똑같이 보이는 두 개의 경로 는 같은 경로가 아니므로 합계에 합산됩니다. 귀하의 예에서 내가 실수하지 않으면 총계는 16이어야합니다-지금 정확하게 계산할 수는 없지만 요점을 알 수 있습니다
Adelin

답변:


11

Wolfram Language (Mathematica) , 16 + 83 = 99 바이트

라이브러리 가져 오기 문 (16 바이트) :

<<Combinatorica`

실제 함수 본문 (83 바이트) :

Length@HamiltonianCycle[MakeGraph[#~Position~1~Join~{1>0},##||Norm[#-#2]==1&],All]&

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


질문은 그래프에서 해밀턴 경로의 수를 묻는 것입니다.

그러나 (어떤 이유로 든) HamiltonianPath함수는 실제로 유 방향 그래프 ( example ) 와 함께 작동하지 않습니다 . 따라서이 Mathematica.SE 질문에 설명 된 해결 방법을 사용했습니다 .

  • True다른 모든 꼭짓점에 연결된 꼭짓점 ( )을 추가하십시오 .
  • 결과 그래프에서 해밀턴 사이클 수를 계산합니다.

그래프는 MakeGraph부울 함수를 사용하여 (성가 적으로 직접 내장되어 있지 않음)를 사용하여 구성됩니다.이 함수 는 인수 중 하나가 있거나 두 정점 사이의 거리 가 인 경우에만 ##||Norm[#-#2]==1&반환 True합니다 .True1


Tr[1^x]대신 사용할 수 없습니다 Length@x, 그리고 <2대신 사용할 수 없습니다 ==1.


HamiltonianPath함수 본문이 84 바이트 (현재 제출보다 1 바이트 더 큼) 와 함께 그래프가 방향이 지정되지 않은 경우 사용할 수 있습니다 .

Length@HamiltonianPath[MakeGraph[#~Position~1,Norm[#-#2]==1&,Type->Undirected],All]&

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


10

자바 스크립트 (ES6) 154 134 바이트

m=>m.map((r,Y)=>r.map(g=(_,x,y,r=m[y=1/y?y:Y])=>r&&r[x]&&[-1,0,1,2].map(d=>r[r[x]=0,/1/.test(m)?g(_,x+d%2,y+~-d%2):++n,x]=1)),n=0)|n/4

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

어떻게?

방법

가능한 각 셀에서 시작하여 행렬을 플러딩하여 도중에 모든 셀을 지 웁니다. 행렬에 1 이 더 이상 포함되지 않을 때마다 가능한 경로 수 n 을 증가시킵니다 .

마지막 셀에서 선택한 방향으로 인해 각 유효한 경로는 4 번 계산되며 실제로는 중요하지 않습니다. 따라서 최종 결과는 n / 4 입니다.

재귀 함수

다음 과 같이 두 번째 map () 의 콜백에서 재귀 함수 g () 를 호출하는 대신 ...

m=>m.map((r,y)=>r.map((_,x)=>(g=(x,y,r=m[y])=>...g(x+dx,y+dy)...)(x,y)))

... 재귀 함수 g ()map () 의 콜백 으로 직접 정의합니다 .

m=>m.map((r,Y)=>r.map(g=(_,x,y,r=m[y=1/y?y:Y])=>...g(_,x+dx,y+dy)...))

y=1/y?y:Y초기 값 y 를 설정하는 데 필요한 다소 긴 공식에도 불구하고 전체적으로 2 바이트를 절약합니다.

주석이 달린 코드

m =>                           // given the input matrix m[][]
  m.map((r, Y) =>              // for each row r[] at position Y in m[][]:
    r.map(g = (                //   for each entry in r[], use g() taking:
      _,                       //     - the value of the cell (ignored)
      x,                       //     - the x coord. of this cell
      y,                       //     - either the y coord. or an array (1st iteration),
                               //       in which case we'll set y to Y instead
      r = m[y = 1 / y ? y : Y] //     - r = the row we're currently located in
    ) =>                       //       (and update y if necessary)
      r && r[x] &&             //     do nothing if this cell doesn't exist or is 0
      [-1, 0, 1, 2].map(d =>   //     otherwise, for each direction d,
        r[                     //     with -1 = West, 0 = North, 1 = East, 2 = South:
          r[x] = 0,            //       clear the current cell
          /1/.test(m) ?        //       if the matrix still contains at least one '1':
            g(                 //         do a recursive call to g() with:
              _,               //           a dummy first parameter (ignored)
              x + d % 2,       //           the new value of x
              y + ~-d % 2      //           the new value of y
            )                  //         end of recursive call
          :                    //       else (we've found a valid path):
            ++n,               //         increment n
          x                    //       \_ either way,
        ] = 1                  //       /  do r[x] = 1 to restore the current cell to 1
      )                        //     end of map() over directions
    ),                         //   end of map() over the cells of the current row
    n = 0                      //   start with n = 0
  ) | n / 4                    // end of map() over the rows; return n / 4

10

젤리 , 12 11 바이트

ŒṪŒ!ạƝ€§ÐṂL

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


설명.

ŒṪ               Positions of snake blocks.
  Œ!             All permutations.
                 For each permutation:
    ạƝ€             Calculate the absolute difference for each neighbor pair
       §            Vectorized sum.
                 Now we have a list of Manhattan distance between snake
                    blocks. Each one is at least 1.
        ÐṂL      Count the number of minimum values.
                    Because it's guaranteed that there exists a valid snake,
                    the minimum value is [1,1,1,...,1].

새로운 기능은 매우 유용합니다.
user202729

바이트를 저장하는 §ỊML대신 어떻습니까 §ỊP€S-작동해야한다고 생각합니까?
Jonathan Allan

... 또는 §ÐṂL조금 더 빠릅니다.
Jonathan Allan

@JonathanAllan 결과가 0이 아닌 경우에만 작동합니다.
user202729

@JonathanAllan 그래서 실제로 작동합니다.
user202729

8

파이썬 (2) , 257 (246) 241 234 233 227 214 210 바이트

lambda b:sum(g(b,i,j)for j,l in e(b)for i,_ in e(l))
e=enumerate
def g(b,x,y):d=len(b[0])>x>-1<y<len(b);c=eval(`b`);c[d*y][d*x]=0;return d and b[y][x]and('1'not in`c`or sum(g(c,x+a,y)+g(c,x,y+a)for a in(1,-1)))

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


저장되었습니다

  • Kevin Cruijssen 덕분에 -8 바이트
  • user202729 덕분에 -14 바이트


1
직업에 맞는 언어?
Neil


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.