De-Snakify a String


58

สตริงปกติมีลักษณะดังนี้:

Hello,IAmAStringSnake!

และงูสตริงมีลักษณะดังนี้:

Hel         
  l      rin
  o,IAmASt g
           S
       !ekan

งานของคุณ

สตริงงูมีอันตรายดังนั้นคุณต้องสร้างโปรแกรมที่ใช้งูสตริงเป็นอินพุตและเอาต์พุตเป็นสตริงปกติ

ข้อมูลจำเพาะ

  • อินพุตสามารถเป็นสตริงหลายบรรทัดหรืออาร์เรย์ของสตริง
  • แต่ละบรรทัดของอินพุตจะถูกเสริมด้วยช่องว่างเพื่อสร้างตารางสี่เหลี่ยม
  • ตัวละครในงูสามารถเชื่อมต่อกับตัวละครที่อยู่ติดกันด้านบนด้านล่างซ้ายหรือขวาของพวกเขา (เช่นเดียวกับในเกมงู) พวกเขาไม่สามารถไปในแนวทแยง
  • ตัวละครงูจะไม่ติดกับส่วนอื่นของงูตัวละครที่เชื่อมต่อเท่านั้น
  • อักขระตัวแรกของสตริงคืออักขระสุดท้ายที่มีระยะทางแมนฮัตตันสั้นที่สุดจากมุมบนซ้ายของตารางอินพุต (เช่นจำนวนการเคลื่อนไหวขั้นต่ำสุดที่งูจะต้องใช้โดยตรงจากอักขระสิ้นสุดไปยังด้านบนซ้าย มุม). ปลายทั้งสองจะไม่มีระยะห่างเท่ากัน
  • สตริงสามารถมีอักขระ ASCII ใด ๆ ระหว่างจุดรหัส 33 ถึง 126 รวม (ไม่มีช่องว่างหรือขึ้นบรรทัดใหม่)
  • สตริงจะมีความยาวระหว่าง 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
Fun Fact: ตามบทความ Wikipedia ที่เชื่อมโยงระยะทางแมนฮัตตันเป็นที่รู้จักกันว่าระยะห่างจากงู!
user81655

อินพุตเช่นhastebin.com/asugoropin.vbsจะถูกต้องหรือไม่
FliiFe

@FliiFe ไม่ชิ้นส่วนของงูไม่สามารถอยู่ติดกันได้เพราะมันเป็นไปไม่ได้เสมอที่จะบอกว่างูกำลังจะเกิดขึ้นเมื่อเกิดเหตุการณ์นี้ขึ้น (และมันจะทำให้การท้าทายยากขึ้นมาก) ฉันเพิ่มบรรทัดลงในข้อมูลจำเพาะเพื่ออธิบายสิ่งนี้
user81655

อินพุตสามารถเป็นอาร์เรย์สองมิติ (เช่นอักขระแต่ละตัวเป็นองค์ประกอบ) ได้หรือไม่?
FliiFe

29
ปริศนานี้ต้องการคำตอบใน python ไหม?
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 องค์ประกอบที่เหลือ:
      • ∆←⍵~⍺: เอาตำแหน่งปัจจุบันจากงูและเก็บไว้ใน
      • +/¨|⍺-∆: หาระยะห่างระหว่างตำแหน่งปัจจุบันและแต่ละจุดในส่วนที่เหลือของงู
      • ∆[⊃⍋...] `: รับจุดที่ใกล้ที่สุดกับงู
      • : เรียกใช้ฟังก์ชั่นอีกครั้งโดยมีจุดที่ใกล้เคียงที่สุดกับจุดปัจจุบันใหม่และงูสั้นลงเป็นงูใหม่
      • ⍺,: เพิ่มตำแหน่งปัจจุบันไปยังผลลัพธ์ของสิ่งนั้น
    • ⋄⍺: มิฉะนั้นเพียงแค่คืนสถานะปัจจุบัน
  • 1↓: วางรายการแรกจากผลลัพธ์ (ซึ่งคือตำแหน่ง (0,0))
  • ⍵[... ]: รับองค์ประกอบเหล่านั้นจาก⍵ตามลำดับ

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

การป้อนข้อมูลเป็นอาร์เรย์ 2 ;มิติของถ่านกับแถวแยกจากกันโดย กรณีทดสอบในรูปแบบนี้คือ

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

ลองออนไลน์!

คำอธิบาย

พิกัดของอักขระที่ไม่ว่างแต่ละตัวจะถูกแทนด้วยจำนวนเชิงซ้อน สำหรับอักขระปัจจุบันแต่ละตัวจะได้รับสิ่งถัดไปตามที่ใกล้เคียงที่สุด

ในการกำหนด char เริ่มต้นต้องพบจุดปลายทั้งสอง ซึ่งทำได้ดังนี้ จุดปลายคือถ่านแบบไม่มีช่องว่างที่มีเพื่อนบ้านที่ไม่ใช่พื้นที่ว่างอย่างแน่นอน จำนวนเพื่อนบ้านได้มาจากการบิด 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

เพิ่มคำอธิบาย @Matt
Luis Mendo

The initial point is the endpoint whose complex coordinate has the least absolute valueระวัง: ระยะทางแบบยุคลิด! = ระยะทางแมนฮัตตัน ตัวอย่างเช่นจุดที่ 7 + 7j มีระยะทางแบบยุคลิด 9.8994 และระยะห่างจากแมนฮัตตัน 14. 10j นั้นขึ้นอยู่กับระยะทางแบบยุคลิด แต่ไกลกว่ามากโดยระยะทางแบบแมนฮัตตัน นอกเหนือจากนั้นแนวคิดที่ยอดเยี่ยม!
เลเวลริเวอร์เซนต์

@LevelRiverSt ขอบคุณ! แก้ไขแล้ว
Luis Mendo

14

C 198 190 179 180 181 ไบต์

แก้ไข: ใช้เคล็ดลับโดย user81655 และลบวงเล็บในผู้ประกอบการที่สามขอบคุณ! ฉันยังเปลี่ยนการทดสอบที่ยุ่งยาก (S & 1) เพื่อความสมดุลสำหรับความสมดุล (และที่สั้นกว่า!) S% 2

แก้ไข 2: การใช้สไตล์การกำหนดที่อยู่ * อย่างหนักทำให้ฉันตาบอดกับการปรับให้เหมาะสมที่ชัดเจนในคำจำกัดความของ S คือการแทนที่ * (a + m) ด้วย [m] ฯลฯ ฉันจึงแทนที่ S ด้วย T ซึ่งเป็นหลัก ครึ่งหนึ่งของสิ่งที่ S ทำ ตอนนี้โค้ดยังใช้ประโยชน์จากค่าส่งคืนของ putchar

แก้ไข 3: แก้ไขข้อผิดพลาดที่มีมาตั้งแต่ต้นเกณฑ์การหยุดการค้นหาในแมนฮัตตัน a <b + m นั้นถูกต้องเฉพาะเมื่อ a ถูกลดระดับลงไปแล้ว สิ่งนี้เพิ่ม 2 ไบต์ แต่มีการคืนค่าด้วยการทำให้คำจำกัดความของ m global

แก้ไข 4: การเล่นกอล์ฟของฉันผ่านขั้นต่ำและไปในทางที่ผิดตอนนี้ แก้ไขข้อผิดพลาดอื่นที่เกี่ยวข้องกับการค้นหาแมนฮัตตัน ตอนแรกฉันมีการตรวจสอบภายในและไม่มีการค้นหาต่อเนื่องสำหรับอินพุตขนาดใหญ่ (ที่ใดที่หนึ่งรอบ 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);}

Ungolfed และอธิบาย:

/* 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

mIllIbyte - อย่าลังเลที่จะเพิ่มความคิดเห็นนั่นคือหนทางสู่แนวคิดใหม่ ๆ
Zunga

user81655 - ขอบคุณสำหรับเคล็ดลับมันโกนออก 6 ไบต์ ในความเป็นจริงฉันลองใช้เมื่อวานนี้รวมถึงใช้ S% 2 แทน (S & 1) ซึ่งโกนออกไปอีก 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- พิเศษไบต์?
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 และ 3), 640 624 604 583 575 561 546 538 ไบต์

ฉันยังเป็นนักกอล์ฟอยู่ n00b ดังนั้นนี่จึงค่อนข้างใหญ่

แก้ไข: ขอบคุณ@porglezompสำหรับคำแนะนำ! ฉันไม่ได้ลบตัวดำเนินการ 'และ' ทั้งหมดเนื่องจากจะทำให้ Python 3 หยุดทำงาน

แก้ไข 2: ขอบคุณ@Aleksi Torhamoสำหรับความคิดเห็นเกี่ยวกับ isspace () การลดลงที่เกิดขึ้นจะชดเชยข้อผิดพลาดที่ฉันใส่เข้าไปและต้องขอบคุณการไม่ระบุชื่อสำหรับการเน้นไวยากรณ์

แก้ไข 3: ขอบคุณ@ 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
ฉันบันทึก 12 ไบต์โดยการแนะนำS=lambda s:s.isspace()แล้วทำแทนS(s) 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

JavaScript (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 ใช่ อันแรกอยู่ในforส่วนหัวที่ต้องการ 2 โคลอน ประการที่สองคือขอบเขตสำหรับforร่างกาย
edc65

3

Lua, 562 535 529 513 507 504 466 458 ไบต์

ตอนนี้ฉันคิดว่าฉันยังคงสามารถตัดกอล์ฟได้ถึง100 ไบท์ซึ่งฉันจะทำงานต่อไป แต่การโพสต์มันเป็นคำตอบเพราะใช้เวลาพอสมควรแล้ว :) ฉันพูดถูกฉันได้ตัดมันมากกว่า 100 ไบต์! ฉันไม่คิดว่าจะมีการปรับปรุงมากนัก

ต้องเรียกใช้ฟังก์ชันนี้ด้วยอาร์เรย์ 2D ที่มีอักขระหนึ่งตัวต่อเซลล์

บันทึก 40 ไบต์ขณะทำงานกับ@KennyLauขอบคุณเขา!

ดีจัง! ต่ำกว่า 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

คำอธิบายจะมาถึงเมื่อฉันเล่นกอล์ฟเสร็จแล้วในตอนนี้ฉันจะให้คุณยืมเวอร์ชั่นที่อ่านได้ของซอร์สโค้ดนี้: 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 ช่อง (หรือ 1 ช่อง)

เงื่อนไขเหล่านี้จะถูกตรวจสอบชิ้นส่วนของรหัสต่อไปนี้

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

m[i][j]~=sตรวจสอบว่าถ่านที่ไม่ได้เป็นพื้นที่ที่จะทำได้โดยการแสดงออก

การตรวจสอบว่าเราถูกล้อมรอบด้วยพื้นที่ที่ไม่ได้มีเพียงแค่ 1 อันเท่านั้นที่ได้รับผลกระทบจากเงื่อนไขข้างต้นสำหรับสภาพแวดล้อมของเราหรือไม่นี่อาจเขียนเป็น

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

และสุดท้ายถ้าทั้งหมดข้างต้นคือการประเมินจริง ternary จะกลับสิ่งที่อยู่ในช่วง->and m[i][j]มิฉะนั้นเราปล่อยให้rตั้ง :)

ตอนนี้เรามีหัวงูแล้วไปต่อจนสุดทาง! การย้ำงูเป็นส่วนใหญ่สำเร็จโดย ternaries ซ้อนกันต่อไปนี้:

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
A มีจุดอ่อนสำหรับคำตอบอีกต่อไปที่มีทางเลือกน้อยถึงตอนนี้เนื่องจากการเลือกภาษา
Matt

@ Matt ขอบคุณมากสำหรับการสนับสนุน! จริงๆแล้วฉันยังคงหาวิธีในการตีกอล์ฟลง แต่มันก็ยากขึ้นเรื่อย ๆ !
Katenkyo

2

Lua 267 ไบต์

ต้อง Lua 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

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

แก้ไข:ขอบคุณ @Cees Timmerman สำหรับการบันทึก 5 ไบต์!


c>' 'andและprint nใน Python 2
Cees Timmerman

คุณทำifแทนelifไม่ได้ใช่ไหม
clismique

@ Qwerp-Derp น่าเสียดายที่ฉันไม่เคยลองมาก่อน แต่มันพิมพ์เช่น "! ekanSgnirtSAmAI, olleHello, IAmAStringSnake!" และ "SlipperyStSyreppilS"
pgks

รูปแบบอินพุตคืออะไร
clismique

sตัวแปร@ Qwerp-Derp เป็นสตริงหลายบรรทัด อักขระตัวสุดท้ายของสตริงจะต้องขึ้นบรรทัดใหม่ (จำเป็นต้องผ่านPythonกรณีทดสอบ)
pgks

1

Python 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

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

ตกลง, ใช้เวลาสักครู่ .. ในบางภาษาการเขียนโปรแกรมมันไม่สำคัญว่าอาเรย์ของคุณและ y จะอยู่นอกขอบเขตของอาเรย์ 2 มิติ แต่ด้วยจาวามันจะโยนArrayIndexOutOfBoundsExceptionsดังนั้นทุกอย่างจะต้องมีการตรวจสอบ ..

ฉันก่อนกำหนดจุดเริ่มต้นแล้วใช้วิธีการซ้ำเพื่อสร้างสตริงจากที่นั่น นอกจากนี้ฉันใช้รายการเพื่อติดตามการเรียงลำดับที่ฉันเคยพบมาแล้วดังนั้นมันจะไม่ไปวนซ้ำไปมาย้อนกลับ (ส่งผลให้ StackOverflowException)

นี่อาจเป็นคำตอบที่ยาวที่สุดที่ฉันโพสต์จนถึงตอนนี้ แต่ถึงแม้ว่าบางส่วนสามารถเล่นกอล์ฟได้ แต่ฉันไม่คิดว่าความท้าทายนี้จะสั้นกว่านี้มากใน 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 ไบต์พระเยซูคริสต์ ... ฮ่า ๆ
Shaun Wild

@BasicallyAlanTuring Hehe ฉันแค่ทำสิ่งที่ท้าทายรหัสก็เล่นกอล์ฟแล้วมองไปที่จำนวนไบต์ แน่นอนสูงกว่าที่คาดไว้มาก แต่ก็ดีอย่างน้อยก็ต่ำกว่า 1k ... ถ้าคุณเห็นอะไรที่ต้องปรับปรุงให้ฉันรู้และถ้าคุณมีวิธีการอื่นที่มีไบต์น้อยกว่า (มาก) ให้แยกออกจากกัน โพสต์; ฉันสนใจที่จะเห็นมัน PS: ตอนนี้เป็น 923 ไบต์ XD
Kevin Cruijssen

ไม่จำเป็นต้องตรวจสอบทุกหัวข้อเพียงเพิ่มการเติมเข้าไปในสายอักขระของคุณ อาจใช้สตริงหลายบรรทัดทำให้ง่ายขึ้น ดูคำตอบ C # ของฉันถูกย้ายจาก javascript แล้ว
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;

รับอินพุตเป็นสตริงหลายบรรทัดจากบรรทัดคำสั่งคาดว่าจะมีการแบ่งบรรทัดสไตล์ของ linux
วิ่งphp -r '<code>' '<string>'; หนี linebreaks

ชำรุด

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

ทดสอบ บน ideone

พร้อมช่องว่าง

    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 ไบต์

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

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