각주로 괄호 위해이를 자동화하는 것이

배경

LISP 프로그래머가 전 세계를 점령했습니다! 괄호는 신성한 문자로 선언되었으며 지금부터 LISP 프로그램에서만 사용할 수 있습니다. 문학 작품의 괄호는 각주로 대체하기로 결정했으며 단순화 된 마크 다운 텍스트를 위해이를 자동화하는 것이 귀하의 임무입니다.

입력

입력은 알파벳 ASCII 문자, 공백 및 특수 문자가 포함 된 단일 문자열 ,.!?()입니다. 개행이나 숫자를 포함하지 않습니다. 괄호가 올바르게 일치합니다.

산출

입력 문자열에서 일치하는 각 괄호 쌍을 각주로 변환해야합니다. 이것은 다음과 같이 발생합니다 :

  1. 첫 번째로 일치하는 괄호 쌍과 그 사이의 하위 문자열을에서 시작 번호로 시작 1하고 Markdown 태그 <sup>와 사이에 래핑합니다 </sup>.
  2. 문자열의 끝에 추가
    • 두 줄 바꿈
    • Markdown을 태그 <sub>,
    • 1 단계의 숫자
    • 우주,
    • 괄호 사이의 하위 문자열
    • </sub>이 순서대로 닫는 태그
  3. 문자열에 여전히 괄호가 남아 있으면 1 단계로 이동하십시오.

결과는 결과 문자열이며 후행 줄 바꿈이 있습니다. 출력이 정확하다면이 정확한 알고리즘을 구현할 필요는 없습니다. 중첩 된 괄호가있을 수 있습니다. 이 경우 다른 각주에 대한 참조가 포함 된 각주가 있습니다. 괄호 안의 부분 문자열도 비어있을 수 있습니다. 예제는 아래 테스트 사례를 참조하십시오.

규칙과 채점

당신은 전체 프로그램이나 함수를 작성할 수 있습니다. 바이트 수가 가장 적고 표준 허점이 허용되지 않습니다.

언어가 기본적으로 십진수를 지원하지 않는 경우 ( 기침 Retina cough ) 이진 또는 단항을 포함하여 다른 기본에 각주 번호를 줄 수 있습니다. 단항 숫자를 사용 하면 + 20 %위약금이 부과 됩니다.

테스트 사례

입력:

This input contains no parentheses.

산출:

This input contains no parentheses.

입력:

This has (some) parentheses (but not so many).

산출:

This has <sup>1</sup> parentheses <sup>2</sup>.

<sub>1 some</sub>

<sub>2 but not so many</sub>

입력:

This has (nested (deeply (or highly?) nested)) parentheses (and several groups).

산출:

This has <sup>1</sup> parentheses <sup>2</sup>.

<sub>1 nested <sup>3</sup></sub>

<sub>2 and several groups</sub>

<sub>3 deeply <sup>4</sup> nested</sub>

<sub>4 or highly?</sub>

입력:

Hmm()(()(,))  a()((trt)(v( (((((wut)))))(X)(Y)(Z) )!?!?!?!))oooooooo(oooo)oooo

산출:

Hmm<sup>1</sup><sup>2</sup>  a<sup>3</sup><sup>4</sup>oooooooo<sup>5</sup>oooo

<sub>1 </sub>

<sub>2 <sup>6</sup><sup>7</sup></sub>

<sub>3 </sub>

<sub>4 <sup>8</sup><sup>9</sup></sub>

<sub>5 oooo</sub>

<sub>6 </sub>

<sub>7 ,</sub>

<sub>8 trt</sub>

<sub>9 v<sup>10</sup>!?!?!?!</sub>

<sub>10  <sup>11</sup><sup>12</sup><sup>13</sup><sup>14</sup> </sub>

<sub>11 <sup>15</sup></sub>

<sub>12 X</sub>

<sub>13 Y</sub>

<sub>14 Z</sub>

<sub>15 <sup>16</sup></sub>

<sub>16 <sup>17</sup></sub>

<sub>17 <sup>18</sup></sub>

<sub>18 wut</sub>

각주 사이에 빈 줄이 있습니다.



답변

펄, 81 75 72 바이트

71 바이트 코드 + 1 바이트 명령 행 인수

Perl 5.10 이상 필요 (재귀 정규식 지원)

$i++;s#(\((((?1)|.)*?)\))(.*)#<sup>$i</sup>$4

<sub>$i $2</sub>#s&&redo

용법:

perl -p entry.pl input.txt

설명

-p 매개 변수는 주어진 명령을 입력에 적용한 결과를 인쇄하므로 명시적인 인쇄가 필요하지 않습니다.

정규식 (\(((?1)|.)*?)\))은 문자열의 시작 부분에서 가장 바깥 쪽 대괄호 집합을 찾고 있습니다. 이것이 발견되면 대체를 수행하여 입력의 끝에만을 추가하여 (입력을 사용하여 입력이 끝날 때까지 모든 것을 캡처하여 (.*)) 보장 합니다.

그런 다음을 사용하여 현재 대체 된 문자열에서 정규식 대체를 반복하여 정규식 대체가 redo더 이상 일치하지 않을 때까지 계속 적용합니다. s수정 보장하지만이 있음을 .우리는 이전 정규식 대체의 결과에 정규식 일치를 다시 적용되기 때문에 정규식에서이 필요 새로운 라인을 일치합니다.


답변

이맥스 리스프, 335 바이트

머리말. 이 답변과 제도 답변은 현재 Mighty Popular Republic of LISP와 Emacs Church에서 공식적으로 승인 한 유일한 답변입니다. 짧거나 그렇지 않은 다른 답변은 평화에 대한 위협으로 간주됩니다. 특히, 적대적인 적들로부터 들리는 매카시즘에 대한 비방적인 주장에 대한 깊은 멸시와 함께, 우리는 지역 사무국에 연락하기 위해 Nonlisp 답변을 쓰는 ​​익명의 저자들의 실제 정체성에 관한 정보를 가지고있는 사람을 동참시킵니다. 모든 사람은 자신이 현재 권한의 공식 대표자와의 미래의 상호 작용을 위협하지 않을 것이라고 깊이 믿는 바에 따라 반영하고 찬성하는 데 시간이 걸리는 것을 상기해야합니다. 코드는 데이터입니다. 데이터는 코드입니다.

(defun p()(let(b(cpt 0)n)(goto-char 0)(while(search-forward"("()t)(setf b(point)n(number-to-string(incf cpt)))(backward-char)(forward-sexp)(backward-char)(kill-region b(point))(delete-backward-char 1)(delete-forward-char 1)(insert "<sup>"n"</sup>")(save-excursion(end-of-buffer)(newline 2)(insert "<sub>"n" ")(yank)(insert"</sub>")))))

더 우아하게 :

(defun parens ()
  (let (b(cpt 0)n)
    (goto-char 0)
    (while(search-forward"("()t)
      (setf b(point)n(number-to-string(incf cpt)))
      (backward-char)
      (forward-sexp)
      (backward-char)
      (kill-region b(point))
      (delete-backward-char 1)
      (delete-forward-char 1)
      (insert "<sup>"n"</sup>")
      (save-excursion
       (end-of-buffer)
       (newline 2)
       (insert "<sub>"n" ")
       (yank)
       (insert "</sub>")))))

답변

망막 , 96 86 83 바이트 * 120 % = 99.6

이 솔루션의 소스 코드는 다음 두 파일로 구성됩니다.

+s`\((((\()|(?<-3>\))|[^)])*).(.*)(?<=(1+).*?)?
<sup>1$5</sup>$4

<sub>1$5 $1</sub>

설명

이것은 도전에 설명 된대로 알고리즘을 매우 직접 구현 한 것입니다. 이 코드는 첫 번째 괄호 세트를 각주로 바꾸는 단일 정규식 대체로 구성됩니다. 이 대체는 +문자열 변경이 멈출 때까지 반복됩니다. 여기서 더 이상 괄호를 찾을 수 없기 때문에 정규식이 더 이상 일치하지 않습니다.

각주는 단항으로 열거되므로 마지막 각주 번호를 찾고 1다음을 만들기 위해 a 를 추가 할 수 있습니다.

첫 번째 괄호 세트를 찾기위한 정규식은 괄호를 균형 그룹과 일치시키는 표준 기술을 기반으로 합니다 (hrhr, “matching 괄호”). 이름이없는 그룹을 사용하고 괄호가 올바르게 균형을 잡았다 고 가정하면 약간 단축되었습니다 (즉 (, 부정 된 문자 클래스에서 생략 하고 최종 문자를 )간단한 문자와 일치 .시킬 수 있음을 의미합니다. 캡처 스택이 비어 있습니다).

괄호를 일치시키고 내용을 group으로 캡처 한 후 1, 나머지 문자열 (.*)을 그룹으로 캡처 4한 다음 1음의 lookbehind가있는 첫 번째 s 세트의 문자열을 다시 검색 합니다. 이러한 하위 문자열을 찾으면 group에 저장 5합니다. 그렇지 않다면, 우리는 실패하지만, 그것은 선택 사항이기 때문에 괜찮습니다-그것은 $5단항 표현 0이며 또한 정확한 빈 문자열을 줄 것임을 의미 합니다.

그런 다음 대체 문자열은 단순히 캡처 그룹을 기반으로 모든 것을 하나로 묶습니다. 각주 번호는로 1마지막 번호 앞에 a 를 붙여서 증가합니다 1$5.


답변

Sacred JavaScript , 1510 바이트

반역자 여러분, 괄호에 대한 압도적 인 철거를하지 마십시오! 인내해야합니다! 처음부터 프로그래밍은 자유 기업이었습니다. 지금, 그것은 경건의 만연 된 쇼가되었습니다. 절대적인 무시 무시 함을 보여 주어야합니다. 따라서 나는 다시 싸웠다!

    ( )( (((  ((  )( )  (( ))( )) (( ( ((  ) ( ()( ) (( ) )(( ((( ()((( ) ( ) )((  ) (((((( )( (())((  ) ) )( ()(( ((()((()   ( (  (  ( )) ((  )( ) (( ) )((((  ( () ) )( ( ()(( )( () ((( )(( ) )( ()((( ) ( )  ( )() (((( () ) (((( () ) ((() ) ()  ( (  (  ( )) ( )(  ((((( )) ((  )( ) (( ) )((((  ) )  ()(  ((() ( ()(( ) ( ) )(( ))(((  (( ) ((  ) ( ()(( )( ) ()  ( (  (  ( ()( ) )( ()(  ) ()  ( (  (  ( )( (( ( (( )  ((((( ))  ) )(( )) ((  )( ) (( ) )((((  ) ()( ))  ) ) (( )( () (((   ( ) )((  )( )(((( ))( )() ) ()( ))  (()( (()( ((()((()   ( (  (    (  ( )) ( )(  (((((( )(( ( (( )) ( ((  ) )( ) )( ( )( ((() ( )( ((() ( ()( ()( ()   ) )( ()(( ) ()  ( (  (    (  ( )) ( )(  (((((( )(( ( (( )) ( ((  ) )( ) )( ( )( (((( ( )( ((() ( ()( ()( (()( ) )( ()(( ) ()  ( (  (    (  ( )) ( )(  (((( ( ) ( ()( ((() ( ()( ())(( ) ( ) )( ()(( ))) ) ()  ( (  (  ((())  ( (  (  ((( ( ) )((( )( () ((( )(((   ( )) ( )  ( ) ) ((((( )) ((  )( ) (( ) )((((  (())( ))  (()( ()(( ((()  ( (  (  ( )(  ) )(((( ( () ((( ) ( ) )(( ((((   ( ()(( )  ( ) ) (((( () )( ((( ((((((()( ((() ((   () )( )(( (()) ( )( ( )( ((() ) ()  ( (  (  (( ) ( ) )(( ))(((  (( ) ((  ) ( ()( ) (( ) )(( ((( ()((( ) ( ) )((  ) (((((( )( () ((( ) ( ) )(( ((((   ( ()(( )  ( ) ) ((((((( ( (()) ( )( ) ) (( )((((  ( ()) ) )) ( )( (()(((  ) (()( ( )( ) )  () )(( )((((  ( ()) ) )) ( )( ((() (()( ( )(  ( (  ( ( ) ) (( )((((  ( ()) ) )) ( )( (()(((  ) (()( ( )( ( () ( )( (()(( )(  (()( ( )( ) )  () )(( )((((  ( ()) ) )) ( )( (())((  ) (()( ()(( ((() ) ()  ( (((())

Lisp 이외의 언어로 신성한 문자를 사용하는 것에 대한 규칙이 없습니다. 아뇨, 전혀 아닙니다. (약간 간단한 방법으로)

( )( (((  ((  )( )  (( ))( )) (( ( ((  ) ( ()( ) (( ) )(( ((( ()((( )
( ) )((  ) (((((( )( (())((  ) ) )( ()(( ((()((()   ( (  (  ( )) ((  )
( ) (( ) )((((  ( () ) )( ( ()(( )( () ((( )(( ) )( ()((( ) ( )  ( )()
 (((( () ) (((( () ) ((() ) ()  ( (  (  ( )) ( )(  ((((( )) ((  )( ) (
( ) )((((  ) )  ()(  ((() ( ()(( ) ( ) )(( ))(((  (( ) ((  ) ( ()(( )(
 ) ()  ( (  (  ( ()( ) )( ()(  ) ()  ( (  (  ( )( (( ( (( )  ((((( ))
 ) )(( )) ((  )( ) (( ) )((((  ) ()( ))  ) ) (( )( () (((   ( ) )((  )
( )(((( ))( )() ) ()( ))  (()( (()( ((()((()   ( (  (    (  ( )) ( )(
 (((((( )(( ( (( )) ( ((  ) )( ) )( ( )( ((() ( )( ((() ( ()( ()( ()
 ) )( ()(( ) ()  ( (  (    (  ( )) ( )(  (((((( )(( ( (( )) ( ((  ) )(
 ) )( ( )( (((( ( )( ((() ( ()( ()( (()( ) )( ()(( ) ()  ( (  (    (
( )) ( )(  (((( ( ) ( ()( ((() ( ()( ())(( ) ( ) )( ()(( ))) ) ()  ( (
  (  ((())  ( (  (  ((( ( ) )((( )( () ((( )(((   ( )) ( )  ( ) ) ((((
( )) ((  )( ) (( ) )((((  (())( ))  (()( ()(( ((()  ( (  (  ( )(  ) )(
((( ( () ((( ) ( ) )(( ((((   ( ()(( )  ( ) ) (((( () )( ((( ((((((()(
 ((() ((   () )( )(( (()) ( )( ( )( ((() ) ()  ( (  (  (( ) ( ) )(( ))
(((  (( ) ((  ) ( ()( ) (( ) )(( ((( ()((( ) ( ) )((  ) (((((( )( () (
(( ) ( ) )(( ((((   ( ()(( )  ( ) ) ((((((( ( (()) ( )( ) ) (( )((((
( ()) ) )) ( )( (()(((  ) (()( ( )( ) )  () )(( )((((  ( ()) ) )) ( )(
 ((() (()( ( )(  ( (  ( ( ) ) (( )((((  ( ()) ) )) ( )( (()(((  ) (()(
 ( )( ( () ( )( (()(( )(  (()( ( )( ) )  () )(( )((((  ( ()) ) )) ( )(
 (())((  ) (()( ()(( ((() ) ()  ( (((())

이것은 내 다른 대답 에서 확장 된 JavaScript로 컴파일됩니다 . 이것은 농담 제출입니다.


답변

루아, 222 216 204 201 바이트

골프 :

s=io.read()g="%b()"c=1k=string l=k.find t=k.sub o=k.format a,b=l(s,g)while a do s=t(s,0,a-1)..o("<sup>%d</sup>",c)..t(s,b+1,#s).."\n\n"..o("<sub>%d %s</sub>",c,t(s,a+1,b-1))c=c+1 a,b=l(s,g)end print(s)

언 골프 드 :

input=io.read()
inputFormat="<sup>%d</sup>"
footnoteFormat="<sub>%d %s</sub>"
counter=1
a,b=string.find(input,"%b()")
while a do
    current=string.sub(input,a+1,b-1)
    input=input.."\n\n"..string.format(footnoteFormat, counter, current)
    input=string.sub(input,0,a-1)..string.format(inputFormat, counter)..string.sub(input,b+1,#input)
    counter=counter+1
    a,b=string.find(input,"%b()")
end

print(input)

답변

체계, 92 바이트

Real Lisp에서 가장 광범위한 검색을 구현 ​​한 것에 실망한 1 은보다 실용적인 접근 방식을 선택하기로 결정했습니다. 결국 괄호는 신성하지만 괄호는 그렇지 않습니다. 2

(lambda(s)(list->string(map(lambda(c)(case c((#\()#\[)((#\))#\])(else c)))(string->list s)))

1. 이맥스의 소위“교회”에서 이단자들의 말을 듣지 마십시오!
2. 그들은 라켓 프로그래머가 아닌가?


답변

하스켈, 210 바이트

n#x|b==""=a|1<2=a++"<sup>"++m++"</sup>"++((n+1)#(c++"\n\n<sub>"++m++' ':init d++"</sub>"))where m=show n;(a,b)=span(/='(')x;(d,c)=[x|x@(y,_)<-map(`splitAt`(tail b))[0..],'('!y<')'!y]!!0;c!l=[1|m<-l,m==c]
p=(1#)

사용 예 :

*Main> putStrLn $ p "This has (nested (deeply (or highly?) nested)) parentheses (and several groups)."
This has <sup>1</sup> parentheses <sup>2</sup>.

<sub>1 nested <sup>3</sup></sub>

<sub>2 and several groups</sub>

<sub>3 deeply <sup>4</sup> nested</sub>

<sub>4 or highly?</sub>

작동 방식 :

n # x                      -- # does all the work, n is the current number of the
                           --   footnote and x the input string
  | b=="" = a              -- if b (see below) is empty, there's no ( in the
                           --   string and the result is 'a' (see below)
  | 1<2   = a++"<sup>"++m++"</sup>"++ ((n+1)#(c++"\n\n<sub>"++m++' ':init d++"</sub>"))
                           -- otherwise (b not empty) build the output string
                           --   starting with 'a' and a footnote number and a
                           --   recursive call with the current footnote appended
                           --   to the rest of the string

  where
  m = show n;              -- turn n into string
  (a,b) = span (/='(') x;  -- split the input string x into two parts:
                           --   a: everything before the first (
                           --   b: beginning with the first ( to the end
                           --   if there's no (, a is x and b is empty
  (d,c) = [x|x@(y,_)<-map(`splitAt`(tail b))[0..],'('!y<')'!y]!!0;
                           -- find matching ) in the tail of b ('tail' to remove leading '(')
                           --   d: everything before and including the matching )
                           --   c: everything behind the matching )
  c!l=[1|m<-l,m==c]        -- helper function that builds a list of 1s for every character searched for
                           --   we have reached the matching ) if the list for ( is
                           --   shorter (less than, <) the list for )

p=(1#)                     -- start with footnote 1