Claramente entre parênteses trens APL

19

No APL, você pode escrever funções tácitas, chamadas de trens . Como eles funcionam é irrelevante para esse desafio. Aqui estão as diferentes maneiras pelas quais eles podem ser agrupados, usando como função:

⍴      -> ⍴
⍴⍴     -> ⍴⍴
⍴⍴⍴    -> ⍴⍴⍴
⍴⍴⍴⍴   -> ⍴(⍴⍴⍴)
⍴⍴⍴⍴⍴  -> ⍴⍴(⍴⍴⍴)
⍴⍴⍴⍴⍴⍴ -> ⍴(⍴⍴(⍴⍴⍴))
...

O pedido permanece o mesmo. O procedimento é que, desde que haja estritamente mais de 3 funções, as últimas 3 funções serão agrupadas em uma função. Se encontrarmos um trem aninhado, parênteses o primeiro, antes de continuar. Aqui está o procedimento aplicado a ⍴⍴⍴⍴⍴⍴:

Step 0: ⍴⍴⍴⍴⍴⍴
There are strictly more than 3 functions, repeat.
Step 1: ⍴⍴⍴(⍴⍴⍴)
There are strictly more than 3 functions, repeat.
Step 2: ⍴(⍴⍴(⍴⍴⍴))
There are 3 or less functions, we're done.

Aqui está o mesmo procedimento aplicado a ⍴⍴⍴(⍴⍴)⍴(⍴⍴⍴⍴(⍴⍴⍴))⍴⍴:

Step 0: ⍴⍴⍴(⍴⍴)⍴(⍴⍴⍴⍴(⍴⍴⍴))⍴⍴
There are strictly more than 3 functions, repeat.
We have met a nested train, applying procedure to that first:
  Step 0: ⍴⍴⍴⍴(⍴⍴⍴)
  There are strictly more than 3 functions, repeat.
  We have met a nested train, applying procedure to that first:
    Step 0: ⍴⍴⍴
    There are 3 or less functions, we're done.
  Step 1: ⍴⍴(⍴⍴(⍴⍴⍴))
  There are 3 or less functions, we're done.
Step 1: ⍴⍴⍴(⍴⍴)⍴((⍴⍴(⍴⍴(⍴⍴⍴)))⍴⍴)
There are strictly more than 3 functions, repeat.
We have met a nested train, applying procedure to that first:
  Step 0: ⍴⍴
  There are 3 or less functions, we're done.
Step 2: ⍴⍴⍴((⍴⍴)⍴((⍴⍴(⍴⍴(⍴⍴⍴)))⍴⍴))
There are strictly more than 3 functions, repeat.
Step 3: ⍴(⍴⍴((⍴⍴)⍴((⍴⍴(⍴⍴(⍴⍴⍴)))⍴⍴)))
There are 3 functions or less, we're done.

Entrada

Para esse desafio, a entrada será simplificada. Isso significa que você pode escolher 2 caracteres diferentes para abrir e fechar parênteses e 1 caractere para funções, diferentes daqueles escolhidos para parênteses. Os caracteres que você escolher devem ser consistentes. A entrada não estará vazia e não conterá parênteses sem conteúdo (ou seja ()).

Resultado

Novamente, você pode escolher 3 caracteres diferentes, 2 para parênteses e 1 para funções. Observe que eles não precisam ser iguais aos escolhidos para entrada, mas devem ser consistentes.

Regras

  • Se houver parênteses que incluam apenas uma função dentro da entrada, você deverá removê-los na saída. Sua saída pode não conter parênteses desnecessários (por exemplo, incluir apenas uma função ou incluir toda a saída).
  • Você não precisa implementar o algoritmo usado aqui, desde que sua solução seja válida para esse desafio.
  • Entrada e saída são cadeias no formato explicado nas seções Entrada e Saída. A entrada terá pelo menos um caractere.
  • É estritamente proibido usar as brechas padrão .
  • Este é o , por isso a resposta mais curta vence. No entanto, não haverá uma resposta aceita, pois essa é uma competição por idioma e para incentivar a resposta em idiomas nos quais essa tarefa resultaria em código mais longo em comparação com o código escrito em outros idiomas.

Casos de teste

Os caracteres usados ​​aqui são ()⍴, você deve substituí-los pelos caracteres escolhidos.

⍴                          -> ⍴
⍴                          -> ⍴
⍴⍴                         -> ⍴⍴
⍴⍴⍴                        -> ⍴⍴⍴
⍴⍴⍴⍴                       -> ⍴(⍴⍴⍴)
⍴⍴⍴⍴⍴⍴⍴⍴⍴⍴⍴⍴⍴⍴⍴            -> ⍴⍴(⍴⍴(⍴⍴(⍴⍴(⍴⍴(⍴⍴(⍴⍴⍴))))))
⍴⍴⍴⍴⍴(⍴⍴⍴)⍴⍴(⍴(⍴⍴⍴)⍴⍴⍴)⍴⍴⍴ -> ⍴(⍴⍴(⍴⍴((⍴⍴⍴)⍴(⍴(⍴(⍴⍴⍴)(⍴⍴⍴))(⍴⍴⍴)))))
(⍴⍴⍴)(⍴⍴⍴)(⍴⍴⍴)            -> (⍴⍴⍴)(⍴⍴⍴)(⍴⍴⍴)
(⍴⍴⍴)(⍴⍴⍴)⍴⍴⍴              -> (⍴⍴⍴)(⍴⍴⍴)(⍴⍴⍴)
⍴⍴(⍴)⍴⍴                    -> ⍴⍴(⍴⍴⍴)
((⍴⍴))                     -> ⍴⍴
⍴⍴((⍴⍴))⍴⍴                 -> ⍴⍴((⍴⍴)⍴⍴)

Este desafio foi publicado na Sandbox. Se você tiver o privilégio necessário, poderá ver a postagem da sandbox aqui .

Erik, o Outgolfer
fonte
2
Eu acho que Fully é um título melhor que Clearly .
Adám 11/11/19
@ Adám Eu esperava essa resposta de referência, mas não receberá muitos
votos positivos
@ Adám A parte Claramente do título se refere ao fato de que você deve remover parênteses desnecessários. Totalmente é algo que você deve fazer quando responde a um desafio; p
Erik the Outgolfer
É verdade que essa função sempre será idempotente?
Esolanging Fruit

Respostas:

7

APL (Dyalog Classic) , 71 68 65 63 bytes

0{⍵≡⍕⍵:⍵⋄⍬≡⍵:'⍬'1=≢⍵:⍺∇⊃⍵⋄3≥≢⍵:⍺⌽')(',⍣⍺∊1∇¨⍵⋄⍺∇¯3(↓,∘⊂1∇↑)⍵}⍎

Experimente online!

Os personagens que eu escolhi para I / O são '(', ')'e '⍬'.

Esta solução é em si um trem de APL.

analisa a entrada como se fosse uma matriz aninhada - uma árvore com vetores numéricos vazios ( ) como folhas.

O dfn (ie lambda - { }) atravessa a árvore recursivamente e a converte em uma string entre parênteses. O argumento esquerdo controla se os parênteses devem ser adicionados ao nível atual, se necessário.

O dfn lida com os seguintes casos com base no argumento correto:

  • se já é uma string ( ⍵≡⍕⍵), retorne-a

  • se for , devolva o char'⍬'

  • se for um singleton, basta ir mais fundo ( é o símbolo de uma chamada recursiva)

  • se o seu comprimento for ≤3, recorra para cada um dos itens e envolva-o, ()se necessário

  • caso contrário, recursione a cauda 3, prefixe tudo menos a 3 cauda e recue novamente

ngn
fonte
Parece 63 caracteres, a maioria deles Unicode. Qual codificação de caracteres produz 63 bytes para isso? Eu faço 141 bytes em UTF8.
Corey
@Corey Meta-postagem relevante .
Adám
@ Adám Obrigado por isso. Procurei, mas não sabia o que procurar para obter essa resposta.
Corey #
3

Python 2 , 224 208 204 bytes

-16 bytes graças ao Sr. Xcoder -4 bytes graças ao ovs

r=str.replace
p='p'
def c(l):
 while len(l)>3:l=l[:-3]+(l[-3:],)
 return l and map(c,l)or l
print r(r(r(r(r(`c(eval(r(r(r(input(),'(p)',p),p,'[],'),')','),')))`,'[]',p),*'[('),*'])'),' ',''),',','')[1:-1]

Experimente online! ou Experimente todos os casos de teste

O código pode ser dividido em 3 etapas principais:
Convertendo a entrada em uma lista aninhada e substituindo (p)->p. A função única pserá substituída por uma lista vazia.

eval(r(r(r(input(),'(p)',p),p,'[],'),')','),'))

Uma função recursiva para aplicar a regra "3 ou menos" na lista atual e chamar todas as sublistas.

def c(l):
 while len(l)>3:l=l[:-3]+(l[-3:],)
 return l and map(c,l)or l

Muitas substituições para formatar para o formato de saída desejado

r(r(r(r(r(`c(...)`,'[]',p),*'[('),*'])'),' ',''),',','')[1:-1]
Cajado
fonte
204 bytes
ovs
11
Isso não simplifica ((pp))(ou p((pp))p).
Martin Ender
2

CJam , 56 bytes

Bate APL!

lW%~]]]{{_,{K_,({~}|}&}%{_,3>}{3/(aa\+:~}w}:K~~`1>W<W%S/

Experimente online!

Isso funciona (eu acho) e não tenho idéia do porquê ...

Caracteres de entrada são ][Tpara ()⍴e caracteres de saída são ][0para ()⍴(sim, isso significa que eles são revertidos do que você esperaria; por exemplo, você pode passar TTT]TT[T]TTTT]TTT[[TT).

Visão geral de alto nível

O programa trabalha com a entrada para trás, porque é mais conveniente. Para analisar a entrada, aproveitamos o analisador do CJam - reverter e executar a entrada fornece a forma analisada (para trás) da entrada.

Em seguida, definimos um procedimento K. Kfaz a maior parte do trabalho para a nossa submissão e funciona da seguinte maneira:

  • A matriz de entrada será uma mistura de zeros e sub-matrizes não vazias. Identifique as sub-matrizes e aplique-as recursivamente Ka elas. O resultado deve ser outra matriz e, se essa matriz consistir em apenas um elemento, descompacte-o (isso elimina os parênteses redundantes).
  • Desde que o resultado tenha mais de três elementos, agrupe os três primeiros (não os três últimos; lembre-se de que a entrada está sendo processada de trás para frente) em uma única lista.
  • Retorne o resultado.

Ao aplicar Kà entrada, obtemos a forma entre parênteses corretamente da entrada (a única coisa a ser observada é que, na verdade, envolvemos a entrada em uma lista de singleton e a desembrulhamos depois; a razão para isso é que queremos o trecho que descompacta os singletons para aplicar ao programa de nível superior, e não apenas às suas sub-matrizes). Depois, aplicamos uma formatação mínima para obter nosso resultado.

Alguma explicação para bits de golfe

O golfe de que mais me orgulho é o uso ,para realizar a verificação entre números inteiros e matrizes.

  • Se o topo da pilha for um número inteiro n , ,gera o intervalo [0..n) . Como o único número inteiro que encontraremos é 0, isso sempre nos dá a lista vazia [], que é falsey.
  • Se o topo da pilha é uma matriz, ,leva seu comprimento. Como todas as matrizes que encontramos serão vazias, isso sempre nos dá um número inteiro positivo, que é verdadeiro.

Outro golfe que pode ser interessante é o método que eu uso para agrupar os três primeiros elementos da matriz; é um pouco semelhante ao meu envio "Turing complete language interpreter code golf" . O CJam não tem um caminho curto para dividir uma matriz em duas partes (você pode tentar dividir a primeira parte e depois a outra parte, mantendo a matriz e o índice originais na pilha, mas isso não funciona muito bem) , então o que eu faço é usar 3/, que agrupa uma matriz em blocos de 3. Em seguida, posso sair do primeiro elemento (, agrupar a matriz duas vezes aae, em seguida, anexar novamente ao início da lista \+. O motivo pelo qual :~agrupamos o array duas vezes é que precisamos remover uma camada , já que também agrupamos o restante do array em seções.

Esolanging Fruit
fonte
Nitpick: este bate o APL sem os builtins .
Erik the Outgolfer
@EriktheOutgolfer Fair suficiente.
Esolanging Fruit
0

JavaScript (ES6), 149 146 bytes

i='a';f=s=>s==(s=s[R='replace'](/\((\w+)\)/,(q,t)=>(f[q=i+=0]=f(t),q)))&&s==(s=s[R](/(?!^)((a0+|p){3})$/,"($1)"))?s[R](/a0+/g,t=>`(${f[t]})`):f(s)
<textarea cols=80 id=I>ppp(pp)p(pppp(ppp))pp</textarea><br>
<button onclick=O.innerText=f(I.value)>Run</button><br>
<pre id=O></pre>

Usa ()p, embora você use uma letra diferente, você pode simplesmente mudar o ptexto no final.

ETHproductions
fonte