Cắt thử thách nghệ thuật ASCII


13

Nghệ thuật ASCII rất thú vị. Trình soạn thảo văn bản hiện đại rất giỏi trong việc thao tác văn bản. Là ngôn ngữ lập trình hiện đại lên đến nhiệm vụ?

Một nhiệm vụ phổ biến trong thao tác nghệ thuật ASCII là cắt văn bản thành hình chữ nhật giữa hai ký tự. Đây là nhiệm vụ bạn phải thực hiện trong thử thách này.

Chi tiết

Chương trình của bạn sẽ có 3 đầu vào:

  • đầu tiên là ký tự 'bắt đầu' của khối - đánh dấu góc trên cùng bên trái
  • thứ hai là ký tự 'kết thúc' của khối - đánh dấu góc dưới bên phải
  • thứ ba là một số dạng văn bản đa dòng, hoặc một chuỗi, hoặc danh sách các chuỗi, hoặc tên tệp, hoặc bất cứ điều gì

Kết quả sẽ là văn bản nhiều dòng (một lần nữa, trong bất kỳ định dạng nào ở trên) được cắt thành hình chữ nhật giữa các đầu vào đã cho. Lưu ý rằng hai đầu vào đầu tiên có thể không phải là duy nhất.

Trường hợp cạnh

Các hộp phải luôn có thể tích ít nhất là 2. Do đó:

()     (
       )

là những hộp nhưng đây là:

)(     )      (
       (     )

không (với start = (và end = )).

Đầu vào sẽ chỉ chứa một hộp. Do đó, các ký tự bắt đầu và kết thúc chỉ phải xảy ra một lần, trừ khi chúng là cùng một ký tự trong trường hợp chúng phải xảy ra chính xác hai lần.

Ngoài ra, mỗi dòng trong đầu vào phải dài ít nhất là khoảng cách từ điểm bắt đầu của dòng đến cạnh phải của hộp trong đầu vào.

Chương trình của bạn không cần xử lý các đầu vào không hợp lệ; họ có thể dẫn đến hành vi không xác định.

Quy tắc

Quy tắc golf-golf điển hình áp dụng. Mã ngắn nhất sẽ thắng.

Ví dụ

Ngày nắng: start: ( end: ) input:

This is some text
. (but this text
  is in a box  ).
So only it is important.

Đầu ra:

(but this text
is in a box  )

Lưu ý tước bỏ không gian ngang là tốt. Cây nghệ thuật ASCII là 2d.

Ngày mưa: start: ( end: ) input:

This is some text (
But is that even  )
really a box?

Đầu ra:

(
)

Bắt đầu / kết thúc giống nhau: start: / end: / input:

Oh, I get how this could be useful
 /----------------------------\
 | All this text is in a box! |
 \----------------------------/

Đầu ra:

/----------------------------\
| All this text is in a box! |
\----------------------------/

Đâu vao không hợp lệ: start: ( end: ) input:

Boxes are rectangular ( so this has
0 volume ) which is illegal.

Đầu vào 2 không hợp lệ: start: ( end: ) input:

(The lines must already be square 
so this line that is too short
relative to this end, is illegal)

Điều gì về một hộp hợp lệ với một dòng bên ngoài ngắn hơn hộp?
seadoggie01

1
làm rõ, đầu vào cũng không hợp lệ
LambdaBeta

Điều gì sẽ là kết quả trong trường hợp đầu vào không hợp lệ? hoặc họ được đề cập để họ sẽ không phải được chăm sóc?
Uriel

1
Kết quả giống như hành vi không xác định trong C, đừng lo lắng về điều đó, mọi thứ đều ổn.
LambdaBeta

Đây là một thách thức nhỏ khó chịu: công việc tốt đẹp!
seadoggie01

Câu trả lời:


15

Vim, 16 , 12 byte / tổ hợp phím

#<C-v>Nj*yggVGp

Hãy thử trực tuyến! trong trình thông dịch V

Trình soạn thảo văn bản hiện đại rất giỏi trong việc thao tác văn bản. Là ngôn ngữ lập trình hiện đại lên đến nhiệm vụ?

Tôi đặt cược các trình soạn thảo văn bản thậm chí còn tốt hơn! : D

Mặc dù không nhất thiết phải có, câu trả lời này không hoạt động với cả hai đầu vào "không hợp lệ" đã cho, xuất ra

 rectangular (
) which is ill

(The lines must already be square
so this line that is too short
relative to this end, is illegal)

Giải trình:

#               " Move backward to the previous occurrence of the word (or in this case, character) under the cursor
 <C-v>          " Start a visual block selection
      N         " Go to the next occurrence of the last searched term (guaranteed to be line 1)
       j        " Move down a line
        *       " Move forward to the next occurrence of the character under the cursor
         y      " Yank (copy) the whole visually selected block
          gg    " Go to line 1
            VG  " Select every line
              p " And paste what we last copied over it, deleting the whole buffer and replacing it with the block

1
Ngẫu nhiên đây chính xác là trường hợp sử dụng mà tôi đang làm để nhắc tôi viết thử thách này. Tôi đã có macro macro q của tôi /\/<cr><c-v>nygv$o0dphoặc một cái gì đó tương tự quá lâu :)
LambdaBeta

2
Vâng, hình chữ nhật là xấu nhất !
admBorkBork

6

Thạch , 13 byte

=€SŒṪr/,þ/Zœị

Một liên kết dyadic chấp nhận một danh sách các ký tự bắt đầu và kết thúc ở bên trái và một danh sách các dòng (dưới dạng danh sách các ký tự) ở bên phải, trong đó đưa ra một danh sách các dòng (dưới dạng danh sách các ký tự).

Hãy thử trực tuyến!(chương trình đầy đủ - nếu đầu vào là Python hợp lệ, họ sẽ yêu cầu trích dẫn chuỗi Python.)

Làm sao?

=€SŒṪr/,þ/Zœị - Link: [start, stop], lines
 €            - for each (of [start, stop]):
=             -   equals? (vectorises across the lines)
  S           - sum (vectorises)
   ŒṪ         - multi-dimensional truthy (i.e. non-zero) indices
      /       - reduce by:
     r        -   inclusive range (vectorises)
         /    - reduce by:
        þ     -    outer product with:
       ,      -       pair
          Z   - transpose
           œị - multi-dimensional index-into (the lines)

Ví dụ: với left = ['a', 'b']và right (dưới dạng danh sách các danh sách các ký tự - các dòng):

--------
--a+++--
--++++--
--+++b--
--------

=€mang lại một danh sách gồm hai danh sách các danh sách (lần đầu tiên thực hiện 'a'=, lần thứ hai 'b'=):

00000000         00000000
00100000         00000000
00000000    ,    00000000
00000000         00000100
00000000         00000000

tóm tắt điều này mang lại một danh sách duy nhất của danh sách (tóm tắt yếu tố khôn ngoan):

00000000
00100000
00000000
00000100
00000000

ŒṪsau đó cung cấp cho chúng tôi các chỉ số đa chiều (1 chỉ mục) của các số không, [[2,3],[4,6]]- tức là [[top,left],[bottom,right]].

r/sau đó thực hiện [2,3]r[4,6]mà, vì rvectơ, giống như [2r4, 3r6], đánh giá [[2,3,4],[3,4,5,6]]- tức là [rows,columns].

,þ/sau đó thực hiện [2,3,4],þ[3,4,5,6]nơi þlà một lệnh ngoài vỏ và ,là cặp. Điều này mang lại tất cả các [row,column]giá trị theo cột, trong trường hợp này:

[[[2,3],[3,3],[4,3]],
 [[2,4],[3,4],[4,4]],
 [[2,5],[3,5],[4,5]],
 [[2,6],[3,6],[4,6]]]

Chúng tôi muốn những thứ này theo hàng, vì vậy Zđược sử dụng để chuyển cái này sang:

[[[2,3],[2,4],[2,5],[2,6]],
 [[3,3],[3,4],[3,5],[3,6]],
 [[4,3],[4,4],[4,5],[4,6]]]

Cuối cùng œịlập chỉ mục trở lại vào các dòng đầu vào:

a+++
++++
+++b

Điều đáng chú ý là khi cả hai nhân vật bị ràng buộc giống nhau =€đều xác định cả hai lần nhưng SŒṪcuối cùng lại làm điều đúng, vì đó 2là sự thật, ví dụ như ['a','a']:

--------         00000000   00000000        00000000
--a+++--         00100000   00100000        00200000
--++++--  =€ ->  00000000 , 00000000  S ->  00000000  ŒṪ ->  [[2,3],[4,6]]
--+++a--         00000100   00000100        00000020
--------         00000000   00000000        00000000

... Tôi đã đọc lời giải thích, nhưng tôi vẫn không hiểu nó. o_o Bạn có thể thêm một ví dụ làm việc, có lẽ?
DLosc

Khuyến khích: Tôi sẽ chấp nhận câu trả lời của bạn nếu nó được giải thích đầy đủ. :)
LambdaBeta

1
@DLosc - xong rồi, mong nó giúp.
Jonathan Allan

@LambdaBeta - câu trả lời V ngắn hơn.
Jonathan Allan

... Lỗi câu trả lời Vim thậm chí.
Jonathan Allan

5

APL (Dyalog) , 38 30 byte

4 byte được lưu nhờ @EriktheOutgolfer

(1-⍨w-⍨⊃⍸⎕=s)↑(w←∊⊃⌽⍸⎕=s)↑s←↑⎕

Hãy thử trực tuyến!


quá phức tạp. bạn có thể chấp nhận một ma trận thay vì vectơ của vectơ, tìm hai vị trí với ⍸matrix∊separatorsvà thực hiện lấy / thả với chúng
ngn

(⍸a=⎕)↓(1+⍸a=⎕)↑a←⎕với⎕io←0
ngn

@ngn OP cho biết số lượng ký tự khác nhau giữa các dòng vì vậy tôi giả sử đầu vào phải là vector trước khi xử lý. Mặc dù vậy, tôi cần các phần lựa chọn (đầu tiên và xoay) trong trường hợp dấu phân cách hiển thị một vài lần (xem trường hợp thử nghiệm thứ ba), nhưng tôi đoán rằng sự sụt giảm đã cắt giảm một vài byte, vì vậy cảm ơn! Tôi sẽ cập nhật khi tôi vào PC
Uriel

Rất tiếc ... tôi quên trường hợp thứ ba, xin lỗi. Sau đó, có thể: ⊃{⌽⊖⍵↓⍨⊃⍸⍺=⍵}/⎕⎕⎕(sic, với 3 quads trailing) thậm chí còn ngắn hơn. Hoặc ... ⎕⎕(↑⎕)nếu một ma trận trộn sẵn không được phép.
ngn

3

Thạch , 14 byte

œẹⱮẎQr/Ṛṭþ/œị⁸

Hãy thử trực tuyến!


Tôi đã thử chạy mã của bạn trên một số ví dụ khác, nhưng chỉ gặp sự cố. Đó có phải là một lỗi không, hay tôi chỉ đang làm gì đó sai?
Ilmari Karonen

@IlmariKaronen Bạn chưa trích dẫn đúng đối số thứ hai (không đề cập đến điều đó trong bài đăng); bọc nó trong dấu ngoặc đơn hoặc kép. Cách bạn đã gọi nó, đối số thứ hai là một tuple (Python) trống (), không phải '()'. Nếu nó có khả năng phân tích cú pháp, nó cần được trích dẫn, tuy nhiên, tôi //không cần phải trích dẫn (toán tử chia số nguyên không có toán hạng? Hm ...).
Erik the Outgolfer

@IlmariKaronen Tôi "nghĩ" rằng điều đó ()chỉ được Jelly diễn giải như một loại nhân vật đặc biệt. Hầu hết các cặp nhân vật tôi cố gắng làm việc. Tôi rất thích nghe những gì mọi người quen thuộc hơn với Jelly nghĩ. EDIT: ninja-ed bởi erik the outgolfer
LambdaBeta



2

Canvas , 37 byte

{³⁴⁰;x≡‽┐
X⁸)J╵⁶;┤ω┤⁵X⁶⁸⁰K├;┐┤└∔┘┘∔;@

Hãy thử nó ở đây!

36 byte để lấy tọa độ của các ký tự (và chuyển đổi chúng thành x, y, w, h vì đó là những gì cần) và 1 byte để có được phần phụ .. Phải có cách tiếp cận tốt hơn


2

JavaScript (ES6), 98 byte

Lấy đầu vào là hai số nguyên và một chuỗi các chuỗi. Trả về một chuỗi các chuỗi.

(x,y,a,X=Y=0)=>a.filter(s=>!Y&&(Y=-~s.indexOf(y,X?X-1:X=-~s.indexOf(x)),X)).map(s=>s.slice(X-1,Y))

Hãy thử trực tuyến!

Đã bình luận

( x,                          // x = start character
  y,                          // y = end character
  a,                          // a[] = array of strings
  X =                         // X = position of x, plus 1
  Y = 0                       // Y = position of y, plus 1
) =>                          //
  a.filter(s =>               // for each string s in a[]:
    !Y &&                     //   reject this string if Y is non-zero
    (                         //   otherwise, use the 2nd condition:
      Y = -~s.indexOf(        //     update Y:
        y,                    //       by looking for y in s
        X ?                   //       if X is non-zero:
          X - 1               //         start the search at X - 1
        :                     //       else:
          X = -~s.indexOf(x)  //         update X and start the search at X
      ),                      //     end of Y update
      X                       //     keep this string if X is non-zero
    )                         //   end of 2nd condition
  )                           // end of filter()
  .map(s =>                   // for each remaining string s:
    s.slice(X - 1, Y)         //   remove left and right characters outside the box
  )                           // end of map()

filter map ?! Sẽ xây dựng một mảng mới với reducehoặc một giải pháp đệ quy không hoạt động ngắn hơn? Trên điện thoại của tôi, xuống quán rượu hoặc tôi sẽ tự đi.
Xù xì

@Shaggy Có lẽ một cách ngắn hơn thực sự, nhưng tôi nghĩ rằng đây là phương pháp được cam chịu để sử dụng 2 đèo: vòng 2 không thể bắt đầu trước ngày 1 một chấm dứt và cả hai XYđược biết chắc chắn.
Arnauld

2

Java 10, 204 byte

(s,e,a)->{int b=-1,i=0;for(;i<a.length;i++)a[i]=(b=b<0?a[i].indexOf(s):b)<0|a[i].length()<b?"":a[i].substring(b);for(b=-1;i-->0;)a[i]=(b=b<0?a[i].indexOf(e):b)<0|a[i].length()<b?"":a[i].substring(0,b+1);}

Sửa đổi mảng đầu vào thay vì trả về một mảng mới để lưu byte. Điều này không có nghĩa là các dòng bị loại bỏ trở thành"" , mặc dù. Nếu điều này không được phép tôi sẽ thay đổi nó.

Hãy thử trực tuyến.

Giải trình:

(s,e,a)->{                 // Method with 2 Strings & String-array parameters and no return
  int b=-1,                //  Boundaries-integer, starting at -1
  i=0;for(;i<a.length;i++) //  Loop `i` in the range [0, amountOfLines)
    a[i]=                  //   Change the `i`th line in the array to:
      (b=b<0?              //    If `b` is -1:
          a[i].indexOf(s)  //     Set `b` to the index of `s` in the current line
                           //     (which is still -1 if it's not found)
         :                 //    Else (starting index already found)
          b                //     Leave `b` unchanged
      )<0                  //    Then, if `b` is -1,
         |a[i].length()<b? //    or the current line-length is too short:
       ""                  //     Remove the current line
      :                    //    Else:
       a[i].substring(b);  //     Shorten the line by removing every character before `b`
  for(b=-1;                //  Reset `b` to -1
      i-->0;)              //  Loop `i` in the range (amountOfLines, 0]
    a[i]=                  //  Change the `i`th line in the array to:
       (b=b<0?a[i].indexOf(e):b)<0|a[i].length()<b?"":
                           //   Similar as above (with end `e` instead of start `s`),
         a[i].substring(0,b+1);}
                           //   except we remove every character after `b` this time

Ví dụ:

Với các đầu vào start = "(", end = ")"lines =

["This is some text",
 ". (but this text",
 "  is in a box  ).",
 "So only it is important."]

vòng lặp đầu tiên sẽ cắt nó ở trên cùng và bên trái, thay đổi nó thành thế này:

["",
 "(but this text",
 "is in a box  ).",
 " only it is important."]

vòng lặp thứ hai sẽ cắt nó ở dưới cùng và bên phải, thay đổi nó thành này:

["",
 "(but this text",
 "is in a box  )",
 ""]

1

Võng mạc 0.8.2 , 110 byte

^((.)¶.)(.*¶)+(.*\2)
$1¶$4
^(.)(¶.¶\1)
$2
}s`(?<=^.¶.+)¶.
¶
s`^¶(.)¶(.*\1).*
$2
+m`^((.)+).¶((?<-2>.)+)$
$1¶$3

Hãy thử trực tuyến! Giải trình:

^((.)¶.)(.*¶)+(.*\2)
$1¶$4

Xóa các dòng đầu vào trước dòng đầu tiên của hộp.

^(.)(¶.¶\1)
$2

Nếu ký tự bắt đầu ở cột bên trái của đầu vào, hãy xóa nó.

}s`(?<=^.¶.+)¶.
¶

Nếu ký tự bắt đầu chưa bị xóa, hãy dịch chuyển tất cả các cột đầu vào còn lại và lặp lại từ đầu.

s`^¶(.)¶(.*\1).*
$2

Xóa ký tự kết thúc và mọi thứ trong đầu vào sau ký tự kết thúc.

+m`^((.)+).¶((?<-2>.)+)$
$1¶$3

Cắt tất cả các dòng theo chiều dài của dòng tiếp theo. Điều này hoạt động bằng cách đếm tất cả trừ một ký tự trên mỗi dòng, sau đó cố gắng khớp với nhiều ký tự trên dòng tiếp theo; nếu điều này thành công thì dòng thứ hai ngắn hơn, vì vậy ký tự cuối cùng sẽ bị xóa và vòng lặp lặp lại.


0

C (gcc) , 237 byte

f(c,r,o,p)char*p,*c;{char*_=strchr(p,r),*a,b;*_=0;a=strrchr(p,10);a=(a?a:p);*_=r;r=_-a;p=a;_=strrchr(p,o);*_=0;a=strrchr(p,10);a=(a?a:p);*_=o;o=_-a+1;_[1]=0;for(_=p;_;_=strchr(_+1,10)){b=_[o];_[o]=0;strcat(c,_+r);strcat(c,"\n");_[o]=b;}}

Hãy thử trực tuyến!

Tôi chắc chắn 99% điều này có thể được rút ngắn bằng cách sử dụng một số loại hàm trợ giúp để tìm chỉ mục ngang và con trỏ tới một ký tự, vì nó được lặp lại hai lần. Than ôi tôi không thể tìm thấy một cách đủ ngắn để làm điều đó, tôi có thể thử lại sau nếu tôi thấy thời gian.

Sự miêu tả

f(c,r,o,p)char*p,*c;{
    char*_=strchr(p,r),*a,b;         // find opening char (and declare vars)
    *_=0;a=strrchr(p,10);            // find \n before it
    a=(a?a:p);                       // deal with single line inputs
    *_=r;r=_-a;                      // save left margin width in r
    p=a;                             // crop everything before opening line

    _=strchr(p,o);                   // find closing char
    *_=0;a=strrchr(p,10);            // find \n before it
    a=(a?a:p);                       // deal with single line inputs
    *_=o;o=_-a+1;                    // save width in o
    _[1]=0;                          // crop everything after closing char
    for(_=p;_;_=strchr(_+1,10)){       // for each line
        b=_[o];_[o]=0;
        strcat(c,_+r);
        strcat(c,"\n");
        _[o]=b;
    }
}

1
Thậm chí tốt hơn: 219 byte
Zacharý 16/11/18

0

Stax , 15 byte

╛↨½╝v∞░W╧)╗Ö≈☼k

Chạy và gỡ lỗi nó

Nó lấy tập hợp các ký tự phân cách hộp (1 hoặc 2) trên dòng đầu tiên. Phần còn lại của dòng là phần đầu vào.

Giải nén, không được chỉnh sửa và nhận xét, nó trông như thế này.

            first line of input is the delimiter characters
dL          discard the first line of input and listify the rest into an array
{           begin block for iteration
  Mr        rotate matrix 90 degrees
  {         begin block for while loop
    ch      copy first row of block
    y|&C    if it insersects with the first line of input, break iteration
    D       drop the first line
  W         do-while loop until break
}4*         execute block 4 times
m           display result lines

Chạy cái này

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.