자르기 ASCII 아트 챌린지


13

ASCII 예술은 재미있다. 최신 텍스트 편집기는 텍스트 조작에 매우 능숙합니다. 현대 프로그래밍 언어가 과제에 달려 있습니까?

ASCII 아트 조작의 일반적인 작업 중 하나는 텍스트를 두 문자 사이의 사각형으로 자르는 것입니다. 이 과제에서 구현해야하는 작업입니다.

세부

프로그램은 3 개의 입력을받습니다 :

  • 첫 번째는 블록의 '시작'문자입니다-왼쪽 상단 모서리 표시
  • 두 번째는 블록의 '끝'문자입니다-오른쪽 하단 모서리를 표시합니다
  • 세 번째는 어떤 형식의 여러 줄 텍스트, 문자열 또는 문자열 목록 또는 파일 이름 또는 기타

결과는 여러 줄의 텍스트 (위의 형식 중 하나)가 주어진 입력 사이의 사각형으로 잘립니다. 처음 두 입력은 고유하지 않을 수 있습니다.

가장자리 케이스

상자의 용량은 항상 2 이상이어야합니다.

()     (
       )

있는 상자 그러나 이들은 :

)(     )      (
       (     )

아닙니다 (start = (및 end = 사용 )).

입력은 하나의 상자 만 포함합니다. 따라서 시작 및 끝 문자는 동일한 문자가 아닌 한 두 번만 발생해야하는 경우가 아니면 한 번만 발생해야합니다.

또한 입력의 각 라인은 적어도 라인의 시작에서 입력의 상자 오른쪽 가장자리까지의 거리만큼 길어야합니다.

프로그램은 유효하지 않은 입력을 처리 할 필요가 없습니다. 정의되지 않은 동작이 발생할 수 있습니다.

규칙

일반적인 코드 골프 규칙이 적용됩니다. 가장 짧은 코드가 승리합니다.

맑은 날: start: ( end: ) input:

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

산출:

(but this text
is in a box  )

수평 공간 제거도주의하십시오. ASCII 아트 작물은 2d입니다.

비오는 날: start: ( end: ) input:

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

산출:

(
)

동일한 시작 / 종료 : start: / end: / input:

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

산출:

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

잘못된 입력: start: ( end: ) input:

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

유효하지 않은 입력 2 : start: ( end: ) input:

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

상자보다 짧은 선이있는 유효한 상자는 어떻습니까?
seadoggie01

1
명확하게, 또한 잘못된 입력
LambdaBeta

잘못된 입력의 경우 결과는 무엇입니까? 또는 그들이 언급되지 않아서 돌볼 필요가 없습니까?
우리엘

1
결과는 C에서 정의되지 않은 동작과 매우 비슷합니다. 걱정하지 마십시오.
LambdaBeta

이것은 어려운 작은 도전입니다.
seadoggie01

답변:


15

Vim, 16 , 12 바이트 / 키 스트로크

#<C-v>Nj*yggVGp

온라인으로 사용해보십시오! V 통역사에서

최신 텍스트 편집기는 텍스트 조작에 매우 능숙합니다. 현대 프로그래밍 언어가 과제에 달려 있습니까?

나는 내기 오래된 텍스트 편집기가 더 나은입니다! :디

반드시 그럴 필요는 없지만,이 답변은 주어진 "유효하지 않은"입력 모두에서 작동하여 출력됩니다.

 rectangular (
) which is ill

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

설명:

#               " 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
덧붙여이는 정확히 내가이 문제를 작성하는 저를 묻는 메시지를 표시하도록하고 있었다 유스 케이스. 내 질문에 같은 매크로했다 /\/<cr><c-v>nygv$o0dp:) 너무 오랫동안 같은 또는 뭔가를
LambdaBeta

2
네, 사각형이 가장 좋지 않습니다 !
AdmBorkBork

6

젤리 , 13 바이트

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

왼쪽의 시작 및 끝 문자 목록과 오른쪽의 행 목록 (문자 목록)을 허용하는 2 진 링크는 행 목록 (문자 목록)을 생성합니다.

온라인으로 사용해보십시오! (전체 프로그램-입력이 유효한 Python이면 Python-string-quoting이 필요합니다.)

어떻게?

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

예를 들어, 왼쪽 = ['a', 'b']및 오른쪽 (문자 목록-행) :

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

=€두 목록 목록 (첫 번째 'a'=는, 두 번째는 'b'=) 의 목록을 생성합니다 .

00000000         00000000
00100000         00000000
00000000    ,    00000000
00000000         00000100
00000000         00000000

이것을 합하면 단일 목록 목록이 생성됩니다 (요소 별 합산).

00000000
00100000
00000000
00000100
00000000

ŒṪ그 다음 우리에게 비 0의 (1 인덱스) 다차원 인덱스를 제공, [[2,3],[4,6]]- 즉 [[top,left],[bottom,right]].

r/다음 수행 [2,3]r[4,6]하기 때문에, rvectorises,처럼 [2r4, 3r6]에 평가, [[2,3,4],[3,4,5,6]]즉 - [rows,columns].

,þ/그런 다음 outer-poduct 명령이있는 [2,3,4],þ[3,4,5,6]위치 를 수행 þ하고 ,쌍입니다. 이 [row,column]경우 열별로 모든 값 이 생성됩니다 .

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

우리는 이것을 행 단위로 원하므로 Z이것을 다음으로 바꾸는 데 사용됩니다.

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

마지막으로 œị입력 행 으로 다시 색인합니다.

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

두 경계 문자가 =€모두 같을 때 두 번 모두 동일 하지만 두 가지 모두를 식별하지만 SŒṪ옳은 일을 2끝내게됩니다 ['a','a'].

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

... 설명을 읽었지만 여전히 이해하지 못합니다. o_o 아마도 예제를 추가 할 수 있습니까?
DLosc

인센티브 : 자세한 설명이 있으면 답변을 받아 드리겠습니다. :)
LambdaBeta

1
@DLosc-완료되었습니다. 도움이 되길 바랍니다.
Jonathan Allan

@LambdaBeta-V 답변이 더 짧습니다.
Jonathan Allan

... Vim 응답조차도 잘못합니다.
Jonathan Allan

5

APL (Dyalog) , 38 30 바이트

@EriktheOutgolfer 덕분에 4 바이트 절약

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

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


너무 복잡한. 벡터로 구성된 벡터 대신 행렬을 받아들이고를 사용하여 두 위치를 찾은 다음 그와 함께 ⍸matrix∊separators가져갈 수 있습니다.
ngn

(⍸a=⎕)↓(1+⍸a=⎕)↑a←⎕⎕io←0
NGN

@ngn OP는 줄마다 문자 수가 다르므로 처리하기 전에 입력이 벡터라고 가정했습니다. 그럼에도 불구하고 구분 기호가 몇 번 (세 번째 테스트 사례 참조) 표시되는 경우 선택 부분 (첫 번째 및 회전)이 필요하지만 드롭으로 인해 몇 바이트가 줄어 듭니다. 감사합니다! PC에 도착하면 업데이트하겠습니다
Uriel

죄송합니다. 세 번째 경우를 잊었습니다. 죄송합니다. 아마도 ⊃{⌽⊖⍵↓⍨⊃⍸⍺=⍵}/⎕⎕⎕더 짧을 수도 있습니다 (3 개의 후행 쿼드가있는 ic). 또는 ... ⎕⎕(↑⎕)사전 혼합 된 매트릭스가 허용되지 않는 경우.
ngn

3

젤리 , 14 바이트

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

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


다른 예제 중 일부에서 코드를 실행하려고 시도했지만 충돌이 발생했습니다. 그게 버그입니까, 아니면 내가 잘못하고 있습니까?
Ilmari Karonen

@IlmariKaronen 당신은 두 번째 논증을 올바르게 인용하지 않았습니다 (게시물에서 언급하지 않았습니다). 작은 따옴표 나 큰 따옴표로 묶으십시오. 호출 한 방식으로 두 번째 인수는 비어 있지 않은 (Python) 튜플 ( ()) '()'입니다. 구문 분석 할 수 있으면 인용해야하지만 인용 할 필요 //는 없습니다 (피연산자가없는 정수 나누기 연산자? hm ...).
Outgolfer Erik

@IlmariKaronen 나는 ()젤리에 의해 일종의 특수 문자로 해석되고있는 "생각한다" . 내가 시도하는 대부분의 문자 쌍. 젤리에 대해 더 잘 알고있는 사람들의 의견을 듣고 싶습니다. 편집 : 에릭 the outgolfer에 의해 닌자
람다 베타

그래, 그래 .
Ilmari Karonen


2

캔버스 , 37 바이트

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

여기 사용해보십시오!

문자의 좌표를 얻기위한 36 바이트 (그리고 그것이 필요한 것이기 때문에 x, y, w, h로 변환 )와 서브 섹션을 얻기위한 1 바이트. 더 나은 접근법이 있어야합니다.


2

JavaScript (ES6), 98 바이트

두 개의 정수와 문자열 배열로 입력을받습니다. 문자열 배열을 반환합니다.

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

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

댓글

( 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 ?! reduce재귀 적 솔루션 으로 새로운 어레이를 구축하는 것이 더 짧지 않을까요? 나에게 전화, 술집을 내려가거나 직접 갈 것입니다.
얽히고 설킨

@Shaggy 아마 참으로 짧은 방법이 있어요,하지만 난 생각 방법은 2 개 패스를 사용하는 운명 : 2 루프는 1 일 이전에 하나의 종료와 동시에 시작할 수 없습니다 XY확실히 알려져있다.
Arnauld

2

자바 10, 204 바이트

(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,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

예를 들면 다음과 같습니다.

입력으로 start = "(", end = ")"그리고lines =

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

첫 번째 루프는 상단과 왼쪽에서 자르고 다음과 같이 변경합니다.

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

두 번째 루프는 아래쪽과 오른쪽에서 자르고 다음과 같이 변경합니다.

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

1

레티 나 0.8.2 , 110 바이트

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

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

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

상자의 첫 번째 줄 앞의 입력 줄을 삭제하십시오.

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

시작 문자가 입력의 왼쪽 열에 있으면 삭제하십시오.

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

시작 문자가 아직 삭제되지 않은 경우 모든 입력 열을 왼쪽으로 이동하고 처음부터 반복하십시오.

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

끝 문자와 끝 문자 뒤의 입력에서 모든 문자를 삭제하십시오.

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

모든 줄을 다음 줄의 길이로 자릅니다. 이것은 각 줄에서 한 문자를 제외한 모든 문자를 세고 다음 줄에서 그 많은 문자와 일치 시키려고 시도합니다. 이것이 성공하면 두 번째 줄이 짧아 지므로 마지막 문자가 삭제되고 루프가 반복됩니다.


0

C (gcc) , 237 바이트

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

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

99 %는 문자의 가로 인덱스와 포인터를 두 번 반복하여 찾기 위해 일종의 도우미 기능을 사용하여 단축 할 수 있다고 확신합니다. 아아, 나는 그것을 할 수있는 짧은 방법을 찾지 못했습니다. 시간을 찾으면 나중에 다시 시도 할 수 있습니다.

기술

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
더 나은 : 219 바이트
Zacharý

0

Stax , 15 바이트

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

실행 및 디버깅

첫 번째 입력 행에서 상자 구분 문자 세트 (1 또는 2)를 사용합니다. 나머지 줄은 입력 본문입니다.

포장을 풀고 포장을 풀고 주석을 달았습니다.

            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

이것을 실행

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