끈을 벗기다


58

일반 문자열은 다음과 같습니다.

Hello,IAmAStringSnake!

그리고 끈 뱀은 다음과 같습니다.

Hel         
  l      rin
  o,IAmASt g
           S
       !ekan

당신의 작업

현 뱀은 위험하므로 현 뱀을 입력으로 사용하여 일반 현으로 출력하는 프로그램을 만들어야합니다.

사양

  • 입력은 여러 줄 문자열 또는 문자열 배열 일 수 있습니다.
  • 입력의 각 라인은 사각형 격자를 형성하기 위해 공백으로 채워집니다.
  • 뱀의 캐릭터는 게임 스네이크에서와 같이 위, 아래, 왼쪽 또는 오른쪽의 인접한 캐릭터에만 연결할 수 있습니다. 그들은 대각선으로 갈 수 없습니다.
  • 뱀 캐릭터는 뱀의 다른 부분에 절대로 인접하지 않으며 연결된 문자 만 있습니다.
  • 문자열의 첫 번째 문자는 입력 그리드의 왼쪽 위 모서리에서 맨해튼 거리 가 가장 짧은 끝 문자입니다 (즉, 뱀이 끝 문자에서 왼쪽 위까지 직접 이동하는 데 필요한 최소 이동 횟수) 모서리). 양쪽 끝이 같은 거리를 가지지 않습니다.
  • 문자열은 코드 포인트 33과 126 사이에 ASCII 문자를 포함 할 수 있습니다 (공백 또는 줄 바꿈 없음).
  • 문자열은 2 ~ 100 자 사이입니다.
  • 바이트 단위의 최단 코드가 이깁니다.

테스트 사례

(입력 그리드 다음에 출력 문자열)

Hel         
  l      rin
  o,IAmASt g
           S
       !ekan

Hello,IAmAStringSnake!

----------

Python

Python

----------

P  ngPu  Code 
r  i  z  d  G 
o  m  z  n  o 
gram  lesA  lf

ProgrammingPuzzlesAndCodeGolf

----------

   ~ zyx tsr XWVUTSR
   }|{ wvu q Y     Q
!          p Z `ab P
"#$ 6789:; o [ _ c O
  % 5    < n \]^ d N
('& 432  = m     e M
)     1  > lkjihgf L
*+,-./0  ?         K
         @ABCDEFGHIJ

!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

----------

  tSyrep    
  r    p    
  in Sli    
   g    Sile
   Snakes  n
Ser      ylt
a eh   ilS  
fe w   t    
   emo h    
     Sre    

SlipperyStringSnakesSilentlySlitherSomewhereSafe

20
재미있는 사실 : 링크 된 Wikipedia 기사에 따르면 맨하탄 거리는 뱀 거리라고도합니다!
user81655

hastebin.com/asugoropin.vbs 와 같은 입력 이 정확합니까?
FliiFe

@FliiFe 아니요, 뱀의 일부는 서로 옆에있을 수 없습니다. 왜냐하면 이것이 일어날 때 뱀이 어디로 가고 있는지 항상 알 수는 없기 때문입니다 (그리고 도전이 훨씬 더 어려워 질 것입니다). 이것을 설명하기 위해 사양에 라인을 추가했습니다.
user81655

입력이 2 차원 배열 일 수 있습니까 (즉, 각 문자를 요소로)?
FliiFe

29
분명히이 퍼즐은 파이썬에서 답이 필요합니까?
abligh

답변:


11

APL, 55 바이트

{⍵[1↓(⊂0 0){1<⍴⍵:⍺,∆[⊃⍋+/¨|⍺-∆]∇∆←⍵~⍺⋄⍺}(,⍵≠' ')/,⍳⍴⍵]}

이 함수는 문자열 뱀이 포함 된 문자 행렬을받습니다.

예:

      s1 s2 s3
┌────────────┬──────────────┬────────────────────┐
│Hel         │P  ngPu  Code │   ~ zyx tsr XWVUTSR│
│  l      rin│r  i  z  d  G │   }|{ wvu q Y     Q│
│  o,IAmAst g│o  m  z  n  o │!          p Z `ab P│
│           S│gram  lesA  lf│"#$ 6789;: o [ _ c O│
│       !ekan│              │  % 5    < n \]^ d N│
│            │              │('& 432  = m     e M│
│            │              │)     1  > lkjighf L│
│            │              │*+,-./0  ?         K│
│            │              │         @ABCDEFGHIJ│
└────────────┴──────────────┴────────────────────┘
      ↑ {⍵[1↓(⊂0 0){1<⍴⍵:⍺,∆[⊃⍋+/¨|⍺-∆]∇∆←⍵~⍺⋄⍺}(,⍵≠' ')/,⍳⍴⍵]} ¨ s1 s2 s3 
Hello,IAmAstringSnake!                                                                        
ProgrammingPuzzlesAndCodeGolf                                                                 
!"#$%&'()*+,-./0123456789;:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefhgijklmnopqrstuvwxyz{|}~

설명:

  • (,⍵≠' ')/,⍳⍴⍵: 공백이 아닌 모든 좌표를 가져옵니다.
  • (⊂0 0): (0,0)에서 시작합니다 (잘못된 좌표).
  • {... }: 위치와 뱀이 주어진 뱀을 따라갑니다.
    • 1<⍴⍵:: 둘 이상의 요소가 남아있는 경우 :
      • ∆←⍵~⍺: 뱀에서 현재 위치를 제거하여 저장하십시오 .
      • +/¨|⍺-∆: 현재 위치와 나머지 뱀의 각 지점 사이의 거리를 찾습니다.
      • ∆[⊃⍋...]`: 뱀에서 가장 가까운 지점을 찾으십시오.
      • : 가장 가까운 점을 새 현재 점으로, 짧게 한 뱀을 새 뱀으로하여 함수를 다시 실행하십시오.
      • ⍺,: 그 결과에 현재 위치를 추가
    • ⋄⍺: 그렇지 않으면 그냥 현재 위치를 반환
  • 1↓: 결과에서 첫 번째 항목을 삭제합니다 ((0,0) 위치).
  • ⍵[... ]: elements에서 해당 요소를 순서대로 가져옵니다.

24

JavaScript (ES6) + SnakeEx , 176 바이트

a=b=>snakeEx.run("s{A}:<+>([^ ]<P>)+",b).reduce((c,d)=>(e=c.marks.length-d.marks.length)>0?c:e?d:c.x+c.y>d.x+d.y?d:c).marks.reduce((c,d,e,f)=>e%2?c+b.split`\n`[d][f[e-1]]:c,"")

SnakeEx를 기억하십니까? 나도 아니기 때문에 좋다! 골프 제안을 환영합니다.


19

MATL , 80 바이트

수정을 위해 @LevelRiverSt에게 감사합니다

32>2#fJ*+X:4Mt1Y6Z+l=*2#fJ*+ttXjwYj+K#X<)wt!"tbb6#Yk2#)yw]xxvtXjwYjqGZy1)*+Gw)1e

입력은 행으로 구분 된 char의 2D 배열입니다 ;. 이 형식의 테스트 사례는

['Hel         ';'  l      rin';'  o,IAmASt g';'           S';'       !ekan']
['Python']
['P  ngPu  Code ';'r  i  z  d  G ';'o  m  z  n  o ';'gram  lesA  lf']
['   ~ zyx tsr XWVUTSR';'   }|{ wvu q Y     Q';'!          p Z `ab P';'"#$ 6789:; o [ _ c O';'  % 5    < n \]^ d N';'(''& 432  = m     e M';')     1  > lkjihgf L';'*+,-./0  ?         K';'         @ABCDEFGHIJ']
['  tSyrep    ';'  r    p    ';'  in Sli    ';'   g    Sile';'   Snakes  n';'Ser      ylt';'a eh   ilS  ';'fe w   t    ';'   emo h    ';'     Sre    ']

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

설명

각 비 공백 문자의 좌표는 복소수로 표시됩니다. 각 현재 문자에 ​​대해 다음 문자는 가장 가까운 문자 (복합 좌표의 최소 절대 차이)로 얻습니다.

초기 문자를 판별하려면 두 개의 엔드 포인트를 찾아야합니다. 이것은 다음과 같이 수행됩니다. 엔드 포인트는 정확히 하나의 비 공간 이웃을 가진 비 공간 문자입니다. 이웃의 수는 적합한 마스크와의 2D 컨볼 루션에 의해 얻어진다. 초기 점은 복소 좌표가 실수 부와 허수 부의 합계를 갖는 끝점입니다. 즉 맨해튼에서 복소수 0과 가장 가까운 거리이거나 왼쪽 상단의 복소수 좌표 인 1 + 1j와 같습니다.

32>      % Take input as 2D char array. Compute 2D array with true for nonspace,
         % false for space
2#f      % Arrays of row and column indices of nonspaces
J*+      % Convert to complex array. Real part is row, imaginary part is column
X:       % Convert to column array
4Mt      % Push arrays of zeros and ones again. Duplicate
1Y6      % Push array [0 1 0; 1 0 1; 0 1 0]. Used as convolution mask to detect
         % neighbours that are nonspace
Z+       % 2D convolution with same size as the input
1=       % True for chars that have only one neighbour (endpoints)
*        % Multiply (logical and): we want nonspaces that are endpoints
2#fJ*+   % Find complex coordinates (as before)
ttXjwYj  % Duplicate. Take real and imaginary parts
+        % Add: gives Manhattan distance to (0,0)
K#X<     % Arg min. Entry with minimum absolute value has least Manhattan
         % distance to (0,0), and thus to (1,1) (top left corner)
)        % Apply as an index, to yield complex coordinate of initial endpoint
wt!      % Swap, duplicate, transpose.
         % The stack contains, bottom to top: complex coordinates of initial
         % endpoint, column array with all complex coordinates, row array of all
         % coordinates. The latter is used (and consumed) by the next "for"
         % statement to generate that many iterations
"        % For loop. Number of iterations is number of nonspaces
  tbb    %   Duplicate, bubble up twice (rearrange is stack)
  6#Yk   %   Find which of the remaining points is closest to current point. This
         %   is the next char in the string
  2#)    %   Remove the point with that index from the array of complex
         %   coordinates. Push that point and the rest of the array
  yw     %   Duplicate extracted point, swap
]        % End for
xx       % Delete top two elements of the stack
v        % Concatenate all stack contents into a column array. This array
         % contains the complex coordinates of chars sorted to form the string
tXjwYj   % Extract real part and imaginary part
GZy1)    % Number of rows of input. Needed to convert to linear index
*+       % Convert rows and columns to linear index
Gw       % Push input below that
)        % Index to get the original chars with the computed order
1e       % Force the result to be a row array (string). Implicitly display

앞으로 설명이 나올 것이라고 생각합니까?
Matt

@Matt Sure ... 다음날 나중에 :-)
Luis Mendo

설명 @ 매트 추가
루이스 Mendo

The initial point is the endpoint whose complex coordinate has the least absolute value주의 : 유클리드 거리! = 맨해튼 거리. 예를 들어, 점 7 + 7j는 유클리드 거리가 9.8994이고 맨해튼 거리가 14입니다. 10j는 유클리드 거리만큼 멀지 만 맨해튼 거리만큼 상당히 더 가깝습니다. 그 외에는 훌륭한 개념입니다!
Level River St

@LevelRiverSt 감사합니다! 수정
루이스 멘도

14

C 198 190 179 180 181 바이트

편집 : user81655의 팁을 사용하고 삼항 연산자에서 괄호를 제거했습니다. 감사합니다! 또한 더 적절한 (그리고 더 짧은!) S % 2에 대한 성가신 (S & 1) 테스트의 균일도를 변경했습니다.

Edit2 : * 주소 지정 스타일을 많이 사용하여 S 정의의 명백한 최적화, 즉 * (a + m)을 a [m] 등으로 대체하는 데 눈을 멀게했습니다. 그런 다음 S 자체를 T로 바꿨습니다. S가하는 것의 절반. 코드는 이제 putchar의 반환 값을 활용합니다.

Edit3 : 맨 처음부터 주위에 있던 버그 수정, 맨하탄 검색 중지 기준 a <b + m은 이미 감소 된 경우에만 정확합니다. 이것은 2 바이트를 추가하지만, m을 전역으로 정의하면 1을 다시 얻습니다.

Edit4 : 내 골프는 최소한으로 넘어 갔고 지금은 잘못 가고 있습니다. Manhattan 검색과 관련된 또 다른 버그 수정. 원래 인바운드 검사가 있었으며 배열이 아닌 대형 입력 배열 (50x50 라운드) 검색이 계속되었습니다. b. 따라서 배열을 이전 크기의 두 배 이상으로 확장해야하므로 바이트가 하나 더 추가됩니다.

#define T(x)+x*((a[x]>32)-(a[-x]>32))
m=103;main(){char b[m<<8],*e=b,*a=e+m;while(gets(e+=m));for(e=a;(T(1)T(m))%2**a<33;a=a<b+m?e+=m:a)a-=m-1;for(;*a;a+=T(1)T(m))*a-=putchar(*a);}

언 골프하고 설명 :

/* T(1)T(m) (formerly S) is used in two ways (we implicitly assume that each cell has
   one or two neighbors to begin with):
   1. (in the first for-loop) T(1)T(m) returns an odd (even) number if cell a has one (two)
      neighbors with ASCII value > 32. For this to work m must be odd.
   2. (in the second for-loop) at this stage each cell a in the array at which T(1)T(m) is
      evaluated has at most one neighboring cell with ASCII value > 32. T(1)T(m) returns the
      offset in memory to reach this cell from a or 0 if there is no such cell.
      Putting the + in front of x here saves one byte (one + here replaces two
      + in the main part)

#define T(x)+x*((a[x]>32)-(a[-x]>32))

  /* A snake of length 100 together with the newlines (replaced by 0:s in memory) fits
     an array of size 100x101, but to avoid having to perform out-of-bounds checks we
     want to have an empty line above and the array width amount of empty lines below
     the input array. Hence an array of size 202x101 would suffice. However, we save
     a (few) bytes if we express the array size as m<<8, and since m must be odd
     (see 1. above), we put m = 103. Here b and e point to the beginning of the (now)
     256x103 array and a points to the beginning of the input array therein */

m=103;
main()
{

  char b[m<<8],*e=b,*a=e+m;

  /* This reads the input array into the 256x103 array */

  while(gets(e+=m));

  /* Here we traverse the cells in the input array one
     constant-Manhattan-distance-from-top-left diagonal at a time starting at the top-left
     singleton. Each diagonal is traversed from bottom-left to top-right since the starting point
     (memory location e) is easily obtained by moving one line downwards for each diagonal
     (+m) and the stopping point is found by comparing the present location a to the input array
     starting position (b+m). The traversal is continued as long as the cell has either
     an ASCII value < 33 or it has two neighbors with ASCII value > 32 each (T(1)T(m)
     is even so that (T(1)T(m))%2=0).
     Note that the pointer e will for wide input arrays stray way outside (below) the
     input array itself, so that for a 100 cell wide (the maximum width) input array
     with only two occupied cells in the bottom-right corner, the starting cell
     will be discovered 98 lines below the bottom line of the input array.
     Note also that in these cases the traversal of the diagonals will pass through the
     right-hand side of the 103-wide array and enter on the left-hand side. This, however,
     is not a problem since the cells that the traversal then passes have a lower
     Manhattan distance and have thereby already been analyzed and found not to contain
     the starting cell. */

  for(e=a;(T(1)T(m))%2**a<33;a=a<b+m?e+=m:a)a-=m-1;

  /* We traverse the snake and output each character as we find them, beginning at the
     previously found starting point. Here we utilize the function T(1)T(m), which
     gives the offset to the next cell in the snake (or 0 if none), provided that
     the current cell has at most one neighbor. This is automatically true for the
     first cell in the snake, and to ensure it for the rest of the cells we put the
     ASCII value of the current cell to 0 (*a-=putchar(*a)), where we use the fact
     that putchar returns its argument. The value 0 is convenient, since it makes the
     stopping condition (offset = 0, we stay in place) easy to test for (*a == 0). */

  for(;*a;a+=T(1)T(m))
    *a-=putchar(*a);
}

1
이 답변은 훌륭합니다.
abligh

+1 훌륭합니다. 귀하의 솔루션과 비교하여 바이트를 어디에 넣었는지 보여주는 답변에 설명을 추가하고 싶습니다. 괜찮습니까?
mIllIbyte

밀리 바이트-의견을 자유롭게 추가하십시오. 이것이 새로운 아이디어로가는 길입니다.
Zunga

user81655-팁 덕분에 6 바이트를 줄였습니다. 사실, 나는 어제 시도하고 (S & 1) 대신 S % 2를 사용하여 균일 성 테스트를 위해 2 바이트를 더 줄 였지만 어떤 이유로 (내 코드가 다른 곳에서 버그가 있음) 제대로 작동하지 않았습니다. 그러나 이제는 모두 괜찮아 보입니다.
Zunga

아주 좋아요 좀 더와 저장 a[1], a[-m]등, 그리고 만드는 m글로벌 - m=103;main().
ugoren

9

C, 272 바이트

#define E j+(p/2*i+1)*(p%2*2-1)
#define X(Y) a[Y]&&a[Y]-32
char A[999],*a=A+99;j,p,t;i;main(c){for(;gets(++j+a);j+=i)i=strlen(a+j);for(c=j;j--;){for(t=p=4;p--;)t-=X(E);t==3&&X(j)?c=c%i+c/i<j%i+j/i?c:j:0;}for(j=c;c;){putchar(a[j]),a[j]=0;for(c=0,p=4;!c*p--;)X(E)?c=j=E:0;}}

@Zunga의 출처를보십시오. 이제 내 것을 봐 여분의 91 바이트를 어떻게 얻었는지 알고 싶습니까?
언 골프 드 :

#define E j+(p/2*i+1)*(p%2*2-1)
#define X(Y) a[Y]&&a[Y]-32  //can be more concise, see @Zunga's
  //and then doesn't need the define
char A[999],*a=A+99;j,p,t;i;
main(c){for(;gets(++j+a);j+=i)
i=strlen(a+j); //we don't need to know the length of a line
  //in @Zunga's solution, lines are spaced a constant distance apart
for(c=j;j--;){
for(t=p=4;p--;)t-=X(E);  //a ton of bytes can be saved with determining 
  //the neighbors, see @Zunga's source
t==3&&X(j)?
c=c%i+c/i<j%i+j/i?c:j:0;}  //we search for ends of the snake, 
  //and compute the Manhattan distance
for(j=c;c;){putchar(a[j]),a[j]=0;
for(c=0,p=4;!c*p--;)  //determining the neighbors again
X(E)?c=j=E:0;}}

5

파이썬 (2, 3) 640 624 604 583 575 561 546 538 바이트

나는 여전히 골프 n00b이므로 이것은 조금 큽니다.

편집 : 제안에 대한 @porglezomp 에게 감사드립니다 ! 파이썬 3을 망칠 수있는 모든 '및'연산자를 제거하지 않았습니다.

Edit2 : isspace ()에 대한 의견 을 보내 주신 @Aleksi Torhamo 에게 감사드립니다 . 결과 감소는 내가 넣은 버그 수정을 보상합니다. 또한 구문 강조에 대한 익명 덕분입니다!

Edit3 : 몇 바이트를 추가 로 @ mbomb007 에게 감사드립니다 .

import sys;s=sys.stdin.read().split('\n');m={};q=[];o=len;j=o(s);r=range;g='!'
for y in r(j):
 v=s[y];f=o(v);d=y+1
 for x in r(f):
  n=[];a=n.append;U=s[y-1]
  if v[x]>=g:j>=y>0==(U[x]<g)<=x<o(U)and a((x,y-1));j>y>=0==(v[x-1]<g)<x<=f and a((x-1,y));j>y>-1<x+1<f>(v[x+1]<g)<1and a((x+1,y));j>d>-1<x<o(s[d])>(s[d][x]<g)<1and a((x,d));m[x,y]=[v[x],n];o(n)-1or q.append((x,y))
t=min(q,key=sum);w=sys.stdout.write;w(m[t][0]);c=m[t][1][0]
while o(m[c][1])>1:
 b=m[c][1];w(m[c][0])
 for k in r(o(b)):
  if b[k]!=t:t=c;c=b[k];break
print(m[c][0])

그리고 여기 내 골프 전 버전이 있습니다

import sys

lines = sys.stdin.read().split('\n')
startend = []
mydict = {}
for y in range( 0, len(lines)):
  for x in range( 0, len(lines[y])):
    if not lines[y][x].isspace():
      neighbors = []
      if x>=0 and x<len(lines[y-1]) and y-1>=0 and y-1<len(lines):
        if not lines[y-1][x].isspace():
          neighbors.append( (x,y-1) )
      if x-1>=0 and x-1<len(lines[y]) and y>=0 and y<len(lines):
        if not lines[y][x-1].isspace():
          neighbors.append( (x-1,y) )
      if x+1>=0 and x+1<len(lines[y]) and y>=0 and y<len(lines):
        if not lines[y][x+1].isspace():
          neighbors.append( (x+1,y) )
      if x>=0 and x<len(lines[y+1]) and y+1>=0 and y+1<len(lines):
        if not lines[y+1][x].isspace():
          neighbors.append( (x,y+1) )
      mydict[(x,y)] = [ lines[y][x], neighbors ]

      if len( neighbors ) == 1:
        startend.append( (x,y) )

startend.sort( key=lambda x : x[0]*x[0] + x[1]*x[1] )

last = startend[0]
sys.stdout.write( mydict[ last ][0] )
current = mydict[last][1][0]
while len( mydict[current][1] ) > 1:
  sys.stdout.write( mydict[current][0] )
  for k in range( 0, len( mydict[current][1] ) ):
    if mydict[current][1][k] != last:
      last = current
      current = mydict[current][1][k]
      break

print(mydict[current][0])

1
소개 S=lambda s:s.isspace()하고 S(s)대신 하여 12 바이트를 절약했습니다 s.isspace().
porglezomp

1
당신은 또한 당신의 모든 변경할 수 있습니다 생각 and 에을 <하기 때문에, f() < g() < h()과 동일 g = g(); f() < g and g < h()부작용의 측면 (비교 체인 단락)에, 당신은 어쨌든 비교의 결과를 무시하고 있습니다.
porglezomp

1
m[(x,y)]=더 짧은m[x,y]=
porglezomp

2
@porglezomp : 훨씬 짧습니다S=str.isspace
Aleksi Torhamo

1
모든 경우에 제거 S하고 대신 사용 <'!'하는 길이는 같을 수 있으므로 더 많은 비용을 절약 할 수 있습니다. 변경 if 1-S(v[x]):if(v[x]<'!')<1:예를 들어,. 나중에 비교하는 방식으로 괄호를 제거 할 수 있습니다.
mbomb007

4

자바 스크립트 (ES6), 195

테스트 스 니펫 내부의 설명을 참조하십시오

s=>[...s].map((c,i)=>{if(c>' '&([n=-1,1,o=-~s.search('\n'),-o].map(d=>n+=s[i+d]>' '&&!!(e=d)),n<1)&m>(w=i/o+i%o|0))for(m=w,r=c,p=i+e;r+=s[i=p],[e,o/e,-o/e].some(d=>s[p=i+(e=d)]>' '););},m=1/0)&&r

테스트

f=s=>[...s].map((c,i)=>{if(c>' '&([n=-1,1,o=-~s.search('\n'),-o].map(d=>n+=s[i+d]>' '&&!!(e=d)),n<1)&m>(w=i/o+i%o|0))for(m=w,r=c,p=i+e;r+=s[i=p],[e,o/e,-o/e].some(d=>s[p=i+(e=d)]>' '););},m=1/0)&&r

// Less golfed

u=s=>(
  o = -~s.search('\n'), // offset between lines
  m = 1/0, // current min manhattan distance, init at infinity
  // scan input looking for the 2 ends of the string
  [...s].map((c,i)=>{ // for each char c at position i
     if(c > ' ' // check if part of the string
        & ( [-1,1,o,-o] // scan in 4 directions and count neighbors
             .map(d=> n+=s[i+d]>' '&&!!(e=d), n=0), // remember direction in e
          n < 2) // if at end of string will have exactly 1 neighbor
        & (w = i/o + i%o |0) < m) // manhattan distance in w, must be less than current min
       // found one of the ends, follow the path and build the string in r
       for(m = w, r = c, p = i+e; 
           r += s[i=p], 
           [e,o/e,-o/e] // check 3 directions, avoiding to go back
           .some(d=>s[p=i+(e=d)]>' '); // save candidate position and direction in p and e
          ); // empty for body, all the work is inside the condition
  }),
  r
)  

console.log=x=>O.textContent+=x+'\n'

;[`Hel         
  l      rin
  o,IAmASt g
           S
       !ekan`,
 `   ~ zyx tsr XWVUTSR
   }|{ wvu q Y     Q
!          p Z \`ab P
"#$ 6789:; o [ _ c O
  % 5    < n \\]^ d N
('& 432  = m     e M
)     1  > lkjihgf L
*+,-./0  ?         K
         @ABCDEFGHIJ`].forEach(t=>{
  console.log(t+'\n\n'+f(t)+'\n')
  })
<pre id=O></pre>


세미콜론이 ););}필요합니까?
Cees Timmerman

1
@CeesTimmerman 예. 첫 번째는 for2 개의 콜론이 필요한 헤더 내부 입니다. 두 번째는 for몸 의 delimeter입니다
edc65

3

루아, 562 535 529 513 507 504 466 458 바이트

지금까지 내 가장 거대한 골프 는 여전히 100 바이트를 잘라낼 수 있다고 생각합니다. 나는 맞았다, 나는 100 바이트 이상을 삭감했다! 개선의 여지가 많다고 생각하지 않습니다.

이 함수는 셀당 하나의 문자를 포함하는 2D 배열로 호출해야합니다.

그 덕분에 @KennyLau 작업을하면서 40 바이트를 절약 했습니다!

우후! 500 이하!

function f(m)t=2u=1i=1j=1s=" "::a::if s~=m[i][j]and(i<#m and m[i+1][j]~=s)~=(j<#m[i]and m[i][j+1]~=s)~=(i>1 and m[i-1][j]~=s)~=(j>1 and m[i][j-1]~=s)then goto b end
i,t=i%t+1,#m>t and t==i and t+1or t j=j>1 and j-1or u u=u<#m[1]and j==1 and u+1or u goto a::b::io.write(m[i][j])m[i][j]=s
i,j=i<#m and s~=m[i+1][j]and i+1or i>1 and s~=m[i-1][j]and i-1or i,j<#m[i]and s~=m[i][j+1]and j+1or j>1 and s~=m[i][j-1]and j-1or j
if s==m[i][j]then return end goto b end

언 골프

일단 골프를 마치면 설명이 나옵니다. 잠시 동안,이 소스 코드를 읽을 수있는 버전으로 빌려 드리겠습니다 : D 여기에 설명이 있습니다!

편집 : 최신 수정 사항으로 업데이트되지 않고 업데이트 전에 여전히 골프를칩니다. 설명도 마찬가지입니다.

function f(m)                    -- declare the function f which takes a matrix of characters
  t=2                            -- initialise the treshold for i
                                 -- when looking for the first end of the snake
  u=1                            -- same thing for j
  i,j=1,1                        -- initialise i and j,our position in the matrix
  s=" "                          -- shorthand for a space
  ::a::                          -- label a, start of an infinite loop
    if m[i][j]~=s                -- check if the current character isn't a space
      and(i<#m                   -- and weither it is surrounded by exactly
          and m[i+1][j]~=s)      -- 3 spaces or not
      ~=(j<#m[i]
          and m[i][j+1]~=s)      -- (more explanations below)
      ~=(i>1 
          and m[i-1][j]~=s)
      ~=(j>1
          and m[i][j-1]~=s)
      then goto b end            -- if it is, go to the label b, we found the head
    i,t=                         -- at the same time
      i%t+1,                     -- increment i
      #m>t and t==i and t+1or t  -- if we checked all chars in the current range, t++
    j=j>1 and j-1or u            -- decrement j
    u=u>#m[1]and j==1 and u+1or u-- if we checked all chars in the current range, u++
  goto a                         -- loop back to label a

  ::b::                          -- label b, start of infinite loop
  io.write(m[i][j])                    -- output the current char
    m[i][j]=s                    -- and set it to a space
    i,j=i<#m                     -- change i and j to find the next character in the snake
          and m[i+1][j]~=s       -- this nested ternary is also explained below
            and i+1              -- as it takes a lot of lines in comment ^^'
          or i>1 
            and m[i-1][j]~=s
            and i-1
          or i,
       j<#m[i] 
         and m[i][j+1]~=s
           and j+1
         or j>1 
           and m[i][j-1]~=s 
           and j-1
         or j
    if m[i][j]==s                -- if the new char is a space
    then                         -- it means we finished
      return                  -- exit properly to avoid infinite
    end                          -- printing of spaces
  goto b                         -- else, loop back to label b
end

다음은이 프로그램의 작동 방식에 대한 자세한 설명입니다.

우선이라는 레이블이 붙은 루프를 살펴보면 a왼쪽 상단 모서리에서 가장 가까운 끝을 찾을 수 있습니다. 끝이 없으면 영원히 반복되지만 문제는 아닙니다 : D.

4x4 그리드에서 여기에 뱀 거리 (왼쪽)와 보이는 순서 (오른쪽)가 있습니다.

1  2  3  4    |     1  2  4  7
2  3  4  5    |     3  5  8 11
3  4  5  6    |     6  9 12 14
4  5  6  7    |    10 13 15 16

이 문자 각각에 대해 끝이 되려면 두 가지 조건을 확인해야합니다.-공백이 아님-정확히 3 개의 공백으로 둘러싸여 있음

이러한 조건은 다음 코드에서 확인됩니다.

r=m[i][j]~=s
    and(i<#m and m[i+1][j]~=s)
    ==not(j<#m[i] and m[i][j+1]~=s)
    ==not(i-1>0 and m[i-1][j]~=s)
    ==not(j-1>0 and m[i][j-1]~=s)
    and m[i][j]
    or r
  -- special note: "==not" is used as an equivalent to xor
  -- as Lua doesn't know what is a xor...

문자가 공백이 아닌지 확인하는 것은 expression에 의해 달성됩니다 m[i][j]~=s.

주변 환경에 대해 위의 조건을 xoring하여 비 공간이 하나만 둘러싸여 있는지 확인하면 다음과 같이 쓸 수 있습니다.

m[i+1][j]~=" "  m[i][j+1]~=" "  m[i-1][j]~=" "  m[i][j-1]~=" "

마지막으로 위의 모든 내용이 true로 평가되면 삼항은 마지막 and->을 반환합니다 m[i][j]. 그렇지 않으면, 우리는 r설정 해제 하자 :)

뱀의 머리가 생겼으니 이제 다른 쪽 끝까지 가자! 뱀을 반복하는 것은 주로 다음과 같은 중첩 된 삼항으로 이루어집니다.

i,j=i<#m and m[i+1][j]~=s and i+1or i-1>0 and m[i-1][j]~=s and i-1or i,
    j<#m[i]and m[i][j+1]~=s and j+1or j-1>0 and m[i][j-1]~=s and j-1or j

우리는-다시 설정 i하고 j동시에 그들은 모두 동일한 구조를 가지고 있고, 간단한 조건을 사용하여 이전 값을 저장하기 위해 인형을 필요로하지 않도록, 그래서 중첩의 형태를 제시거야 if, 당신이 읽을 수 있도록해야 더 쉽게. :)

i=i<#m and m[i+1][j]~=s and i+1or i-1>0 and m[i-1][j]~=s and i-1or i

다음과 같이 번역 될 수 있습니다.

if(i<#m)
then
  if(m[i+1][j]~=" ")
  then
    i=i+1
  end
elseif(i-1>0)
then
  if(m[i-1][j]~=" ")
  then
    i=i-1
  end
end

그것을 테스트하십시오!

이 코드를 실행하는 데 사용하는 코드는 다음과 같습니다 . 복사하여 붙여 넣어 온라인 으로 테스트 할 수 있습니다 .

function f(m)t=2u=1i=1j=1s=" "::a::if s~=m[i][j]and(i<#m and m[i+1][j]~=s)~=(j<#m[i]and m[i][j+1]~=s)~=(i>1 and m[i-1][j]~=s)~=(j>1 and m[i][j-1]~=s)then goto b end
i,t=i%t+1,#m>t and t==i and t+1or t j=j>1 and j-1or u u=u<#m[1]and j==1 and u+1or u goto a::b::io.write(m[i][j])m[i][j]=s
i,j=i<#m and s~=m[i+1][j]and i+1or i>1 and s~=m[i-1][j]and i-1or i,j<#m[i]and s~=m[i][j+1]and j+1or j>1 and s~=m[i][j-1]and j-1or j
if s==m[i][j]then return end goto b end


test1={}
s1={
"  tSyrep    ",
"  r    p    ",
"  in Sli    ",
"   g    Sile",
"   Snakes  n",
"Ser      ylt",
"a eh   ilS  ",
"fe w   t    ",
"   emo h    ",
"     Sre    ",
     }
for i=1,#s1
do
  test1[i]={}
  s1[i]:gsub(".",function(c)test1[i][#test1[i]+1]=c end)
end
f(test1)

1
언어 선택으로 인해 지금은 거의 선택하지 않은 더 긴 답변을 얻을 수있는 곳이 없습니다.
Matt

@Matt 지원 주셔서 감사합니다! 사실, 나는 여전히 이것을 골프화하는 방법을 찾고 있지만 점점 더 어려워지고 있습니다!
Katenkyo

2

루아, 267 바이트

루아 5.3이 필요합니다.

e=" "w=#arg[1]+1i=1/0q=0s=table.concat(arg,e)s=e:rep(#s)..s
m,n=i,{}for p in s:gmatch"()%g"do u=-1
for _,d in ipairs{-1,1,-w,w}do u=u+(s:find("^%S",d+p)or 0)end
n[p]=u+1m=math.min(m,p*i^(u//#s)+(p%w*w+p)*#s)end
p=m%#s repeat q,p=p,n[p]-q io.write(s:sub(q,q))until p<1

용법:

$ lua desnakify.lua \
>    "  tSyrep    " \
>    "  r    p    " \
>    "  in Sli    " \
>    "   g    Sile" \
>    "   Snakes  n" \
>    "Ser      ylt" \
>    "a eh   ilS  " \
>    "fe w   t    " \
>    "   emo h    " \
>    "     Sre    "
SlipperyStringSnakesSilentlySlitherSomewhereSafe

2

파이썬 3, 245 243 241 236 바이트

s입력 문자열이고 n출력이 stdout으로 인쇄됩니다.

f=s.find
w,l=f('\n')+1,len(s)
t=1,w,-1,-w
y=z=f(s.strip()[0]);n=s[y];v={y}
for i in range(l*l):
 i%=l;c=s[i]
 if c>' 'and i not in v:
  if i-y in t:y=i;n=c+n;v|={i}
  elif i-z in t:z=i;n+=c;v|={i}
if y%w+y//w>z%w+z//w:n=n[::-1]
print(n)

편집 : 5 바이트를 절약 한 @Cees Timmerman에게 감사드립니다!


c>' 'andprint n파이썬 2에서
시스 Timmerman

if대신에 할 수 없습니까 elif?
clismique

@ Qwerp-Derp 불행히도, 전에 시도하지는 않았지만 "! ekanSgnirtSAmAI, olleHello, IAmAStringSnake!"와 같이 인쇄됩니다. 및 "SlipperyStSyreppilS".
pgks

입력 형식은 무엇입니까?
clismique

@ Qwerp-Derp s변수는 여러 줄 문자열입니다. 문자열의 마지막 문자는 개행이어야합니다 ( Python테스트 케이스 를 통과하는 데 필요함 )
pgks

1

파이썬, 537

내 초기 솔루션 :

from itertools import chain, product, ifilter
from operator import add
moves = ((1,0),(0,1),(-1,0),(0,-1))
h = dict(ifilter(lambda (p,v):not v.isspace(),chain(*map(lambda (i,r):map(lambda (j,c):((i,j),c),enumerate(r)),enumerate(s)))))
n = defaultdict(list)
for m,p in product(moves, h):
    np = tuple(map(add,m,p))
    if np in h:
        n[p].append(np)
def pr(nx):
    return(lambda l:(h[l[0]], h.pop(l[0]))[0] + pr(l[0]) if l else '')([x for x in n[nx] if x in h])
(lambda y: h[y]+ pr(y))(next(x for x in n if len(n[x])==1))

약간 압축했지만 방법으로 남겨 두었습니다.

from itertools import chain, product
from operator import add
def unsnake(s):
    (h,n) = (dict(filter(lambda (p,v):not v.isspace(),chain(*map(lambda (i,r):map(lambda (j,c):((i,j),c),enumerate(r)),enumerate(s))))),defaultdict(list))
    for m,p in product(((1,0),(0,1),(-1,0),(0,-1)), h):(lambda np: n[p].append(np) if np in h else 0)(tuple(map(add,m,p)))
    def pr(nx):return(lambda l:(h[l[0]], h.pop(l[0]))[0] + pr(l[0]) if l else '')([x for x in n[nx] if x in h])
    return(lambda y: h[y]+ pr(y))(next(x for x in n if len(n[x])==1))

1

자바 7, 927 924 923 바이트

import java.util.*;int l,k;char[][]z;Set p=new HashSet();String c(String[]a){int x=0,y=0,n,t,u,v,w=t=u=v=-1;l=a.length;k=a[0].length();z=new char[l][k];for(String s:a){for(char c:s.toCharArray())z[x][y++]=c;}x++;y=0;}for(x=0;x<l;x++)for(y=0;y<k;y++){n=0;if(z[x][y]>32){if(x<1|(x>0&&z[x-1][y]<33))n++;if(y<1|(y>0&&z[x][y-1]<33))n++;if(x>l-2|(x<l-1&&z[x+1][y]<33))n++;if(y>k-2|(y<k-1&&z[x][y+1]<33))n++;}if(n>2&t<0){t=x;u=y;}if(n>2&t>v){v=x;w=y;}}if(v+w>t+u){p(t,u);return n(""+z[t][u],t,u);}p(v,w);return n(""+z[v][w],v,w);}String n(String r,int x,int y){int a,b;if(x>0&&z[a=x-1][b=y]>32&q(a,b)){p(a,b);return n(r+z[a][b],a,b);}if(y>0&&z[a=x][b=y-1]>32&q(a,b)){p(a,b);return n(r+z[a][b],a,b);}if(x<l-1&&z[a=x+1][b=y]>32&q(a,b)){p(a,b);return n(r+z[a][b],a,b);}if(y<k-1&&z[a=x][b=y+1]>32&q(a,b)){p(a,b);return n(r+z[a][b],a,b);}return r;}boolean q(int x,int y){return!p.contains(x+","+y);}void p(int x,int y){p.add(x+","+y);}

좋아, 잠시했다가 .. 일부 프로그래밍 언어에서 당신의 배열 x와 y는 2 차원 배열의 경계 밖에있는,하지만 자바는 던질거야 경우 문제가되지 않습니다 ArrayIndexOutOfBoundsExceptions, 그래서 모든 것을 확인해야합니다 ..

먼저 시작점을 결정한 다음 재귀 메서드를 사용하여 문자열을 작성합니다. 또한 목록을 사용하여 이미 발생한 조정을 추적하므로 루프 백 포스 백 포스 (스택 오버 플로우 예외 발생)로 이동하지 않습니다.

이것은 아마도 내가 지금까지 게시 한 가장 긴 대답 일지 모르지만 일부 부분은 골프를 칠 수 있지만 Java에서는이 과제가 그렇게 짧을 수 있다고 생각하지 않습니다. Java는 그리드의 경로를 따르는 데 적합하지 않습니다. 그럼에도 불구하고 이해하기는 재미있는 도전이었습니다. :)

언 골프 및 테스트 사례 :

여기에서 시도하십시오.

import java.util.*;
class M{
  static int l,
             k;
  static char[][] z;
  static Set p = new HashSet();

  static String c(String[] a){
    int x=0,
        y=0,
        n,
        t,
        u,
        v,
        w = t = u = v = -1;
    l = a.length;
    k = a[0].length();
    z = new char[l][k];
    for(String s:a){
      for(char c:s.toCharArray()){
        z[x][y++] = c;
      }
      x++;
      y = 0;
    }
    for(x=0; x<l; x++){
      for(y=0; y<k; y++){
        n = 0;
        if(z[x][y] > 32){ // [x,y] is not a space
          if(x < 1 | (x > 0 && z[x-1][y] < 33)){
            n++;
          }
          if(y < 1 | (y > 0 && z[x][y-1] < 33)){
            n++;
          }
          if(x > l-2 | (x < l-1 && z[x+1][y] < 33)){
            n++;
          }
          if(y > k-2 | (y < k-1 && z[x][y+1] < 33)){
            n++;
          }
        }
        if(n > 2 & t < 0){
          t = x;
          u = y;
        }
        if(n > 2 & t > v){
          v = x;
          w = y;
        }
      }
    }
    if(v+w > t+u){
      p(t, u);
      return n(""+z[t][u], t, u);
    }
    p(v, w);
    return n(""+z[v][w], v, w);
  }

  static String n(String r, int x, int y){
    int a,b;
    if(x > 0 && z[a=x-1][b=y] > 32 & q(a,b)){
      p(a, b);
      return n(r+z[a][b], a, b);
    }
    if(y > 0 && z[a=x][b=y-1] > 32 & q(a,b)){
      p(a, b);
      return n(r+z[a][b], a, b);
    }
    if(x < l-1 && z[a=x+1][b=y] > 32 & q(a,b)){
      p(a, b);
      return n(r+z[a][b], a, b);
    }
    if(y < k-1 && z[a=x][b=y+1] > 32 & q(a, b)){
      p(a, b);
      return n(r+z[a][b], a, b);
    }
    return r;
  }

  static boolean q(int x, int y){
    return !p.contains(x+","+y);
  }

  static void p(int x, int y){
    p.add(x+","+y);
  }

  public static void main(String[] a){
    System.out.println(c(new String[]{ "Hel         ",
      "  l      rin",
      "  o,IAmASt g",
      "           S",
      "       !ekan" }));
    p = new HashSet();
    System.out.println(c(new String[]{ "Python" }));
    p = new HashSet();
    System.out.println(c(new String[]{ "P  ngPu  Code ",
      "r  i  z  d  G",
      "o  m  z  n  o",
      "gram  lesA  lf" }));
    p = new HashSet();
    System.out.println(c(new String[]{ "   ~ zyx tsr XWVUTSR",
      "   }|{ wvu q Y     Q",
      "!          p Z `ab P",
      "\"#$ 6789:; o [ _ c O",
      "  % 5    < n \\]^ d N",
      "('& 432  = m     e M",
      ")     1  > lkjihgf L",
      "*+,-./0  ?         K",
      "         @ABCDEFGHIJ" }));
    p = new HashSet();
    System.out.println(c(new String[]{ "  tSyrep    ",
      "  r    p   ",
      "  in Sli   ",
      "   g    Sile",
      "   Snakes  n",
      "Ser      ylt",
      "a eh   ilS ",
      "fe w   t   ",
      "   emo h   ",
      "     Sre    " }));
  }
}

산출:

Hello,IAmAStringSnake!
Python
ProgrammingPuzzlesAndCodeGolf
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
SlipperyStringSnakesSilentlySlitherSomewhereSafe

924 바이트, 예수 그리스도 ... lol
숀 와일드

@BasicallyAlanTuring Hehe. 난 그냥 도전하고, 코드를 골라 낸 다음 바이트 수를 보았습니다. 실제로 예상보다 훨씬 높았지만 아아, 적어도 1k 미만입니다. 개선해야 할 것이 있으면 알려주고 바이트 수가 적은 다른 방법을 사용하는 경우 자유롭게 분리하십시오. 우편; 나는 그것을보고 싶어한다. 추신 : 이제 923 바이트입니다. XD
Kevin Cruijssen

everythig확인할 필요가 없으며 문자열에 패딩을 추가하십시오. 아마도 여러 줄 문자열을 사용하면 더 쉽습니다. javascript에서 내 C # 답변을 살펴보십시오
edc65

1

PHP, 199 (184) 182 바이트

여전히 약간의 골프 잠재력이있을 수 있습니다

for($w=strpos($i=$argv[1],"
");;)for($y=++$n;$y--;)if($i[$p=$y*$w+$n-1]>" ")break 2;for($p-=$d=$w++;$d&&print$i[$p+=$e=$d];)foreach([-$w,-1,1,$w,0]as$d)if($d+$e&&" "<$i[$d+$p])break;

커맨드 라인에서 입력을 여러 줄로 받아 리눅스 스타일의 줄 바꿈이 필요합니다.
실행 php -r '<code>' '<string>'; 줄 바꿈을 피하십시오.

고장

for(
    // find width
    $w=strpos($i=$argv[1],"\n")
    ;
    // find first character: initialize $p(osition)
    ;
)
    for($y=++$n             // increase distance
        ;$y--;)             // loop $y from (old)$n to 0
        if(" "<$i[$p=$y*$w+$n   // if character at $y*($width+1)+$x(=$d-$y) is no space
            -1                  // (adjust for the premature increment)
        ])
            break 2;                    // break loops

for(
    $p-=            // b) reverse the increment that follows in the pre-condition
    $d=             // a) initialize $d to anything!=0 to enable the first iteration
    $w++;           // c) increase $w for easier directions
    $d              // loop while direction is not 0 (cursor has moved)
    &&
    print$i[$p+=$e=$d]              // remember direction, move cursor, print character
    ;
)
    foreach([-$w,-1,1,$w,0]as$d)// loop through directions
        if($d+$e                    // if not opposite previous direction
            &&" "<$i[$d+$p]         // and character in that direction is not space
        )break;                     // break this loop

1

C #, 310

(편집 : 버그 수정)

여러 줄 문자열 매개 변수를 사용하여 문자열을 반환하는 함수입니다.

요청 using된 바이트 수를 포함합니다 .

이것은 내 자바 스크립트 답변의 포팅입니다.

using System.Linq;
string f(string s){int o=-~s.IndexOf('\n'),m=99;var r=new string(' ',o);(s=r+s+r).Select((c,i)=>{int n=2,e=0,p,w=i%o+i/o;if(c>' '&w<m&&new[]{-1,1,o,-o}.All(d=>(s[i+d]>' '?(e=d)*--n:n)>0))for(m=w,r=""+c+s[p=i+e];new[]{e,o/e,-o/e}.Any(d=>s[p+(e=d)]>' ');)r+=s[p+=e];return i;}).Max();return r;}

이데온 테스트

공백으로

    string f(string s)
    {
        int o = -~s.IndexOf('\n');
        var r = new string(' ', o);
        var m = 99;
        (s = r + s + r).Select((c, i) =>
        {
            int n = 2, e = 0, p, w = i % o + i / o;
            if (c > ' ' & w < m & new[] { -1, 1, o, -o }.All(d => (s[i + d] > ' ' ? (e = d) * --n : n) > 0))
                for (m = w, r = "" + c + s[p = i + e]; 
                     new[] { e, o / e, -o / e }.Any(d => s[p + (e = d)] > ' '); 
                     ) 
                   r += s[p += e];
            return i;
        }
        ).Max();
        return r;
    }

1

파이썬 2, 251 바이트

w=s.find('\n')+1;q=' ';p=q*w+'\n';s=list(p+s+p);d=-w,1,w,-1
def r(x):c=s[x];s[x]=q;v=[c+r(x+o)for o in d if s[x+o]>q];return v[0]if v else c
e=[x for x in range(len(s))if s[x]>q and sum([s[x+o]>q for o in d])<2]
print r(e[e[0]/w+e[0]%w>e[1]/w+e[1]%w])

또는 테스트 케이스에서 줄 바꿈을 원하는 경우 257 바이트 :

w=s.find('\n',1);q=' ';p=q*-~w+'\n';s=list(p+s[1:]+p);d=-w,1,w,-1
def r(x):c=s[x];s[x]=q;v=[c+r(x+o)for o in d if s[x+o]>q];return v[0]if v else c
e=[x for x in range(len(s))if s[x]>q and sum([s[x+o]>q for o in d])<2]
print r(e[e[0]/w+e[0]%w>e[1]/w+e[1]%w])

모든 테스트 케이스를 통과합니다.

s="""
  tSyrep    
  r    p    
  in Sli    
   g    Sile
   Snakes  n
Ser      ylt
a eh   ilS  
fe w   t    
   emo h    
     Sre    
"""

결과 :

SlipperyStringSnakesSilentlySlitherSomewhereSafe

3
나는 당신이 대체 할 수있는 생각 b.append(...)b+=[...]def n(x,y):return ...함께n=lambda x,y:...
acrolith

1
에 대한 변수를 만듭니다 ' '.
pacholik

1
그리고 사용하는 ~-x대신 x-1, 당신은 괄호를 사용하지 않아도됩니다.
pacholik

0

apt -P , 106 바이트

K=U·ÌÊÄ ç iU ¬mx T=[-KJ1K]
ËÊ*Tm+E è@gX
[]V£YÃf@gXÃrQ@WpQ Tm+Q kW fZ Ì}V£[XYuK YzK]ÃkÈv ÉÃñx v rÈ+Y*K
W£gX

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

그건 ... 음 ... 가증 한 일이야

포장 풀기 및 작동 방식

K=UqR gJ l +1 ç iU q mx
  UqR gJ l +1            Split the input by newline, take last item's length +1
K=                       Assign to K
              ç iU       Generate a string of K spaces, and append to U
                   q mx  Split into chars, and trim whitespaces on each item
                         Implicit assign to U

T=[-KJ1K]  Assign an array [-K, -1, 1, K] to T (this represents 4-way movement)
           I could use implicit assignment, but then 4-argument function below is broken

UmDEF{Dl *Tm+E èXYZ{UgX
UmDEF{                   Map over the list of one- or zero-length strings...
      Dl *                 If the length is zero, return zero
          Tm+E             Add the index to each element of T
               èXYZ{UgX    Count truthy elements at these indices
                         The result is an array of 0(space/newline), 1(start/end), or 2(body)
                         Implicit assign to V

[]  Implicit assign to W

VmXYZ{Y} fXYZ{UgX} rQXYZ{WpQ Tm+Q kW fZ gJ }
VmXYZ{Y}                                      Map V into indices
         fXYZ{UgX}                            Filter the indices by truthiness of U's element
                   rQXYZ{                     Reduce on the indices... (Q=last item, Z=array)
                         WpQ                    Push Q to W
                             Tm+Q               Take 4-way movements from Q
                                  kW fZ gJ }    Exclude visited ones, take last one in Z

VmXYZ{[XYuK YzK]} kXYZ{Xv -1} ñx v rXYZ{X+Y*K  Starting point of reduce
VmXYZ{[XYuK YzK]}                              Convert elements of V to [elem, col, row]
                  kXYZ{Xv -1}                  Take the ones where elem(popped)=1
                              ñx v             Sort by row+col and take first one
                                   rXYZ{X+Y*K  Convert [row,col] back to the index

WmXYZ{UgX  Map indices back to chars

-P  Join with empty string

주목할만한 점은 JS에서 할당과 쉼표 연산자 사이의 연산자 우선 순위를 사용하여 일부 줄을 묶고 바로 가기 @( XYZ{)를 사용할 수 있다는 것입니다.

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