fundo
(Baseado em uma história verdadeira e comovente)
No meu tempo, eu brinquei com o Lisp e idiomas semelhantes com frequência. Eu escrevi com eles, os executei, os interpretei, os projetei e fiz máquinas escreverem com eles para mim ... E se há uma coisa que me incomoda, é ver o Lisp que não está de acordo com o meu estilo de formatação específico.
Infelizmente, alguns editores de texto ( tosse XCode tosse ) tendem a tirar minhas lindas abas e espaços sempre que o código é copiado e colado ... Pegue esta sintaxe do Lisp, muito bem espaçada:
(A
(B
(C)
(D))
(E))
(Onde ABCDE
estão as funções arbitrárias)
ALGUNS editores de texto restringem esse código adorável para o seguinte fim:
(A
(B
(C)
(D))
(E))
Que bagunça! Isso não é legível!
Me ajuda aqui?
O desafio
Seu objetivo neste desafio é pegar uma série de funções separadas por novas linhas em um formato descrito abaixo e retornar um arranjo mais bonito que destaque legibilidade e elegância.
A entrada
Definimos uma função F
dos N
argumentos arity como uma construção semelhante à seguinte:
(F (G1 ...) (G2 ...) (G3 ...) ... (GN ...))
onde G1, G2, ..., GN
estão todas as funções em si mesmas. Uma 0
função de aridade A
é simplesmente (A)
, enquanto uma 2
função de aridade B
é da forma(B (...) (...))
Seu código deve receber entrada como uma série de funções com uma única nova linha antes dos parênteses principais de cada função (exceto a primeira função). O exemplo acima é uma entrada válida.
Você pode assumir:
- Os parênteses estão equilibrados.
- Uma função nunca precisará ser recuada mais de 250 vezes.
- TODAS as funções estão entre parênteses:
()
- O nome de uma função conterá apenas caracteres ASCII imprimíveis.
- O nome de uma função nunca conterá parênteses ou espaços.
- Há uma nova linha à direita opcional na entrada.
A saída
Seu código deve produzir o mesmo conjunto de funções, onde as únicas alterações feitas são as adições de espaços ou tabulações antes dos parênteses principais de funções. A saída deve obedecer às seguintes regras:
- A primeira função (e as funções posteriores de nível superior) fornecidas não deve ter espaços anteriores
- Um argumento para a localização horizontal de uma função é exatamente uma guia à direita da localização horizontal dessa função.
- Uma guia é definida pela implementação, mas deve ter pelo menos três espaços.
- Opcionalmente, você pode imprimir no máximo dois espaços após cada linha.
Regras
- Este é o código-golfe: o código mais curto vence!
- As brechas padrão não são permitidas.
Exemplos
Entrada:
(A
(B
(C)
(D))
(E))
Saída:
(A
(B
(C)
(D))
(E))
Entrada:
(!@#$%^&*
(asdfghjklm
(this_string_is_particularly_long
(...))
(123456789)))
(THIS_IS_TOP_LEVEL_AGAIN
(HERE'S_AN_ARGUMENT))
Saída:
(!@#$%^&*
(asdfghjklm
(this_string_is_particularly_long
(...))
(123456789)))
(THIS_IS_TOP_LEVEL_AGAIN
(HERE'S_AN_ARGUMENT))
Entrada:
(-:0
(*:0
(%:0
(Arg:6)
(Write:0
(Read:0
(Arg:30))
(Write:0
(Const:-6)
(Arg:10))))
(%:0
(Const:9)
(/:0
(Const:-13)
(%:0
(Arg:14)
(Arg:0)))))
(WriteArg:22
(-:0
(Const:45)
(?:0
(Arg:3)
(Arg:22)
(Arg:0)))))
Saída:
(-:0
(*:0
(%:0
(Arg:6)
(Write:0
(Read:0
(Arg:30))
(Write:0
(Const:-6)
(Arg:10))))
(%:0
(Const:9)
(/:0
(Const:-13)
(%:0
(Arg:14)
(Arg:0)))))
(WriteArg:22
(-:0
(Const:45)
(?:0
(Arg:3)
(Arg:22)
(Arg:0)))))
fonte
()
?Respostas:
Pitão,
24201918 bytesIncrementa um contador para cada linha, conta o número total de parênteses de fechamento encontrados até o momento e o subtrai do contador. Em seguida, recuamos por
counter
tabulações.fonte
*4
preferência é codificada e redundante.FN.z+*ZC9N~Z-1/N\)
permite usar a largura do recuo do editor e salvar um byte.\<tab>
ouC9
.Lisp comum -
486414 bytes (versão Rube Goldberg)Aproximação
Em vez de fazer como todos os outros e contar parênteses à mão, vamos chamar o leitor Lisp e fazê-lo da maneira certa :-)
(
,)
ou espaços em branco como strings.read
função padrão para criar listas reais.p
cada uma dessas listas, que as grava recursivamente na saída padrão com o formato solicitado. Em particular, as strings são impressas sem aspas.Como conseqüência dessa abordagem:
Exemplo
Lendo de um arquivo, usando este wrapper:
Aqui está o resultado:
(parece que as guias são convertidas em espaços aqui)
Pretty-impresso (versão golfed)
Ao contrário da versão original mais segura, esperamos que a entrada seja válida.
fonte
Retina ,
8983 bytesOnde
<tab>
representa um caractere de tabulação real (0x09) e<empty>
representa uma linha vazia. Depois de fazer essas substituições, você pode executar o código acima com o-s
sinalizador No entanto, não estou contando esse sinalizador, porque você também pode colocar cada linha em seu próprio arquivo de origem. Nesse caso, as 7 novas linhas serão substituídas por 7 bytes de penalidade para os arquivos de origem adicionais.Este é um programa completo, inserindo STDIN e imprimindo o resultado em STDOUT.
Explicação
Cada par de linhas define uma substituição de regex. A idéia básica é usar os grupos de balanceamento do .NET para contar a profundidade atual até um determinado
(
e, em seguida, inserir várias guias antes disso(
.Primeiro, preparamos a entrada. Não podemos realmente escrever de volta um número condicional de guias, se não pudermos encontrá-las em algum lugar da string de entrada para capturá-las. Então começamos duplicando toda a entrada, separada por uma guia. Observe que
s`
apenas ativa o modificador de linha única (ou "ponto tudo"), o que garante que o mesmo.
também corresponda a novas linhas.Agora, transformamos todos os personagens depois dessa guia em uma guia também. Isso nos fornece uma quantidade suficiente de guias no final da sequência, sem modificar a sequência original até o momento.
Esta é a carne da solução. O
m
es
ativa o modo de várias linhas (para^
coincidir com o início das linhas) e o modo de linha única. O+
instrui o Retina a continuar repetindo essa substituição até que a saída pare de mudar (nesse caso, isso significa até que o padrão não corresponda mais à sequência).O padrão em si corresponde a um prefixo da entrada até um não processado
(
(ou seja, um(
que não possui nenhuma guia antes, mas deve). Ao mesmo tempo, determina a profundidade do prefixo com grupos de balanceamento, de modo que a altura da pilha2
corresponda à profundidade atual e, portanto, ao número de guias que precisamos anexar. Essa é esta parte:Ele corresponde a
(
, empurrando-o para a2
pilha ou a)
, capturando a última captura da2
pilha ou corresponde a outra coisa e deixa a pilha intocada. Como os parênteses garantem um equilíbrio, não precisamos nos preocupar em tentar sair de uma pilha vazia.Depois de analisarmos a sequência dessa maneira e encontrarmos um não processado
(
para parar, a cabeça de impressão então pula para o final da sequência e captura as guias no grupo3
enquanto aparece da2
pilha até ficar vazia:Ao usar um
+
in, garantimos que o padrão corresponda apenas a qualquer coisa se pelo menos uma guia for inserida na correspondência - isso evita um loop infinito quando existem várias funções no nível raiz.Por fim, apenas nos livramos dessas guias auxiliares no final da string para limpar o resultado.
fonte
C:
9594 caracteresAinda não é muito disputado e, pela pergunta, não tenho certeza se as abas são aceitáveis, e é isso que uso aqui.
Ungolfed:
Edit: Feito para que saia no EOF.
fonte
if(c<11)
vez deif(c==10)
?Julia,
10399979488 bytesIsso define uma função sem nome que aceita uma sequência e imprime a versão recuada. Para chamá-lo, dê um nome, por exemplo
f=p->...
. Observe que a entrada deve ser uma sequência Julia válida, portanto, os cifrões ($
) devem ser escapados.Ungolfed + explicação:
Exemplo, fingir cada conjunto de quatro espaços é uma guia:
Todas as sugestões são bem-vindas!
fonte
Haskell,
8381uma solução sem muitos pontos.
fonte
h=
.Perl, 41
40
caracteres+1
para-p
.Correr com:
fonte
Python
2-8878 bytesSolução bastante simples (e não muito curta):
fonte
'\t'
vez de' '
e salvar um byte; 2) não é necessário atribuirinput.split()
a uma variável, pois ela é usada apenas uma vez (o mesmo parac
e também -d
basta mover aprint
instrução); 3) a precedência do operador significa quel*c
não são necessários parênteses . Além disso, parece quef
não é usado para nada - isso é uma relíquia de uma versão anterior?raw_input
vez deinput
(e não se esqueça dos parênteses depois dele!).CJam, 20 bytes
Experimente online no intérprete CJam .
Como funciona
fonte