끈을 안쪽으로 돌리십시오


21

균형 잡힌 문자열은 ()모든 괄호를 다른 괄호와 일치시킬 수 있도록 괄호 문자열입니다 . 더 엄격하게 그들은이 문법에 의해 퍼져있는 줄입니다 :

S → (S)S | ε

다음과 같이 문자열을 "내부"로 바꿀 수 있습니다.

  • 모든 항목 전환 ()서로를

  • 줄이 다시 균형을 잡을 때까지 줄 앞에서 뒤로 문자 이동.


예를 들어 봅시다.

균형 잡힌 문자열로 시작합니다.

(()(())())

그런 다음 파 렌스를 전환하여

))())(()((

그런 다음 문자열이 균형을 잡을 때까지 문자열 앞쪽에서 문자열 뒤쪽으로 문자를 이동하십시오.

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

그게 우리의 결과입니다!


일부 문자열은 문자열과 같이 여러 가지 방법으로 뒤집어 질 수 있습니다.

(()())

뒤집어 놓으면 다음 중 하나 일 수 있습니다.

()(())

또는

(())()

그러나 모든 문자열 에는 하나 이상의 솔루션이 있습니다.

태스크

균형 잡힌 문자열을 입력으로 사용하고 그 문자열을 뒤집어 출력하는 프로그램을 작성하십시오. 유효한 출력이 여러 개인 경우 그 중 하나만 출력하면됩니다. 당신은 다른 브레이스 유형을 사용 (수 <>, []또는 {}당신이 그렇게 원하는 경우).

이것은 경쟁이므로 바이트 단위로 측정 할 때 소스 코드의 크기를 최소화해야합니다.

테스트 사례

(()())     -> ()(()), (())()
(()(())()) -> (()(())())
((())())() -> (()(()()))

항상 해결책이 있다는 것이 보장됩니까?
Luis Mendo

@LuisMendo 예, 나는 이것을 증명했습니다. 당신이 증거를보고 싶다면, 채팅에 저를 핑 자유롭게.
밀 마법사

감사. 그것을 아는 것으로 충분합니다. 어쩌면 당신은 도전에 그것을 써야한다. 그렇지 않으면 해결책이 없다면 출력 할 것을 정의해야 할 것이다
Luis Mendo

답변:


9

하스켈 , 124 120 119 117 113 110 109 106 105 104 101 98 바이트

bartavelle 덕분에 4 바이트가 절약되었습니다!

Zgarb 덕분에 3 바이트 절약

Peter Taylor 덕분에 1 바이트 절약

여기 Haskell에서 해결 한 솔루션이 있습니다. 내가받은 도움 덕분에 지금괜찮습니다 . 그러나 이것을 짧게 만들고 싶습니다. 따라서 피드백 / 제안을 부탁드립니다.

until(!0)g.map d
_!1=1<0
('(':a)!x=a!(x-1)
(_:a)!x=a!(x+1)
_!_=1>0
g(a:b)=b++[a]
d '('=')'
d _='('

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

설명

이 프로그램은 4 개의 함수를 정의하며, 첫 번째 (!)는 문자열의 균형이 맞는지 결정합니다. 다음과 같이 정의됩니다.

_!1=1<0
('(':a)!x=a!(x-1)
(_:a)!x=a!(x+1)
_!_=1>0

이 검사에서는 Peter Taylor의 제안에 따라 입력에 동일한 수의 열린 및 닫힌 파 렌스가 있다고 가정합니다.

다음 g은 문자열을 한 번 회전시킵니다.

g(a:b)=b++[a]

그런 다음 우리는 d단순히 paren을 가져 와서 그것을 미러링합니다.

d '('=')'
d _='('

마지막으로 우리는 우리가 관심있는 기능을 가지고 있습니다. 여기서는 until(!0)g로 구성된 pointfree 표현을 사용 하여 입력에 map d매핑 하고 결과가 균형을 이룰 때까지 d적용 g합니다. 이것은 질문에 설명 된 정확한 과정입니다.

until(!0)g.map d

1
g x@(a:b)|x!0=x|1>0=g$b++[a]대한 parens를 제거하고 제거하여 몇 바이트를 스크랩 할 수 있습니다 d '('=')'.
bartavelle

@bartavelle에 대한 parens를 제거하면 d컴파일러 오류가 발생합니다. 그러나 첫 번째 제안은 환영합니다. 감사!
밀 마법사

1
!문자열에 열리고 닫히는 괄호 수가 다른 경우를 처리 할 필요가 없으므로 다른 바이트를 절약 할 수 있으므로 처음 두 경우를 바꿀 수 있습니다._!1=1<0 []!_=0<1
Peter Taylor

1
until단축 사용 g: TIO
Zgarb

2
나는함으로써 상당한 절약이 있어야한다고 생각 d지도 '('(-1)와에 무엇을 1, 그리고 그 다음이 긴 경우 !에 결합 될 수있다 (i:a)!x=a!(x+i). 그런 다음 최상위 레벨 구조 map duntil조건 으로 푸시하기 위해 재 작업이 필요 하며 실행해야하므로 지금 결합기를 결합하는 데 필요한 결합기를 알아낼 시간이 없습니다.
피터 테일러

7

SOGL V0.12 , 12 11 바이트

↔]»:l{Ƨ()øŗ

여기 사용해보십시오!

설명:

↔            mirror characters
 ]           do ... while the top of stack is truthy
  »            put the last letter at the start
   :           duplicate it
    l{         length times do
      Ƨ()        push "()"
         ø       push ""
          ŗ      replace ["()" with ""]
             if the string left on stack is empty (aka all matched parentheses could be removed), then stop the while loop

참고 : ( 10 바이트의 l{경우)로 바꿀 수 있지만 슬프게도 구현되지 않습니다.


문자 미러링이 작동합니까? 나는 그것이 정확히 무엇을 의미하는지 알지 못하지만 내 직감은 그것이 문자의 순서를 뒤집어 놓았다고 말하지만 작동하지 않을 것이라고 생각합니다.
밀 마법사

1
@Olmman 그것은 문자를 반전하기위한,하지만하지 않습니다 (여기 바이트를 저장하는!). 여물통을 변경하기 위해 V0.13 라인업에 있습니다.
dzaima

5

CJam (20 자)

q1f^0X${~_}%_:e>#)m<

온라인 데모

또는 동일한 문자 수

q1f^_,,{0W$@<~}$W=m<

온라인 데모

해부

두 버전에는 공통 머리글과 바닥 글이 있습니다.

q1f^    e# Read input and toggle least significant bit of each character
        e# This effectively swaps ( and )

m<      e# Stack: swapped_string index
        e# Rotates the string to the left index characters

그런 다음 가운데의 비트는 분명히 얼마나 멀리 회전해야하는지 계산합니다. 둘 다 평가를 사용 (하며 CJam 감소 연산자 및 )증가 연산자 에 의존합니다 .

0X$     e# Push 0 and a copy of the swapped string
{~_}%   e# Map: evaluate one character and duplicate top of stack
        e# The result is an array of the negated nesting depth after each character
_:e>    e# Copy that array and find its maximum value
#       e# Find the first index at which that value occurs
)       e# Increment

vs

_,,     e# Create array [0 1 ... len(swapped_string)-1]
{       e# Sort with mapping function:
  0W$@  e#   Rearrange stack to 0 swapped_string index
  <~    e#   Take first index chars of swapped_string and evaluate
}$      e# The result is an array of indices sorted by the negated nesting depth
W=      e# Take the last one

3

자바 스크립트 (ES6) 111 105 바이트

(@CraigAyre 덕분에 2 바이트, @PeterTaylor 덕분에 2 바이트, @Shaggy 덕분에 2 바이트 절약 됨)

s=>(r=[...s].map(c=>'()'[c<')'|0])).some(_=>r.push(r.shift(i=0))&&!r.some(c=>(i+=c<')'||-1)<0))&&r.join``

언 골프 드 :

s=>(
  r=[...s].map(c=>'()'[c<')'|0]),  //switch "(" and ")"
  r.some(_=>(
    r.push(r.shift(i=0)),          //move last element to beginning of array, initialize i
    !r.some(c=>(i+=c<')'||-1)<0)   //check if balanced (i should never be less than 0)
  )),
  r.join``
)

테스트 사례 :


3

망막 , 46 38 바이트

T`()`)(
(.*?)(((\()|(?<-4>\)))+)$
$2$1

온라인으로 사용해보십시오! 링크에는 테스트 사례가 포함됩니다. 편집 : @MartinEnder의 도움으로 8 바이트를 저장했습니다. 첫 번째 단계는 단순히 괄호를 바꾸는 반면, 두 번째 단계는 유효한 균형 접두사 인 가장 긴 접미사를 찾습니다. 이는 회전이 완전히 균형을 잡기에 충분한 조건 인 것 같습니다. 밸런싱은 밸런싱 그룹을 사용하여 감지됩니다. 구축물은 ((\()|(?<-4>\)))+임의의 수의 일치 (의 플러스의 수 )만큼 우리는 이미 (가지고들 <-4>) 많은으로 볼 (의. 유효한 접두사 만 찾고 있기 때문에 나머지와 일치하지 않아도됩니다 ).


일반적으로 두 괄호를 반복하는 대신 대체로 넣어서 byte를 저장합니다 ((\()|(?<-2>\))). 그러나 당신의 시도는 저에게 또 다른 두 가지를 절약하는 완전히 새로운 접근법을 찾도록 영감을주었습니다 (?<-1>(\()*\))+. 앞으로 확실히 도움이 될 것입니다. 감사합니다. :)
Martin Ender

음의 스택 깊이를 얻지 않고 문자열 끝에 도달 할 수있는 첫 번째 접미사를 일치시켜 회전을 결정하는 것이 훨씬 짧습니다. tio.run/…
Martin Ender

@MartinEnder 원래는 교대로 시도했지만 그 당시에는 작동하지 못했지만 실제로는 어떤 것도 일치하기 전에 스택 (?<-1>(\()*\))+에서 튀어 나오고 싶어하는 것 같아서 어떻게 작동 하는지 알 수 없습니다 1...
Neil

@MartinEnder 발란스 접두사와 일치 할 때 대체 버전이 골퍼로 보입니다.
Neil

1
실제 터지는 것은 시작이 아닌 그룹의 끝에서 발생합니다. 중복을 피하기 위해 교대로 좋은 지적 \(*.
마틴 엔더

2

PHP, 110 108 바이트

for($s=$argn;;$p?die(strtr($s,"()",")(")):$s=substr($s,1).$s[$i=0])for($p=1;$p&&$c=$s[$i++];)$p-=$c<")"?:-1;

파이프로 실행 -nR하거나 온라인으로 테스트하십시오 .

고장

for($s=$argn;               # import input
    ;                       # infinite loop
    $p?die(strtr($s,"()",")(")) # 2. if balanced: invert, print and exit
    :$s=substr($s,1).$s[$i=0]   #    else: rotate string, reset $i to 0
)                               # 1. test balance:
    for($p=1;                   # init $p to 1
        $p&&$c=$s[$i++];)       # loop through string while $p is >0
        $p-=$c<")"?:-1;             # increment $p for ")", decrement else


2

옥타브, 62 바이트

@(s)")("(x=hankel(s,shift(s,1))-39)(all(cumsum(2*x'-3)>=0)',:)

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

문자열을 입력으로 사용하여 모든 결과를 인쇄하는 함수입니다.

설명:

           hankel(a,shift(a,1))                                % generate a matrix of n*n where n= length(s) and its rows contain incresing circulraly shifted s
         x=...                 -39                             % convert matrix of "(" and ")" to a mtrix of 1 and 2
    ")("(x                        )                            % switch the parens
                                               2*x'-3          % convert [1 2] to [-1 1]
                                        cumsum(      )         % cumulative sum along the rows
                                    all(              >=0)'    % if all >=0
                                   (                       ,:) % extract the desired rows

2

Mathematica, 78 바이트

""<>{"(",")"}[[2ToCharacterCode@#-81//.x_/;Min@Accumulate@x<0:>RotateLeft@x]]&

1

JavaScript (ES6), 97 바이트

f=(s,t=s,u=t.replace(')(',''))=>u?t==u?f(s.slice(1)+s[0]):f(s,u):s.replace(/./g,c=>c<')'?')':'(')

조옮김이 균형을 잡을 때까지 입력 문자열을 재귀 적으로 회전시킨 다음 조옮김으로써 작동합니다.


단순히 아름답습니다.
Rick Hitchcock

1

APL (Dyalog Unicode) , 35 30 바이트

@ Adám을 통한 새로운 접근 방식

1⌽⍣{2::01∊⍎⍕1,¨⍺}')('['()'⍳⎕]

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

골프가 진행 중입니다.

설명

'()'⍳⎕              Find the index of each character of the input in the string '()'
                    (this is 1-indexed, so an input of '(())()' would give 1 1 2 2 1 2)
')('[...]           Find the index of the vector in the string ')('
                    This essentially swaps ')'s with '('s and vice versa
                   On this new string, do:
 1                   rotate it one to the left
                    Until this results in 1:
 1,¨⍺                 Concatenate each element of the argument with a 1
                      This inserts 1 one before each parenthesis
                     Stringify it
                     And evaluate it, if the parentheses are balanced, this produces no errors
 1                   Check if 1 belongs to evaluated value
                      If the parentheses were not matches during ⍎, this causes a syntax error
 2::0                 This catches a syntax error and returns 0
                      Essentially this code checks if the brackets are balanced or not

0

파이썬 2 , 99 바이트

r=[0];S=''
for c in input():b=c>'(';r+=[r[-1]+2*b-1];S+=')('[b]
n=r.index(min(r))
print S[n:]+S[:n]

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

쉬운 테스트 사례를위한 기능 형태 :

파이썬 2 , 108 바이트

def f(s):
 r=[0];S=''
 for c in s:b=c>'(';r+=[r[-1]+2*b-1];S+=')('[b]
 n=r.index(min(r))
 return S[n:]+S[:n]

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

이것은 약간 다른 접근법을 사용합니다-문자열을 재귀 적으로 회전시키는 대신에, 일부 균형 카운터를 증가시키고 감소시키는 것으로 Parens를 생각한다면, 균형 잡힌 문자열은 총 증가의 합을 가져서는 안됩니다-0보다 작은 감소.

그래서 우리는

(()(())())

파 렌스를 뒤집습니다 :

))())(()((

증분 / 감소의 합계 목록으로 변환하십시오.

[-1,-2,-1,-2,-3,-2,-1,-2,-1,0]

-3은 인덱스 4에서 최소값입니다 (0부터 시작). 인덱스 +1만큼 이동하고 싶습니다. 이렇게하면 누적 증감이 0보다 작지 않습니다. 합계는 0입니다.


내 휴대 전화에서 테스트 할 수는 없지만 r=0,대신 할 수 r=[0]있습니까?
Cyoce

당신이 Cyoce의 제안을 @로려고하는 경우에, 당신은 교체해야합니다 r+=[r[-1]+2*b-1]함께 r+=r[-1]+2*b-1,뿐만 아니라
OVS

0

클로저, 118 바이트

#(loop[s(map{\(\)\)\(}%)](let[s(conj(vec(rest s))(first s))](if(some neg?(reductions +(map{\( 1\) -1}s)))(recur s)s)))

일련의 문자를 반환하므로 다음과 같이 호출합니다.

(apply str (f "(()(())())"))
; "(()(())())"

먼저 대괄호를 뒤집고 시퀀스의 특정 지점에서 대괄호 수의 누적 합계가 음수가되는 한 반복됩니다.


0

brainfuck , 82 바이트

,[++[->->++<<]-[--->+>-<<]>-->+[-[-<<+>>>>+<<]],]+[<<]>>>[.[-]>>]<[<<]<[<<]>>[.>>]

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

설명

각 문자를 읽을 때마다 카운터는 다음과 같이 수정됩니다.

  • 카운터는 0에서 시작합니다.
  • 각각의 후에 )카운터는 1 씩 증가합니다.
  • 각각이 후에 (카운터가 0이 아닌 경우 카운터는 1 씩 감소하며,이 경우 카운터는 변경되지 않습니다.

이 접두어가 0 인 경우에만 각 접두사는 균형 문자열 (역전 후)의 유효한 접미사입니다.이 코드는 가장 긴 접두사를 사용하여 출력을 구성합니다.

,[                   Take input and start main loop
                     The cell one space right is the output cell (0 at this point),
                     and two spaces right is a copy of the previous counter value
  ++                 Add 2 to input
  [->->++<<]         Negate into output cell, and add twice to counter
  -[--->+>-<<]       Add 85 to output cell, and subtract 85 from counter
  >-->+              Subtract 2 from output cell and add 1 to counter
                     The output cell now has (81-input), and the counter has been increased by (2*input-80)
  [-[-<<+>>>>+<<]]   If the counter is nonzero, decrement and copy
,]
+[<<]                Go to the last position at which the counter is zero
>>>                  Go to following output character
[.[-]>>]             Output from here to end, clearing everything on the way
                     (Only the first one needs to be cleared, but this way takes fewer bytes)
<[<<]                Return to the same zero
<[<<]>>              Go to beginning of string
[.>>]                Output remaining characters
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.