Achatar um programa Stack Cats

13

Stack Cats é uma linguagem reversível baseada em pilha. Sua natureza reversível cria loops um tanto estranhos. Esse desafio é sobre o loop condicional (...). Quando esses loops são aninhados de certas maneiras, é possível transformar o código para reduzir a profundidade do aninhamento. Aqui estão as regras (onde Ae Brepresentam trechos arbitrários):

  1. Quando um loop começa com outro, podemos extrair o loop interno para a frente: ((A)B)torna - se (A)(B).
  2. Quando um loop termina com outro loop, podemos extrair o loop interno até o fim: (B(A))torna - se (B)(A).
  3. Loops vazios,, ()podem ser removidos totalmente do programa. Como corolário (em conjunto com as outras regras), ((A))é equivalente a (A).

Os loops única aninhados que permanecem são de forma (A(B)C), onde A, Be Csão não-vazia.

O desafio

Você recebe um programa Stack Cats válido e sua tarefa é reduzir o nível de aninhamento de loops o máximo possível, sem deixar loops vazios, usando as transformações acima.

Um programa Stack Cats válido ...

  • ... consiste apenas nos personagens ()/\<>[]{}!"*+-:=ITX^_|.
  • ... possui simetria espelhada (por exemplo, \(]{}!{}[)/é um programa válido, mas /|/não é).
  • ... foi correspondido e aninhado corretamente ()e {}( [], <>e \/não necessariamente precisa ser correspondido como de costume, embora eles apareçam em pares devido ao requisito de simetria de espelho).

Você pode usar uma sequência ou uma lista de caracteres como entrada, mas a saída precisa ser apresentada no mesmo formato.

Você pode escrever um programa ou uma função e usar qualquer um dos nossos métodos padrão de recebimento de entrada e fornecimento de saída. Observe que essas brechas são proibidas por padrão.

Isso é , então a resposta mais curta e válida - medida em bytes - vence.

Casos de teste

Os casos de teste são duas linhas cada (entrada e saída), separadas por linhas vazias. Observe que uma saída está vazia. Você também precisa oferecer suporte à entrada vazia (o que deve resultar em saída vazia).

(((=+|+=)))
(=+|+=)

({(=+|+=)})
({(=+|+=)})

((\)/)I(\(/))
(\)(/)I(\)(/)

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


((<|>((X((T)))[_]))\^/(([_](((T))X))<|>))
(<|>)(X)(T)([_])(\^/)([_])(T)(X)(<|>)
Martin Ender
fonte
Só para ter certeza, os loops que precisamos extrair são indicados apenas entre parênteses (), para que uma entrada {{A}B}permaneça como está e não será extraída {A}{B}também?
Kevin Cruijssen
@KevinCruijssen Sim, a transformação é válida apenas para (...)loops do tipo.
Martin Ender
No caso de teste final, por que está \^/entre parênteses?
Kevin Cruijssen
1
@KevinCruijssen Esses são os parênteses mais externos depois que você extrai (<|>((X((T)))[_]))e (([_](((T))X))<|>).
Martin Ender
1
Ah entendo. Portanto ((A)B(C)), (A)(B)(C)as regras 1 e 2 se tornarão subsequentes: ((A)B(C))(A)(B(C))(regra 1) → (A)(B)(C)(regra 2).
Kevin Cruijssen

Respostas:

6

Retina 0.8.2 , 113 107 67 66 bytes

+`\(\)|(\()?(\(((\()|(?<-4>\))|[^()])*(?(4)@)\))(?(1)|(\)))
$5$2$1

Experimente online! Inclui economia de 3 bytes graças ao @MartinEnder. Explicação:

+`

Aplique a substituição repetidamente até que não haja correspondências.

\(\)|

Corresponda a um loop vazio (nesse caso, nada é capturado, portanto a substituição simplesmente o exclui) ou:

(\()?

Corresponder opcionalmente a (. Isso é capturado no grupo 1 se corresponder, mas não se não corresponder.

(\(

Capture o corpo principal da partida no grupo 2 e combine a (.

(
 (\()
|
 (<-4>\))
|
 [^()]
)*

Corresponda repetidamente a (, capturando-o no grupo 4, ou a ), removendo uma captura do grupo 4 (falhando se não houver um) ou outra coisa.

(?(4)@)

Verifique se não há capturas sobressalentes no grupo 4.

\))

Finalize o grupo de captura 2 com outro ).

(?(1)|(\)))

Se o grupo de captura 1 estiver vazio, capture um )no grupo de captura 5. (Portanto, exatamente um desses dois grupos terá uma captura).

$5$2$1

Mova o suporte capturado no grupo 1 ou no grupo 5 para o outro lado do grupo 2. Isso tem o efeito de mover o loop interno para a frente ou para o final do loop externo, dependendo de qual lado ele corresponde.

Neil
fonte
2

Stax v1.0.3 +, 76 65 64 62 58 bytes CP437

îÜ•$o,Γ{í]Üf╒9♦╛üΣóç*\$ñ₧└ΦJ♠¥c╥jóu≥3E.╘ⁿ◄◘W₧<¶┼7úê╟┴zç↨aG

70 bytes quando descompactado,

{{.((:/Yc{Z{40=+_41=-c^Ci~^Fdy,,\32&jEa:{a:{a4l$c}Md}X!:Rx!:Rc.()z:rgp

Execute e depure online!

Explicação

{.((:/Yc{Z{40=+_41=-c^Ci~^Fdy,,\32&jEa:{a:{a4l$c}Mdé um bloco que se separa A((B)C)Dem quatro partes e o converte em A(B)(C)D.

X!:Rx!:Rexecuta o bloco na string de entrada (etapa 1), depois reflete a string (a reflexão da string no Stax refere-se a reverter a string mais substituir (traduzir) (<[{/por (to) \}]>)) e executar o bloco na string obtida e depois refleti-la novamente (passo 2). Etapa 2 é essencialmente converter (A(B))para (A)(B).

c.()z:r remova todos os loops vazios (etapa 3).

gpé um gerador que encontra o ponto de correção de uma iteração. Nesse caso, a sequência é iterada com o processo de três etapas até que não seja mais alterada.

Saída implícita.

Weijun Zhou
fonte
1

Python 3 , 226 223 212 206 bytes

Ok, aqui está uma tentativa de resolver isso em um idioma que não suporta regex recursivo.

lambda s:g(g(s,*'()'),*')(').replace('()','')
def g(s,t,u):
 m,*a={},;i=v=0
 for c in s:
  i+=1;a+=[i]*(c==t)
  if c==u:*a,x=a;m[x]=i;v=m.get(x+1)
  if v:return g(s[:x]+s[x+1:v]+t+s[v:],t,u)
 return s[::-1]

Experimente online!

Editar% s:

  • Refatorado [::-1]para economizar 6 bytes, graças ao Mr.Xcoder.

A gfunção é o bloco de construção básico, que encontra uma ocorrência de ((A)B), altera para (A)(B)e depois se aplica ao resultado até que não seja possível mais transformação.

Os principais passos são:

  • Aplique g à entrada normalmente.
  • Aplique gna entrada invertida. Esta execução localiza a ocorrência de))A(B( na entrada reversa, que efetivamente lida com (A(B)).
  • Remova qualquer ocorrência de () .

O problema é gque a estrutura de controle é tão ruim que, ao tentar fazer uma linha, ela ficou inchada demais, então não acho que uma grande melhoria seja possível com base nessa solução.

Bubbler
fonte