Détruire une corde

58

Une chaîne régulière ressemble à ceci:

Hello,IAmAStringSnake!

Et un serpent à cordes ressemble à ceci:

Hel         
  l      rin
  o,IAmASt g
           S
       !ekan

Ta tâche

Les serpents de chaîne sont dangereux, vous devez donc créer un programme qui prend un serpent de chaîne en entrée et le sort en tant que chaîne normale.

Caractéristiques

  • L'entrée peut être une chaîne multiligne ou un tableau de chaînes.
  • Chaque ligne de l'entrée sera complétée d'espaces pour former une grille rectangulaire.
  • Les personnages du serpent ne peuvent se connecter qu'aux personnages adjacents situés au-dessus, au-dessous, à gauche ou à droite (comme dans le jeu Snake). Ils ne peuvent pas aller en diagonale.
  • Les personnages serpent ne seront jamais adjacents à une autre partie du serpent, mais uniquement aux personnages connectés.
  • Le premier caractère de la chaîne est le caractère de fin avec la distance la plus courte entre Manhattan et le coin supérieur gauche de la grille de saisie (c’est-à-dire le nombre minimum de déplacements nécessaires pour qu’un serpent passe directement du caractère de fin à la partie supérieure gauche. Coin). Les deux extrémités n'auront jamais la même distance.
  • La chaîne peut contenir n’importe quel caractère ASCII entre les points de code 33 et 126 inclus (sans espaces ni nouvelles lignes).
  • La chaîne comportera entre 2 et 100 caractères.
  • Le code le plus court en octets gagne.

Cas de test

(Grille d'entrée, suivie de la chaîne de sortie)

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
utilisateur81655
la source
20
Anecdote: Selon l'article lié à Wikipedia, la distance de Manhattan est également appelée distance de serpent!
user81655
Une entrée comme hastebin.com/asugoropin.vbs serait-elle correcte?
FliiFe
@FliiFe Non, certaines parties du serpent ne peuvent pas être côte à côte car il n'est pas toujours possible de savoir où le serpent se dirige quand cela se produit (et cela rendrait le défi beaucoup plus difficile). J'ai ajouté une ligne à la spécification pour expliquer cela.
user81655
L'entrée peut-elle être un tableau à deux dimensions (chaque caractère en tant qu'élément)?
FliiFe
29
Ce casse-tête a sûrement besoin d'une réponse en python?
Abligh

Réponses:

11

APL, 55 octets

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

Cette fonction prend une matrice de caractères contenant la chaîne serpent.

Exemple:

      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{|}~

Explication:

  • (,⍵≠' ')/,⍳⍴⍵: obtenir les coordonnées de tous les non-espaces
  • (⊂0 0): commence à (0,0) (ce qui est une coordonnée invalide)
  • {... }: suivez le serpent, position donnée et serpent:
    • 1<⍴⍵:: s'il reste plus d'un élément:
      • ∆←⍵~⍺: supprime la position actuelle du serpent et la stocke dans .
      • +/¨|⍺-∆: recherche la distance entre la position actuelle et chaque point du reste du serpent
      • ∆[⊃⍋...] `: obtenir le point le plus proche sur le serpent
      • : exécutez à nouveau la fonction, avec le point le plus proche en tant que nouveau point actuel et le serpent raccourci en tant que nouveau serpent.
      • ⍺,: ajoute la position actuelle au résultat de cette
    • ⋄⍺: sinon, il suffit de retourner la position actuelle
  • 1↓: supprime le premier élément du résultat (qui est la position (0,0))
  • ⍵[... ]: récupère ces éléments de ⍵, dans cet ordre
marinus
la source
24

JavaScript (ES6) + SnakeEx , 176 octets

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,"")

Tu te souviens de SnakeEx? Bien, parce que moi non plus! Les suggestions de golf sont les bienvenues.

LegionMammal978
la source
19

MATL , 80 octets

Merci à @LevelRiverSt pour une correction

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

L'entrée se présente sous la forme d'un tableau 2D de caractères, avec des lignes séparées par ;. Les cas de test dans ce format sont

['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    ']

Essayez-le en ligne!

Explication

Les coordonnées de chaque caractère non-espace sont représentées par un nombre complexe. Pour chaque caractère actuel, le suivant est obtenu comme étant le plus proche (différence absolue minimale de leurs coordonnées complexes).

Pour déterminer le caractère initial, il faut trouver les deux extrémités. Cela se fait comme suit. Un point de terminaison est un caractère non-espace qui a exactement un voisin non-espace. Le nombre de voisins est obtenu par convolution 2D avec un masque approprié. Le point initial est le point final dont la coordonnée complexe a la plus petite somme de parties réelles et imaginaires; c'est-à-dire que, à Manhattan, la distance est la plus proche du nombre complexe 0 ou équivalente à 1 + 1j, qui est la coordonnée complexe du coin supérieur gauche.

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
Luis Mendo
la source
Je supposerai qu'une explication est à venir?
Matt
@Matt Bien sûr ... plus tard dans la journée :-)
Luis Mendo
Explication ajoutée @Matt
Luis Mendo
The initial point is the endpoint whose complex coordinate has the least absolute valueAttention: distance euclidienne! = Distance de Manhattan. par exemple, le point 7 + 7j a une distance euclidienne de 9,8994 et Manhattan une distance de 14. 10j est plus éloigné de la distance euclidienne mais considérablement plus proche de Manhattan. Autre que ça, super concept!
Level River St
@LevelRiverSt Merci! Corrigé
Luis Mendo
14

C 198 190 179 180 181 181 octets

Edit: Utilisé le conseil par user81655 et supprimé la parenthèse dans l'opérateur ternaire, merci! J'ai également changé le test fastidieux (S & 1) pour l'uniformité pour le plus approprié (et plus court!) S% 2.

Edit2: L’utilisation intensive du style * a m’aveugle sur les optimisations évidentes de la définition de S, c’est-à-dire le remplacement de * (a + m) par un [m], etc. J'ai ensuite remplacé S lui-même par T, qui la moitié de ce que S fait. Le code tire également parti de la valeur de retour de putchar.

Edit3: Correction d'un bug qui existait depuis le début, le critère d'arrêt de recherche de Manhattan a <b + m n'est correct que si a a déjà été décrémenté. Cela ajoute 2 octets, mais on en retrouve un en rendant la définition de m globale.

Edit4: Mon golf a passé le minimum et va maintenant dans le mauvais sens. Une autre correction de bogue liée à la recherche Manhattan. J'avais initialement des contrôles entrants en place et sans ceux-ci, la recherche continue pour les grands tableaux d'entrée (quelque part autour de 50x50) au-delà du tableau b. Par conséquent, ce tableau doit être étendu à au moins deux fois la taille précédente, ce qui ajoute un octet supplémentaire.

#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);}

Ungolfed et expliqué:

/* 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);
}
Zunga
la source
1
Cette réponse est géniale.
Abligh
+1 c'est génial. Je voudrais ajouter une explication à ma réponse indiquant où j'ai multiplié les octets par rapport à votre solution, est-ce que ça va?
mIllIbyte
mIllIbyte - n'hésitez pas à ajouter des commentaires, c'est la voie vers de nouvelles idées.
Zunga
user81655 - merci pour le conseil, il a rasé 6 octets. En fait, j’ai essayé cela hier en utilisant S% 2 au lieu de (S & 1), qui supprimait encore 2 octets, pour le test de régularité, mais pour une raison quelconque (mon code était ailleurs), cela ne fonctionnait pas correctement à ce moment-là. Maintenant, cependant, tout semble aller pour le mieux.
Zunga
Très agréable. Économisez un peu plus avec a[1], a[-m]etc, et en rendant mglobal - m=103;main().
Ugoren
9

C, 272 octets

#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;}}

Regardez la source de @ Zunga. Maintenant, regarde le mien. Vous voulez savoir comment j'ai obtenu les 91 octets supplémentaires?
Ungolfed:

#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;}}
MIllIbyte
la source
5

Python (2 et 3), 640 624 604 583 575 561 546 538 octets

Je suis toujours un n00b de golf, donc c'est un peu gros.

Edit: Merci à @porglezomp pour les suggestions! Je n'ai pas supprimé tous les opérateurs 'et' car cela casserait Python 3.

Edit2: Merci à @Aleksi Torhamo pour le commentaire à propos de isspace (). La réduction résultante compense la correction de bogue que j’ai mise. Aussi, grâce à anonymous pour la coloration syntaxique!

Edit3: Merci à @ mbomb007 pour quelques octets supplémentaires.

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])

Et voici ma version pré-golf

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])
plafondcat
la source
1
J'ai sauvegardé 12 octets en introduisant S=lambda s:s.isspace()puis en faisant à la S(s)place de s.isspace().
mardi
1
Je pense que vous pouvez également changer tous vos and à <, depuis f() < g() < h()est la même que celle g = g(); f() < g and g < h()en termes d'effets secondaires (chaînes de comparaison de court-circuit), et vous ne tenez pas compte du résultat des comparaisons de toute façon.
mardi
1
m[(x,y)]=est le même que le plus courtm[x,y]=
porglezomp
2
@porglezomp: c'est encore plus court à direS=str.isspace
Aleksi Torhamo
1
Supprimer Set utiliser <'!'à la place dans chaque occurrence peut être de la même longueur, ouvrant éventuellement une opportunité d'économiser davantage. Changer if 1-S(v[x]):pour if(v[x]<'!')<1:, par exemple. Et peut-être que vous pourriez supprimer certaines parenthèses lors des comparaisons ultérieures en procédant ainsi.
mbomb007
4

JavaScript (ES6), 195

Voir l'explication à l'intérieur de l'extrait de test

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

Tester

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>

edc65
la source
Les points-virgules sont-ils ););}nécessaires?
Cees Timmerman
1
@CeesTimmerman oui. Le premier est à l'intérieur de l'en- fortête où 2 points sont nécessaires. Le second est le séparateur pour le forcorps
edc65
3

Lua, 562 535 529 513 507 504 466 458 octets

De loin mon golf le plus massif en ce moment, je pense que je peux encore couper 100 octets, ce sur quoi je vais travailler, mais je l’afficherai comme réponse car cela prenait déjà un peu de temps :). J'avais raison, j'ai coupé plus de 100 octets! Je ne pense pas qu'il y ait beaucoup de place à l'amélioration.

cette fonction doit être appelée avec un tableau 2D contenant un caractère par cellule.

Sauvegardé 40 octets en travaillant avec @KennyLau , merci à lui!

Woohoo! Moins de 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

Ungolfed

Les explications viendront une fois que j'aurai fini de jouer au golf. Pour le moment, je vais vous prêter une version lisible de ce code source: D Voici les explications!

Edit: pas mis à jour avec la dernière modification, toujours jouer au golf avant la mise à jour. Idem pour les explications

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

Voici donc quelques explications détaillées sur le fonctionnement de ce programme.

Tout d'abord, considérons la boucle étiquetée a, elle nous permet de trouver l'extrémité la plus proche du coin supérieur gauche. Il y aura une boucle pour toujours s'il n'y a pas de fin, mais ce n'est pas un problème: D.

Sur une grille 4x4, voici les distances des serpents (à gauche), et leur ordre d'affichage (à droite)

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

Pour chacun de ces personnages, pour être la fin, il doit vérifier deux conditions: - ne pas être un espace - être entouré exactement par 3 espaces (ou exactement 1 non-espace)

Ces conditions sont vérifiées dans le code suivant

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...

Vérifier si le caractère n'est pas un espace est obtenu par l'expression m[i][j]~=s.

En vérifiant si nous sommes entourés par seulement un espace non-espace, en remplissant les conditions ci-dessus pour notre environnement, vous pouvez écrire ceci:

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

Et enfin, si tout ce qui précède est évalué comme étant vrai, le ternaire retournera ce qui se trouve dans le dernier and-> m[i][j]. Sinon, nous laissons rhors service :)

Maintenant que nous avons la tête du serpent, allons jusqu'au bout! La itération du serpent est principalement réalisée par les ternaires imbriqués suivants:

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

Nous sommes-ensemble iet jen même temps pour éviter les mannequins qui nécessitent garder les anciennes valeurs Ils ont tous deux la même structure exacte et les conditions d' usage simples, donc je vais les présenter sous la forme d'imbriquée if, il devrait vous permettre de les lire plus facilement. :)

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

Peut être traduit en:

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

Essaye-le!

Voici le code que j'utilise pour exécuter ceci, vous pouvez le tester en ligne en le copiant-collant.

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)
Katenkyo
la source
1
Ayez un faible pour les réponses plus longues qui ont peu à choisir en raison du choix de la langue.
Matt
@ Matt merci beaucoup pour le soutien! En fait, je trouve toujours le moyen de jouer au golf, mais ça devient de plus en plus difficile!
Katenkyo
2

Lua, 267 octets

Lua 5.3 est requis.

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

Usage:

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

Python 3, 245 243 241 236 octets

sest la chaîne d'entrée, nla sortie est-elle imprimée sur 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)

Edit: Merci à @Cees Timmerman pour la sauvegarde de 5 octets!

pgks
la source
c>' 'andet print nen Python 2.
Cees Timmerman
Tu ne peux pas faire ifau lieu de elif?
Clismique
@ Qwerp-Derp malheureusement pas, je l'ai déjà essayé, mais il affiche, par exemple "! EkanSgnirtSAmAI, olleHello, IAmAStringSnake!" et "SlipperyStSyreppilS".
pgks
Quel est le format d'entrée?
Clismique
La svariable @ Qwerp-Derp est une chaîne multiligne; le dernier caractère de la chaîne doit être une nouvelle ligne (cela est nécessaire pour réussir le Pythontest)
pgks
1

Python, 537

Ma solution initiale:

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))

Compacté un peu, mais laissé comme méthode:

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))
Topkara
la source
1

Java 7, 927 924 923 octets

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);}

Ok, ça a pris un peu de temps .. Dans certains langages de programmation, peu importe que votre tableau x et y se trouvent en dehors des limites d'un tableau 2D, mais avec Java cela jette ArrayIndexOutOfBoundsExceptions, tout doit être vérifié ..

Je détermine d'abord le point de départ, puis utilise une méthode récursive pour construire la chaîne à partir de là. De plus, j'utilise une liste pour garder une trace des coordinations que j'ai déjà rencontrées, ainsi elle ne passera pas dans une boucle de va-et-vient en boucle (donnant ainsi une exception StackOverflowException).

C’est probablement la réponse la plus longue que j’ai publiée jusqu’à présent, mais bien que certaines parties puissent être jouées au golf, je ne pense pas que ce défi puisse être beaucoup plus court en Java. Java ne convient tout simplement pas pour suivre un chemin dans une grille. C'était quand même un défi amusant à comprendre. :)

Ungolfed & cas de test:

Essayez ici.

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    " }));
  }
}

Sortie:

Hello,IAmAStringSnake!
Python
ProgrammingPuzzlesAndCodeGolf
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
SlipperyStringSnakesSilentlySlitherSomewhereSafe
Kevin Cruijssen
la source
924 octets, Jésus-Christ ... lol
Shaun Wild
@BasicallyAlanTuring Hehe. Je me suis contenté de relever le défi, de coder en golf, puis de regarder le nombre d'octets. Était en effet beaucoup plus élevé que prévu, mais ah bon, au moins il est inférieur à 1k ... Si vous voyez quelque chose à améliorer, faites-le-moi savoir, et si vous avez une approche alternative avec (beaucoup) moins d'octets, n'hésitez pas à en faire une autre poster; Je serais intéressé de le voir. PS: C'est maintenant 923 octets. XD
Kevin Cruijssen le
Pas besoin de tout vérifier , il suffit d'ajouter un peu de rembourrage à votre chaîne. Utiliser probablement une seule chaîne multiligne facilite les choses. Jetez un coup d’œil à ma réponse C # en javascript
edc65
1

PHP, 199 184 182 octets

peut encore avoir un peu de potentiel de golf

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;

prend l'entrée en tant que chaîne multiligne à partir de la ligne de commande, attend les sauts de ligne de style linux.
Run php -r '<code>' '<string>'; échapper à la ligne.

panne

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
Titus
la source
1

C #, 310

(Edit: correction de bug)

Une fonction avec un paramètre de chaîne multiligne renvoyant une chaîne.

Y compris le demandé usingdans le nombre d'octets.

Ceci est un portage de ma réponse javascript.

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;}

Test sur ideone

Avec des espaces

    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;
    }
edc65
la source
1

Python 2, 251 octets

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])

Ou, si vous souhaitez diriger les nouvelles lignes dans vos tests, 257 octets:

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])

Passe tous les tests.

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

Résulte en:

SlipperyStringSnakesSilentlySlitherSomewhereSafe
Cees Timmerman
la source
3
Je pense que vous pouvez remplacer b.append(...)par b+=[...]et def n(x,y):return ...avecn=lambda x,y:...
acrolithe
1
Créer une variable pour ' '.
pacholik
1
et utilisez ~-xau lieu de x-1, vous n’aurez pas à utiliser de parenthèses.
Pacholik
0

Japt -P , 106 octets

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

Essayez-le en ligne!

C'est ... euh ... une abomination.

Déballé et comment ça marche

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

Un point remarquable est que j’ai utilisé la priorité des opérateurs entre les opérateurs assignation et les opérateurs de virgule dans JS, afin de compresser certaines lignes et de conserver le raccourci @( XYZ{) utilisable.

Barboteur
la source