Entschlüsseln Sie eine Zeichenfolge


58

Eine reguläre Zeichenfolge sieht folgendermaßen aus:

Hello,IAmAStringSnake!

Und eine String-Schlange sieht ungefähr so ​​aus:

Hel         
  l      rin
  o,IAmASt g
           S
       !ekan

Deine Aufgabe

String-Schlangen sind gefährlich, daher müssen Sie ein Programm erstellen, das eine String-Schlange als Eingabe verwendet und als regulären String ausgibt.

Spezifikationen

  • Die Eingabe kann eine mehrzeilige Zeichenfolge oder ein Array von Zeichenfolgen sein.
  • Jede Zeile der Eingabe wird mit Leerzeichen aufgefüllt, um ein rechteckiges Gitter zu bilden.
  • Charaktere in der Schlange können sich nur mit benachbarten Charakteren verbinden, die sich über, unter, links oder rechts von ihnen befinden (genau wie im Spiel Schlange). Sie können nicht diagonal gehen.
  • Die Schlangencharaktere werden niemals an einen anderen Teil der Schlange angrenzen, sondern nur an die verbundenen Charaktere.
  • Das erste Zeichen der Zeichenfolge ist das Endzeichen mit dem kürzesten Manhattan-Abstand von der linken oberen Ecke des Eingaberasters (dh der minimalen Anzahl von Zügen, die eine Schlange benötigen würde, um direkt vom Endzeichen nach links oben zu gelangen) Ecke). Beide Enden werden niemals den gleichen Abstand haben.
  • Die Zeichenfolge kann ein beliebiges ASCII-Zeichen zwischen den Codepunkten 33 und 126 enthalten (keine Leerzeichen oder Zeilenumbrüche).
  • Die Zeichenfolge ist zwischen 2 und 100 Zeichen lang.
  • Kürzester Code in Bytes gewinnt.

Testfälle

(Eingaberaster, gefolgt von der Ausgabezeichenfolge)

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
Fun Fact: Laut dem verlinkten Wikipedia-Artikel wird Manhattan Distance auch als Snake Distance bezeichnet!
User81655

Wäre eine Eingabe wie hastebin.com/asugoropin.vbs korrekt?
FliiFe

@FliiFe Nein, Teile der Schlange können nicht nebeneinander sein, da nicht immer erkennbar ist, wohin die Schlange geht, wenn dies geschieht (und dies würde die Herausforderung erheblich erschweren). Ich habe der Spezifikation eine Zeile hinzugefügt, um dies zu erklären.
user81655

Kann die Eingabe ein zweidimensionales Array sein (dh jedes Zeichen als Element)?
FliiFe

29
Sicherlich braucht dieses Rätsel eine Antwort in Python?
Abligh

Antworten:


11

APL, 55 Bytes

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

Diese Funktion nimmt eine Zeichenmatrix mit der Zeichenfolge snake auf.

Beispiel:

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

Erläuterung:

  • (,⍵≠' ')/,⍳⍴⍵: Ermittelt die Koordinaten aller Nicht-Leerzeichen
  • (⊂0 0): beginne bei (0,0) (das ist eine ungültige Koordinate)
  • {... }: folge der Schlange, gegebene Position und Schlange:
    • 1<⍴⍵:: wenn mehr als ein Element übrig ist:
      • ∆←⍵~⍺: Entfernen Sie die aktuelle Position von der Schlange und speichern Sie sie in .
      • +/¨|⍺-∆: Finde den Abstand zwischen der aktuellen Position und jedem Punkt im Rest der Schlange
      • ∆[⊃⍋...] `: Finde den nächsten Punkt auf der Schlange
      • : Führen Sie die Funktion erneut aus, wobei der nächstgelegene Punkt der neue aktuelle Punkt und die verkürzte Schlange die neue Schlange ist.
      • ⍺,: füge die aktuelle Position zum Ergebnis hinzu
    • ⋄⍺: Andernfalls geben Sie einfach die aktuelle Position zurück
  • 1↓: lösche den ersten Eintrag aus dem Ergebnis (das ist die (0,0) Position)
  • ⍵[... ]: Holen Sie sich diese Elemente von ⍵, in dieser Reihenfolge

24

JavaScript (ES6) + SnakeEx , 176 Byte

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

Erinnerst du dich an SnakeEx? Gut, denn ich auch nicht! Golfvorschläge sind willkommen.


19

MATL , 80 Bytes

Vielen Dank an @LevelRiverSt für eine Korrektur

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

Die Eingabe erfolgt als 2D-Zeichenfeld mit durch getrennten Zeilen ;. Die Testfälle in diesem Format sind

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

Probieren Sie es online!

Erläuterung

Die Koordinaten jedes Nicht-Leerzeichens werden durch eine komplexe Zahl dargestellt. Für jedes aktuelle Zeichen wird das nächste als dasjenige erhalten, das am nächsten ist (minimale absolute Differenz ihrer komplexen Koordinaten).

Um den Anfangsbuchstaben zu bestimmen, müssen die beiden Endpunkte gefunden werden. Dies geschieht wie folgt. Ein Endpunkt ist ein Nicht-Leerzeichen, das genau einen Nicht-Leerzeichen-Nachbarn hat. Die Anzahl der Nachbarn wird durch 2D-Faltung mit einer geeigneten Maske erhalten. Der Anfangspunkt ist der Endpunkt, dessen komplexe Koordinate die geringste Summe von Real- und Imaginärteilen aufweist. dh ist in Manhattan am nächsten an der komplexen Zahl 0 oder äquivalent zu 1 + 1j, der komplexen Koordinate der oberen linken Ecke.

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

Ich gehe davon aus, dass eine Erklärung bevorsteht.
Matt

@ Matt Sicher ... später am Tag :-)
Luis Mendo

Erklärung hinzugefügt @Matt
Luis Mendo

The initial point is the endpoint whose complex coordinate has the least absolute valueAchtung: Euklidische Distanz! = Manhattan Distanz. Zum Beispiel hat der Punkt 7 + 7j eine euklidische Entfernung 9,8994 und eine Manhattan-Entfernung 14. 10j ist weiter von der euklidischen Entfernung entfernt, aber wesentlich näher von der Manhattan-Entfernung. Ansonsten tolles Konzept!
Level River St

@LevelRiverSt Danke! Korrigiert
Luis Mendo

14

C 198 190 179 180 181 Bytes

Bearbeiten: Benutzte den Tipp von user81655 und entfernte die Klammer im ternären Operator, danke! Ich habe auch den umständlichen (S & 1) Test auf Gleichmäßigkeit geändert, um den angemesseneren (und kürzeren!) S% 2 zu erhalten.

Edit2: Die Verwendung des Adressierungsstils * a hat mich blind gemacht für die offensichtlichen Optimierungen in der Definition von S, dh das Ersetzen von * (a + m) durch [m] usw. Ich habe dann S selbst durch T ersetzt, was im Wesentlichen zutrifft die Hälfte von dem, was S macht. Der Code nutzt jetzt auch den Rückgabewert von putchar.

Edit3: Behobener Fehler, der von Anfang an auftrat. Das Manhattan-Suchstoppkriterium a <b + m ist nur dann korrekt, wenn a bereits dekrementiert wurde. Dies fügt 2 Bytes hinzu, aber eines wird wiederhergestellt, indem die Definition von m global gemacht wird.

Edit4: Mein Golfen hat das Minimum überschritten und geht jetzt in die falsche Richtung. Ein weiterer Bugfix im Zusammenhang mit der Manhattan-Suche. Ich hatte ursprünglich eingehende Prüfungen eingerichtet, und ohne diese wurde die Suche nach großen Eingabearrays (etwa 50 x 50) über das Array hinaus fortgesetzt. B. Daher muss dieses Array auf mindestens das Doppelte der vorherigen Größe erweitert werden, wodurch ein weiteres Byte hinzugefügt wird.

#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 und erklärte:

/* 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
Diese Antwort ist großartig.
abligh

+1 Das ist großartig. Ich möchte meiner Antwort eine Erklärung hinzufügen, aus der hervorgeht, wo ich im Vergleich zu Ihrer Lösung Bytes verloren habe. Ist das in Ordnung?
MIllIbyte

mIllIbyte - zögern Sie nicht, die Kommentare hinzuzufügen, das ist der Weg zu neuen Ideen.
Zunga

user81655 - danke für den tipp, es hat 6 bytes gespart. Tatsächlich habe ich gestern versucht, S% 2 anstelle von (S & 1) zu verwenden, wodurch weitere 2 Byte gespart wurden, aber aus irgendeinem Grund (mein Code war an einem anderen Ort fehlerhaft) funktionierte dies nicht richtig. Jetzt scheint alles in Ordnung zu sein.
Zunga

Sehr schön. Sparen Sie noch mehr mit a[1], a[-m]etc, und machen mglobal - m=103;main().
Ugoren

9

C 272 Bytes

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

Schauen Sie sich die Quelle von @ Zunga an. Nun sieh dir meine an. Möchten Sie wissen, wie ich die zusätzlichen 91 Bytes erhalten habe?
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;}}

5

Python (2 und 3), 640 624 604 583 575 561 546 538 Bytes

Ich bin immer noch ein Golf-N00B, das ist also ein bisschen groß.

Edit: Danke an @porglezomp für die Vorschläge! Ich habe nicht alle 'und' Operatoren entfernt, da dies Python 3 beschädigen würde.

Edit2: Danke an @Aleksi Torhamo für den Kommentar zu isspace (). Die daraus resultierende Reduzierung gleicht den von mir eingebrachten Bugfix aus. Auch dank anonymous für die Syntaxhervorhebung!

Edit3: Danke an @ mbomb007 für ein paar zusätzliche Bytes.

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

Und hier ist meine Pre-Golf-Version

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
Ich habe 12 Bytes gespart, indem ich eingeführt habe S=lambda s:s.isspace()und dann getan habe, S(s)anstatt s.isspace().
Porglezomp

1
Ich glaube , Sie auch alle Ihre ändern können and zu <, da f() < g() < h()die gleichen wie g = g(); f() < g and g < h()in Bezug auf Nebenwirkungen (Vergleichsketten Kurzschluss), und Sie sind das Ergebnis der Vergleiche ohnehin ignorieren.
Porglezomp

1
m[(x,y)]=ist das gleiche wie die kürzerem[x,y]=
Porglezomp

2
@porglezomp: Es ist noch kürzer zu sagenS=str.isspace
Aleksi Torhamo

1
Das Entfernen Sund Verwenden kann <'!'bei jedem Auftreten gleich lang sein, was möglicherweise die Möglichkeit eröffnet, mehr zu sparen. Zum Beispiel wechseln if 1-S(v[x]):zu if(v[x]<'!')<1:. Und vielleicht könnten Sie auf diese Weise einige Klammern in den späteren Vergleichen entfernen.
mbomb007

4

JavaScript (ES6), 195

Siehe Erklärung im Test-Snippet

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

Prüfung

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>


Werden die Semikolons ););}benötigt?
Cees Timmerman

1
@ CeesTimmerman ja. Der erste befindet sich in der forKopfzeile, in der 2 Doppelpunkte erforderlich sind. Der zweite ist der Delimeter für den forKörper
edc65

3

Lua, 562 535 529 513 507 504 466 458 Bytes

Mein derzeit mit Abstand massivstes Golfspiel, ich denke, ich kann immer noch 100 Bytes abschneiden, worauf ich hinarbeiten werde, aber es als Antwort posten, da es schon einige Zeit gedauert hat :). Ich hatte recht, ich habe mehr als 100 Bytes gekürzt! Ich denke nicht, dass es viel Raum für Verbesserungen gibt.

Diese Funktion muss mit einem 2D-Array aufgerufen werden, das ein Zeichen pro Zelle enthält.

40 Bytes bei der Arbeit mit @KennyLau gespart , dank ihm!

Woohoo! Unter 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

Sobald ich mit dem Golfen fertig bin, werden Erklärungen folgen. Im Moment leihe ich Ihnen eine lesbare Version dieses Quellcodes: D Hier kommen die Erklärungen!

Bearbeiten: nicht mit der neuesten Änderung aktualisiert, noch vor dem Aktualisieren golfen. Gleiches gilt für die Erklärungen

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

Hier finden Sie einige detaillierte Erklärungen zur Funktionsweise dieses Programms.

Betrachten wir zunächst die Schleife mit der Bezeichnung a, damit wir das nächste Ende in der oberen linken Ecke finden können. Es wird für immer wiederholt, wenn es kein Ende gibt, aber das ist kein Problem: D.

Auf einem 4x4-Gitter sind hier die Schlangenabstände (links) und die Reihenfolge, in der sie betrachtet werden (rechts).

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

Damit jedes dieser Zeichen das Ende ist, müssen zwei Bedingungen überprüft werden: - Kein Leerzeichen - Umgeben von genau 3 Leerzeichen (oder genau 1 Nicht-Leerzeichen)

Diese Bedingungen werden im folgenden Code überprüft

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

Durch den Ausdruck wird überprüft, ob das Zeichen kein Leerzeichen ist m[i][j]~=s.

Wenn Sie überprüfen, ob nur 1 Nicht-Leerzeichen vorhanden ist, indem Sie die obigen Bedingungen für unsere Umgebung angeben, kann dies folgendermaßen geschrieben werden

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

Und schließlich, wenn alle oben genannten Werte als wahr ausgewertet werden, gibt der Ternär das zurück, was in der letzten and-> steht m[i][j]. Sonst lassen wir los r:)

Jetzt, wo wir den Schlangenkopf haben, gehen wir zum anderen Ende! Das Iterieren der Schlange wird hauptsächlich durch die folgenden geschachtelten Ternaries erreicht:

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

Wir werden zurückgesetzt iund jzur gleichen Zeit, um zu vermeiden, dass Dummies zum Speichern der alten Werte benötigt werden. Beide haben die exakt gleiche Struktur und verwenden einfache Bedingungen. Deshalb werde ich sie in Form von verschachtelten präsentieren if, damit Sie sie lesen können noch einfacher. :)

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

Kann übersetzt werden in:

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

Probier es aus!

Hier ist der Code, den ich verwende, um dies auszuführen. Sie können ihn online testen, indem Sie ihn kopieren und einfügen.

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
A hat ein Faible für längere Antworten, die aufgrund der Sprachauswahl nur eine geringe Auswahl haben.
Matt

@Matt vielen Dank für die Unterstützung! Eigentlich finde ich immer noch Möglichkeiten, um Golf zu spielen, aber es wird immer schwieriger!
Katenkyo

2

Lua, 267 Bytes

Lua 5.3 ist erforderlich.

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

Verwendungszweck:

$ 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

Python 3, 245 243 241 236 Bytes

sist die Eingabezeichenfolge, nwird die Ausgabe auf stdout gedruckt:

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: Danke an @Cees Timmerman für das Speichern von 5 Bytes!


c>' 'andund print nin Python 2.
Cees Timmerman

Kannst du nicht ifstatt elif?
Clismique

@ Qwerp-Derp habe ich leider nicht ausprobiert, aber es druckt zB "! EkanSgnirtSAmAI, olleHello, IAmAStringSnake!" und "SlipperyStSyreppilS".
pgks

Was ist das Eingabeformat?
Clismique

@ Qwerp-Derp- sVariable ist eine mehrzeilige Zeichenfolge. Das letzte Zeichen der Zeichenfolge muss ein Zeilenumbruch sein (dies ist erforderlich, um den PythonTestfall zu bestehen)
pgks

1

Python, 537

Meine anfängliche Lösung:

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

Ein bisschen komprimiert, aber als Methode belassen:

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

Java 7, 927 924 923 Bytes

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, das hat eine Weile gedauert. In einigen Programmiersprachen spielt es keine Rolle, ob Ihr Array x und y außerhalb der Grenzen eines 2D-Arrays liegt, aber mit Java wird es geworfen ArrayIndexOutOfBoundsExceptions, also muss alles überprüft werden.

Ich bestimme zuerst den Startpunkt und benutze dann eine rekursive Methode, um die Zeichenfolge von dort zu erstellen. Außerdem verwende ich eine Liste, um die bereits aufgetretenen Koordinierungen zu protokollieren, damit sie nicht in einer Schleife vor und zurück ablaufen (was zu einer StackOverflowException führt).

Dies ist wahrscheinlich die längste Antwort, die ich bisher gepostet habe, aber obwohl einige Teile golfen können, glaube ich nicht, dass diese Herausforderung in Java so viel kürzer sein kann. Java ist einfach nicht geeignet, um einem Pfad in einem Raster zu folgen. Trotzdem war es eine lustige Herausforderung, dies herauszufinden. :)

Ungolfed & Testfälle:

Probieren Sie es hier aus.

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

Ausgabe:

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

924 bytes, jesus christ ... lol
Shaun Wild

@BasicallyAlanTuring Hehe. Ich habe die Herausforderung einfach gemeistert, mit Code gespielt und dann die Byteanzahl überprüft. War zwar viel höher als erwartet, aber na ja, zumindest ist es unter 1k ... Wenn Sie Verbesserungsvorschläge sehen, lassen Sie es mich wissen, und wenn Sie einen alternativen Ansatz mit (viel) weniger Bytes haben, können Sie einen separaten Ansatz erstellen Post; Es würde mich interessieren, es zu sehen. PS: Es ist jetzt 923 Bytes. XD
Kevin Cruijssen

Es ist nicht nötig, alles zu überprüfen , füge einfach ein wenig Abstand zu deiner Saite hinzu. Die Verwendung einer einzelnen mehrzeiligen Zeichenfolge macht dies wahrscheinlich einfacher.
Werfen

1

PHP, 199 184 182 Bytes

hat vielleicht noch ein wenig golfpotential

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;

Nimmt die Eingabe als mehrzeilige Zeichenfolge von der Befehlszeile und erwartet Zeilenumbrüche im Linux-Stil.
Run php -r '<code>' '<string>'; Entkomme Zeilenumbrüchen.

Nervenzusammenbruch

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

(Edit: Bugfix)

Eine Funktion mit einem mehrzeiligen Zeichenfolgenparameter, der eine Zeichenfolge zurückgibt.

Einbeziehen der angeforderten usingin die Byteanzahl.

Dies ist eine Portierung meiner Javascript-Antwort.

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 auf Ideone

Mit Leerzeichen

    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

Python 2, 251 Bytes

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

Oder, wenn Sie führende Zeilen in Ihren Testfällen haben möchten, 257 Bytes:

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

Besteht alle Testfälle.

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

Ergebnisse in:

SlipperyStringSnakesSilentlySlitherSomewhereSafe

3
Ich denke, Sie können b.append(...)mit b+=[...]und def n(x,y):return ...mit ersetzenn=lambda x,y:...
Acrolith

1
Erstellen Sie eine Variable für ' '.
Pacholik

1
und verwenden ~-xstatt x-1, müssen Sie keine Klammern verwenden.
Pacholik

0

Japt -P , 106 Bytes

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

Probieren Sie es online!

Es ist ... ähm ... ein Gräuel.

Ausgepackt und wie es funktioniert

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

Ein bemerkenswerter Punkt ist, dass ich in JS die Operator-Rangfolge zwischen Zuweisungs- und Komma-Operatoren verwendet habe, um einige Zeilen zu packen und die shortcut @( XYZ{) verwendbar zu halten.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.