Haskell possui tuplas que podem ser escritas como
(a,b,c)
No entanto, este é apenas açúcar sintático para
(,,)a b c
Em geral, uma tupla n pode ser formada com n-1 ,
s entre (
... )
seguido por seus elementos separados por espaços. Por exemplo, a 7-tupla, (1,2,3,4,5,6,7)
pode ser formada por
(,,,,,,)1 2 3 4 5 6 7
Como Haskell não possui tuplas 1, elas não podem ser formadas. Você também não será responsável por tuplas vazias.
Tuplas aninhadas podem ser formadas usando parênteses para substituir a ordem das operações.
((1,2),3) == (,)((,)1 2)3
Como parte de nossa busca para remover todo o açúcar sintático do Haskell , vou pedir que você escreva um programa que remova o açúcar sintático das tuplas de Haskell também.
Seu programa deve usar uma tupla, uma matriz ou uma string representando uma tupla açucarada e deve gerar uma string representando uma tupla "sem açúcar". As tuplas de entrada sempre conterão números inteiros positivos ou outras tuplas.
Como estamos jogando golfe aqui, sua produção deve ser curta. Não deve conter desnecessários
Espaços. Os espaços devem ser usados apenas para separar argumentos de uma função de tupla e não devem aparecer após um
)
ou antes de um(
Parênteses. Parênteses devem ser usados apenas ao formar funções de tupla ou ao aninhar tuplas.
Esta é uma questão de código-golfe, para que as respostas sejam pontuadas em bytes, com menos bytes sendo melhores.
Casos de teste
(1,2) -> (,)1 2
(1,2,3) -> (,,)1 2 3
((1,2),3) -> (,)((,)1 2)3
(1,2,3,4) -> (,,,)1 2 3 4
(1,(2,3)) -> (,)1((,)2 3)
(10,1) -> (,)10 1
,
((1,(2,3)),4,(5,6))
e(1,(2,3),4)
.Respostas:
Haskell ,
169148 bytesExperimente online! Toma a tupla como uma string.
init.tail.fst.([]%)
é a função principal anônima. Ligue-o a, por exemplo,f
e use comof "(3,(14,1),4,7)"
, o que produz"(,,,)3((,)14 1)4 7"
.Por que a entrada não é fornecida como uma tupla de Haskell, você pergunta? Como Haskell é fortemente digitado, uma tupla
(1,2)
tem o tipo(Int,Int)
1 e uma tupla(1,(2,3))
tem o tipo(Int,(Int,Int))
. Assim, uma função que aceita o primeiro tipo de tupla não pode ser aplicada ao segundo tipo e, especialmente, não pode haver função que use uma tupla arbitrária 2 .Explicação:
p:k="(,"
é uma maneira curta de atribuirp
a'('
ek
para","
.(%)
é a função de análise e conversão recursiva. O primeiro argumento é uma lista de entradas de tupla já analisadas, o segundo argumento é o restante da string original. Cada chamada retorna uma tupla da tupla atual convertida (como uma sequência e entre colchetes) e o restante da sequência.l%('(':r)
Se a sequência começar com um colchete de abertura, precisamos analisar uma nova entrada da tupla.(y,x:s)<-[]%r
Aplicamos recursivamente%
e obtemos uma entrada de tuplay
e a sequência restante dividida no próximo caracterex
e no restante da sequências
.m<-y:l
Adicionamos a nova entraday
à lista atual de entradas já encontradasl
e chamamos o resultadom
.x
agora é uma vírgula,
ou um colchete de fechamento)
. Olast$ <B> :[ <A> |x<',']
é apenas uma maneira mais curta da escritaif x == ')' then <A> else <B>
.,
for o próximo, precisamos analisar recursivamente a próxima entrada:m%(p:s)
Anexamos um colchete de abertura para terminar no caso correto e passar a lista de entradas já encontradasm
.x == ')'
, concluímos a tupla atual e precisamos fazer a transformação necessária:(p:p:(l>>k)++x:foldl(\r x->x++[' '|x>k,r>k]++r)[x]m,s)
p:p:(l>>k)++x:
Se temos achado n entradas, entãom
tem n elementos ey
, a lista antes de adicionar o elemento mais encontrado recentemente, tem n-1 entradas. Isso é útil, pois precisamos do n-1,
para uman
tupla de elemento el>>k
trabalha em listas como "concatenar a listak
consigo mesma quantas vezesy
tiver elementos" . Assim, esta primeira parte produz algumas cordas como"((,,,)"
.foldl(\r x->x++[' '|x>k,r>k]++r)[x]m
concatena os elementos dem
(na ordem inversa, porque adicionando novas entradas à frente emm
si foi construído na ordem inversa) e adicionando apenas espaços entre dois elementos se ambos forem números:[' '|x>k,r>k]
verificamos se as entradas atuaisx
er
os números são comparados lexicograficamente eles para","
- se eles não são números, eles já são uma representação de tupla entre colchetes e são'(' < ','
retidos.l%('(':r)
logo no início falhar, então vamos acabar na última linha:l%r=lex r!!0
. Isso significa que precisamos analisar um número e retornar o número e o restante da string. Felizmente, existe alex
função que faz exatamente isso (analisa o próximo token Haskell válido, não apenas números). No entanto, a tupla resultante é agrupada em uma lista, portanto, usamos!!0
o primeiro elemento da lista.init.tail.fst.([]%)
é a função principal que pega uma string e se aplica%
a uma lista vazia. Por exemplo, para uma entrada"(1,2)"
, aplicando([]%)
rendimentos("((,)1 2)","")
, para que a tupla externa e os colchetes precisem ser removidos.fst
obtém o primeiro elemento da tupla,tail
remove o colchete de fechamento einit
o de abertura.Edit: Muito obrigado a @ Ørjan Johansen por jogar um total de 21 bytes !
1 Na verdade, o tipo é (Num t1, Num t) => (t, t1) , mas essa é uma história diferente.
2 Ignorando funções polimórficas como id , que não podem realmente funcionar com suas entradas.
fonte
Desugarable
, mas seria necessário declarar instâncias paraInt
e todos os tipos de tupla.g
pode ser encurtadofoldr1(\x r->x++[' '|x>k,r>k]++r)
e embutido.show (1,2,3,4,5,6,7,8,9,0,1,2,3,4,5)
na GHCi, em seguida, adicione um,6
no final e tente novamente.)m<-y:l
, dobre à esquerda em vez de à direita e use[x]
como valor inicial. Experimente online!f
pode ser anônimo:init.tail.fst.([]%)
.Haskell,
141 bytes138 bytes (Graças a Ørjan Johansen)f
tem o tipoExp -> String
.Entrada: uma recessão de Haskell de modelo
Exp
(ou seja, a representação AST padrão de valores de Haskell de tipo arbitrário - basicamente, analisou o código de Haskell antes da verificação de tipo); deve representar uma tupla contendo apenas números inteiros não negativos e outras tuplas.Saída: uma sequência que contém a sintaxe desejada para essa expressão de tupla.
Demo:
fonte
")"++
para')':
em dois lugares e economizar espaço depoistail
movendo-o para fora dos parênteses.Haskell , 119 bytes
Experimente online! Isso usa um tipo de dados personalizado
T
para representar tuplas, ou seja, uma tupla((1,2),3)
é representada comoU[U[I 1,I 2],I 3]
. Exemplo de uso:init.tail.f $ U[U[I 1,I 2],I 3]
rendimentos(,)((,)1 2)3
.fonte
Python 2 , 110 bytes
Experimente online!
Leva um
tuple
.fonte
GNU sed,
14982 + 2 = 84 bytes+2 bytes para
-r
sinalizador.Experimente online!
Explicação
fonte
((1,(2,3)),4,(5,6))
e(1,(2,3),4)
.JavaScript, 75 bytes
Matriz de entrada do número | matriz, sequência de saída.
Graças a Neil, economize 2 bytes
fonte
(1/t?' ':0)+v
pode ser1/t?' '+v:v
.Mathematica, 94 bytes
Contém uma função
U+F4A1
interna não imprimívelFunction
.Retorna um
List
número inteiroString
s. Se este não for permitido, isto pode ser corrigido através da adição de mais 10 bytes (esta versão tem umList
deList
s /Integer
s):fonte
Pip , 45 bytes
Esta é uma função que recebe uma lista como argumento. Experimente online!
Versão comentada
fonte
JavaScript (ES6),
8884 bytesToma uma matriz de números inteiros e matrizes. Editar: salvou 1 byte usando em
s+=
vez de dois usos separados des+
. Salvei mais 3 bytes agora que posso simplificar o ternário interno. Se eu roubar as idéias do @ tsh, posso reduzi-lo para 76 bytes:fonte
Your program should take either a tuple or a string representing a sugary tuple
Eu presumo que uma matriz de matrizes / números inteiros deve estar bem.R, 316 bytes?
(Tenho que sair e não tenho certeza da maneira correta de contar bytes ... além disso, não é uma ótima solução, mas queria publicá-la, pois passei o tempo fazendo isso ...)
Casos de teste:
fonte
JavaScript (ES6), 72 bytes
Entrada: matriz contendo números e / ou matrizes
Saída: string
Uso: f ([...])
Conclui todos os casos de teste, melhorias são bem-vindas
fonte
Bytes C, 308 ou 339
308 ou 339 bytes, dependendo da passagem ou não de um ponteiro para o final da sequência de entrada; a última linha existe apenas para permitir a passagem direta de uma string literal sem ter que calcular seu comprimento.
Explicação
Um algoritmo bastante simples. Ele conta o número de vírgulas na profundidade atual, as imprime como um construtor de tupla e, em seguida, acompanha os argumentos da tupla, escapados (espaços entre números, tuplas aninhadas entre parênteses), recursivamente.
Casos de teste e aplicação
fonte