Recentemente, alguém propôs limites mais rigorosos para o comprimento da linha padrão do Python:
Claramente, nenhum programa deve usar mais de 80 caracteres por linha, por várias razões. Antes de mais nada, para facilitar a leitura e a manutenção, é importante ter um padrão sólido, para que possamos ajustar a largura de nossos editores de texto adequadamente. Como um benefício secundário, o código pode ser facilmente transferido para a mídia que pode ter restrições e onde a adição de quebras de linha pode ser uma distração, como páginas impressas para revisão em uma reunião ou cartões perfurados.
Mas 80 caracteres são altos demais? Alguns sugerem 79, ou até 75, para permitir que um terminal com 80 caracteres se encaixe no código com algumas colunas dedicadas aos números das linhas. Claramente, em última análise, menor é melhor, pois os limites mais baixos permitem que o código seja usado em mais situações sem reformatação.
Seu objetivo é encontrar e demonstrar o comprimento mínimo de linha exigido pelo seu idioma favorito, escrevendo uma variante do FizzBuzz com o menor número de caracteres em qualquer linha.
Entrada
Um número inteiro, n , através de qualquer método desejado.
Saída
Imprima os números de 1 a n , ( n ≥ 1, n ∈ ℤ) separados por quebras de linha, exceto:
- para múltiplos de 3 impressões "Apple"
- para múltiplos de 5 impressões "Torta"
- para múltiplos de 3 e 5 impressos "ApplePie"
Pontuação
O comprimento máximo da linha em bytes, sem incluir a quebra de linha (Cr, CrLf, Lf ou outra quebra padrão do sistema, especifique, conforme desejado), e o comprimento total do código em bytes como desempatador.
Regras
Todas as quebras de linha devem ser significativas. As quebras de linha que podem ser removidas e as linhas adjacentes diretamente concatenadas sem impacto na saída devem ser removidas.
Respostas:
> <> , 1 byte por linha,
243161135 bytes-26 bytes graças a Jo King!
Linguagens 2D FTW! Embora escrever loops e ramificações usando instruções goto em vez da estrutura 2D não seja divertido.
Experimente online! , ou assista no playground de peixes !
O peixe nada para baixo ao longo do código, usando gotos condicionais para pular as coisas, dependendo do que divide o acumulador.
Acredito que isso atenda às especificações: sejam quais forem as novas linhas removidas, o peixe sempre atinge a inicial
v
(a única instrução de mudança de direção presente); portanto, o peixe sempre nada para baixo na primeira coluna. Assim, excluir uma nova linha tem o efeito de simplesmente remover o próximo caractere do caminho do peixe, e não acho que você possa remover qualquer um dos caracteres sem alterar a saída.fonte
Haskell , 3 bytes / linha,
494 471 470 463 453 450461 bytesEDITAR:
-1+x
parax-1
.--
linha extra depoisx-
.f
uso emc 47:[]
vez de[c 47&0]
.w
.a="Apple"
ep="Pie"
in#
e use uma recursão fictícia para o caso 15.w
emf
. Remova redundante--
entrex
e15
.%
função. Finalmente, fiz alguns testes automatizados para garantir que não houvesse mais surpresas.f
pega umInt
e retorna umString
.Experimente online!
Restrições da fonte de teste! (A linha 70 é excluída do teste porque a remoção de sua nova linha causa um loop infinito sem saída.)
Versão com os truques de aperto mais importantes removidos:
Como funciona
{}
. Como estou definindo uma função em vez de um programa inteiro, não sei bem como contar bytes; Eu escolhi para contar defensivamente tanto o{}
s e um extra de;
separador de declaração (o último sendo geralmente uma nova linha no modo Haskell normal.)--
comentários de linha, que tornam a próxima nova linha não removível e também uma nova linha anterior, no caso em que a linha anterior termina com um caractere de operador (que não faz parte de um comentário de linha) .\
barras invertidas em literais de string, recuada para continuações de linha com possível recuo. Um espaço de cadeia com delimitadores é removido da cadeia analisada."Apple"
e"Pie"
isso aparece diretamente na saída. Para"8"
e"9"
uma correspondência de padrão é usada para dar um erro se a sequência tiver mais de um caractere.&
e%
, que permitem forçar uma linha a terminar em um caractere de operador para o primeiro truque. Precisamos disso para finalizar literais de string, porque\"
é muito amplo para acrescentar--
.&
é o geral, definido de tal forma quex&y=x
.%
é definido de forma que[a]%y=a
, permitindo que ele substitua!!0
e imponha simultaneamente que seu argumento de cadeia de caracteres tenha o comprimento 1.\n
parece impossível caber em uma literal de seqüência de caracteres com apenas 3 bytes na linha.c x=["9"%0,"8"%0..]!!x
é usado para converter deInt
um caractere, contando do dígito'9'
para baixo.show
são quatro caracteres, a saída numérica deve ser implementada manualmente.d
é uma lista das cadeias de dígitos"1".."9"
.n
é uma lista infinita de representações numéricas["1","2","3",...]
definidas recursivamente usandod
.#
converte umInt
x
em sua forma ApplePie, com um primeiro argumento extra que é ogcd
dex
15.fonte
Haskell , 7 bytes / linha, 339 bytes
O requisito de quebras de linha sejam significativas faz deste um desafio não trivial em Haskell. Quase não há maneiras de inserir quebras de linha que não possam ser removidas; portanto, tudo deve ser feito com instruções minúsculas.
Experimente online!
fonte
Gelatina ,
32 bytes / linha,1068056 bytesLinhas e colunas da cadeia literal são transpostas, portanto, a remoção de novas linhas atrapalha sua ordem.
As linhas restantes são links / funções separados e contêm chamadas de função (
¢
), portanto, elas só podem ser concatenadas se as chamadas de função também forem eliminadas.Experimente online!
fonte
TI-BASIC, 4 bytes por linha
Como o objetivo é apenas minimizar o comprimento máximo da linha, algumas delas são mais longas do que precisam, mas a menor que eu pude criar na linha mais longa foi de 4 bytes. Portanto, achei que seria mais fácil ler o código se mesclasse as linhas que poderiam ser combinadas sem exceder 4 bytes.
Ungolfed
Sobre o idioma e as limitações
O TI-BASIC é uma linguagem tokenizada e, nesse caso, cada um dos tokens tem 1 byte, com exceção das
StrN
variáveis, que são 2 bytes. Além disso, você pode deixar de fechar parênteses na maioria das vezes. Aremainder(
função é de 2 bytes; portanto, para isso, é necessário pelo menos 5 bytes (um para a função, dois para os argumentos e um para a vírgularemainder(I,3
). Em vez disso, usei as funçõesfPart(
enot(
para torná-lo mais curto, que são ambos tokens de 1 byte. Além disso, você pode ver que eu usei a variável embutidaAns
bastante a interna, pois qualquer expressão que é avaliada em uma linha por si só é automaticamente armazenada nela. Portanto, posso economizar alguns bytes dividindo as expressões e atribuições.Outra estratégia era obviamente minimizar as atribuições de strings. Meu método para fazer isso dependia do comprimento máximo da linha no restante do código. Depois de determinar que tinha 4 bytes, consegui agrupar o máximo de cada sequência na mesma linha possível para minimizar a quantidade de atribuições necessárias. Eu fiz isso por uma questão de legibilidade.
Os fatores limitantes neste código são as atribuições para variáveis de sequência e concatenação com variáveis de sequência. As linhas
Ans→Str1
eStr1+Ans
dois têm 4 bytes no total. Eu precisaria encontrar uma maneira de eliminar completamente as variáveis de string para minimizar ainda mais o comprimento máximo da linha no meu código. Tudo o resto pode ser reduzido para um máximo de 3 bytes ou menos por linha.O problema está nas atribuições de variáveis numéricas, como
1→I
. Você não pode jogar mais isso de alguma forma sem encontrar uma solução sem variáveis que não excedam 2 bytes de comprimento de linha. Isso é impossível para esse desafio.Operadores binários como
+
exigem o símbolo do operador e os argumentos esquerdo e direito. Portanto, sem isso, você não seria capaz de concatenar seqüências de caracteres. Sem concatenação de cadeias, não haveria maneira de exibir as cadeias necessárias para este programa concluir o desafio sem exceder 2 bytes no comprimento da linha. Portanto, o limite teórico para esse desafio nesse idioma seria de 3 bytes por linha, o que não consegui atingir.fonte
If A and B
Ans
token tem 1 byte, enquanto os três caracteres consecutivosAns
são 1, 2 e 2 bytes, respectivamente, para um total de 5. Não é uma sequência ASCII, é literalmente o token quando você o digita na calculadora.C (gcc) , 2 bytes por linha,
374368320310262 bytesEu suponho que pode ser jogado um pouco mais. As barras invertidas que escapam das novas linhas o tornam meio trivial.
Experimente online!
fonte
&&
.Python 3 , 4 bytes / linha, 113 bytes
Experimente online!
fonte
PHP 7, 2 bytes por linha
fonte
Aceto , 1 byte por linha, 230 bytes
Bem, isso não foi divertido de escrever. Como um fungoide, as estruturas de controle do Aceto dependem fortemente de sua natureza 2D, mas podemos contornar isso com muitas, muitas escapadas condicionais (
`
). O único problema com eles é que eles afetam o próximo comando, independentemente de sua presença (todos os programas Aceto são quadrados internamente), e é por isso que precisamos alinhar o programa em alguns locais inserindo linhas vazias em alguns pontos.Os literais de string não podem realmente ser usados, mas os literais de char podem (em alguns lugares; novamente, precisamos alinhá-los).
Chamado com
20
, isso imprime:Esse nunca é o caso aqui, porque é executado de baixo para cima.
Há pelo menos um lugar onde podemos salvar 2 bytes (substituindo o
`X
por um|
ou#
), mas eu o mantive como está devido ao custo de tempo de execução associado à execução de uma curva de Hilbert relativamente grande.Eu também ignorei o requisito implícito para usar
\r
ou\r\n
novas linhas, porque acho que é um erro não intencional do OP. Se houver uma edição ou um comentário que reforce esse requisito, eu posso alterá-lo sem muitos problemas para usar as novas linhas de CR.O bytecount é baseado na codificação de codegolf da Aceto; Latin-7, no qual
£
é um único byte.fonte
Perl 5 , 2 bytes por linha, 182 bytes
Experimente online!
A sintaxe do Perl é muito indulgente, portanto, muitas lacunas podem ser adicionadas ao código e aos comentários adicionados, o que torna a idéia central bastante direta. O principal objetivo desse código é criar uma string contendo o código que queremos executar e
eval
ele. No Perl, é possível chamar uma função usando uma string ou variável com a&{...}
notação, infelizmente, no entanto,eval
não é possível chamar dessa forma, masevalbytes
é, desde que você a chame por meio do . Para manter isso válido, alguns locais tiveram que colocar comentários, para que a remoção das novas linhas resultasse em código que não funcionava.CORE::
namespace. A criação dessa sequência foi bastante direta e o programa é passado diretamente para esta chamada. As strings são construídas utilizando as novas linhas como parte do XOR, para construir essas eu usei esse scriptA rotina do FizzBuzz foi retirada da excelente resposta do primo .
Perl 5 , 1 byte por linha, 172 bytes
Então, agora eu sei que isso é inválido , porque várias linhas novas podem ser removidas, mas como essa foi minha abordagem original para o problema, eu a adicionei. Foi divertido ver até onde você consegue empurrar a sintaxe do Perl! Eu gostei desse problema por mérito próprio, embora seja inválido.
Experimente online!
fonte
SmileBASIC,
97 bytes por linha,159155154152 152 bytesEste foi um desafio muito divertido. Infelizmente, a regra contra quebras de linha desnecessárias causa alguns problemas (embora felizmente não afete o comprimento máximo da linha aqui.) Eu tive que adicionar comentários entre as linhas como
A%=I/3
eA=A%*3
, uma vez queA%=I/3A=A%*3
é analisado corretamente no SB. Eu pude usar um truque para deixar de fora alguns comentários, pois a substituiçãoA
porE
invalida essa linha (isso tem algo a ver com números escritos usandoE
notação, eu acho.3E
É considerado um número inválido em vez de um número e um nome de variável).A maior limitação aqui é obter informações.
INPUT x
é a maneira mais simples permitida, a alternativa é definir uma função com um valor de entrada como,DEF F x
mas que ainda tem 7 caracteres. Fazer uma declaração condicional também é difícil; Não consigo pensar em nada mais curto queWHILE x
.fonte
A%=I/3A=A%*3
for sintaticamente válido, mas logicamente quebrado, você não precisa do caractere de comentário.A%=I/3
eA=A%*3
, portanto, o comentário é necessário.JavaScript (ES6), 3 bytes por linha
Usa a variável global
top
para acessar owindow
objeto, a partir do qualeval
o seguinte código:Você precisará executá-lo no console, pois
top
é inacessível a partir de um snippet de pilha na caixa de areia.fonte
C #, 9 bytes por linha,
248 242230 bytesComo o C # não se importa com quebras de linha, ele precisa de um comentário on-line no final de quase (obrigado Ørjan Johansen) todas as linhas para cumprir as regras. Este programa espera n como um argumento de linha de comando. Aqui está o maior número possível de novas linhas não excluídas:
Mas como a linha mais longa tem 9 bytes, outras linhas também podem ter esse comprimento, eliminando alguns bytes:
fonte
//
entre tokens que se fundiriam, comostatic
evoid
.var
s="";if//
(i%3==0//
)s+=//
"Apple"//
;if(i%5//
.A
da primeira para a segunda linha.Python 2, 5 bytes / linha, 93 bytes
O padrão max6 já está obsoleto.
Experimente online!
Python 2 e 3, 5 bytes / linha, 100 bytes
Experimente online!
fonte
JavaScript, máximo de 6 bytes / linha, 528 bytes
Idéia arrancada daqui .
Código extraído daqui .
Agradecemos a Anders Kaseorg por
g=eval
salvar um byte por linha.Não separados:
fonte
a=""+\n"f"+\n"o"+ ...
e terminando comeval(\na)
é um pouco mais curtof=eval
ef(a)
.PHP, 4 bytes / linha
Experimente online!
fonte
APL (Dyalog) , 5 bytes por linha
Experimente online!
fonte
Retina , 4 bytes / linha
Experimente online!
fonte
R , 10 bytes por linha, 800 bytes
A regra "quebras de linha significativas" tornou esse desafio. Atualmente, isso apenas explica o código do fizzbuzz em uma string e depois o executa.
Experimente online!
Aqui está o código ApplePie concatenado (adaptado do golfe de MickyT aqui ).
E a versão não destruída do código de análise:
Aqui eu uso
toString
para concatenar a lista de símbolosa
em uma única string. No entanto, o comportamento padrão é separar cada símbolo com,
, portanto, chamamosgsub
para substituí-los por nulos. Então passamos paraparse
eeval
fazemos o trabalho sujo.É possível que exista uma abordagem que não use esse método de análise de string e apenas implemente o fizzbuzz, mas parece-me que usar
for
ouwhile
ou definir umfunction
necessidades linhas mais longas do que a abordagem atual.fonte
Rubi,
105 bytes / linha,354214 bytes-140 bytes da pontuação bruta de @NieDzejkob.
Como funciona
O Ruby concatenará automaticamente sequências de literais de cadeia de caracteres (exceto literais de um caractere como
?a
) na mesma instrução. Isso significa quex = "a" 'b' "c" %q{d}
é equivalente ax = "abcd"
. Usamos isso para dividir o código do FizzBuzz em sequências muito menores para chamareval
, pois+
invalidará o programa devido à regra de remoção de novas linhas, mas\
causará erros de sintaxe se as novas linhas forem removidas!fonte
eval
linha inicial é mais longa que o resto, certo?Julia 0,6 , 5 bytes por linha, total de 168 bytes
Experimente online!
o
print
traz isso inevitavelmente (em conflito) para o território de 5 bytes por linha.Ungolfed:
*
é o operador de concatenação de strings ea*p*"\n"
forma "ApplePie \ n".|>
é o operador de encadeamento de funções (/ piping), portanto, a sequência escolhida é enviada como argumento paraprint
. Osin
não é usado, ele está lá porqueprint
precisa estar em uma matriz para ter um espaço em branco significativo depois dele (usar o#
truque depois trará a contagem máxima de bytes por linha para 6).Se simplesmente é permitido retornar a saída como uma matriz, isso pode ser feito com 4 bytes no máximo por linha:
Julia 0,6 , 4 bytes por linha, total de 152 bytes
Experimente online!
Uma função que pega n e retorna uma matriz que contém a saída esperada. O comprimento máximo da linha aqui é limitado por
n->
- Julia precisa disso em uma única linha para analisá-la corretamente como o início de uma lambda.fonte
Pascal (FPC)
-Sew
, 6 bytes por linha,348320 bytesExperimente online!
Utiliza o FPC para obter 6 bytes por linha; sem ele, o resultado seria muito pior. Essa é a menor largura de linha possível, pois depois
write
deve ser;
ou(
(ou espaço em branco desnecessário); portanto, um comentário especial é inserido para evitar isso. Os recursos do FPC que influenciaram esta resposta são://
- iniciando comentários de uma linha.{$<something>...}
são diretivas do compilador. Se a diretiva não existir, o FPC emitirá um aviso (e{$ ...}
também). Neste programa,{
e$
são separados por uma nova linha que emitirá o aviso quando excluído.-Sew
- O compilador também pára após os avisos para que,{
e$
unidos, parem a compilação.fonte
Japt , 3 bytes por linha
Quase consegui reduzi-lo a dois bytes por linha, mas o retorno do mapa é interrompido se for seguido por uma nova linha.
A implementação do FizzBuzz em si é do segmento canônico do FizzBuzz .
Experimente online!
fonte
LOLCODE ,
188 bytes por linha, total de 303 bytesExperimente online!
-10 bytes por linha usando o caractere de continuação de linha
…
, graças a Ørjan Johansen!fonte
Python 2 , 5 bytes / linha
Experimente online!
fonte
'z\"'
significa a mesma coisa que'z\
⏎"'
; portanto, a regra de nova linha redundante significa que você não tem permissão para iniciar uma linha de continuação dentro da sequência com"
.r'...'
agoraSyntaxError
.FizzBuzz
para usarApplePie
.JavaScript (ECMAScript6), 2 bytes por linha
Explicação longa
A maneira como podemos tornar as linhas mais curtas é transformar o código em uma string e escapar do final da linha, isso impõe um limite de 2 bytes por linha.
Então
alert(1)
se tornaMas agora seu código é uma string, então precisamos executá-la como código. Eu sei pelo menos 4 maneiras que você pode executar seqüência de caracteres como código:
eval(
onclick=""
atributo, mas não consegui tornar a criação do elemento curta.Todas as funções nativas vidas dentro da janela de objeto e em javascript você pode acessar propriedades do objeto usando a notação de ponto para que
eval()
se tornewindow.eval()
, ou você pode acessar as propriedades usando a notação de colcheteswindow['eval']()
. Você pode tirar vantagem disso para quebrar aseval
várias linhas usando o método descrito anteriormente. Mas você ainda precisa digitar o janela , um truque é que, se você não estiver dentro de um quadro, a variável top também será window, então window.eval se tornará top.eval (3 bytes a menos).Portanto, isso tornará o código mínimo de 3 bytes. Para tornar o código 2 bytes, usei o
new Function(/*string*/);
construtor, mas tive que ser criativo para acessá-lo sem precisar digitá-lo.Primeiro, o construtor Function permite chamá-lo como uma função que omite a nova palavra-chave; isso reduz 4 bytes, mas também é importante por outro motivo. Chamar o construtor como uma função ainda retorna uma instância que nos permite ativar
new Function(code)
aFunction(code)
. Outra coisa importante é que o construtor Function tenha umcall
método que permite que você chame qualquer função, mas substitui a referência desta, e o próprio construtor Function é uma função que você pode chamar por si próprio.Function.call(null, code)
.Todas as funções nativas são instâncias do construtor Function e todos os objetos em javascript possuem uma propriedade construtora . Assim, você pode ter acesso ao construtor Function em qualquer função nativa como
alert.constructor
, e usando a chamada método de , podemos executar o construtor como uma função. Agora temos alert.constructor.call (null, code) retorna uma função.combinando as técnicas anteriores, podemos transformá-lo em
alert['constructor']['call'](null, code)
Agora só precisamos encontrar uma função ou método nomeado curto, então escolho o método big () dentro do construtor String. Para acessá-lo diretamente de uma string vazia
"".big
Então eu apenas quebrei tudo em 2 bytes
Curto er explicação (TLDR)
Estou acessando o novo construtor Function (code) para analisar a string em vez de eval (code) . Esse construtor está disponível em todas as funções nativas executando anyFunction. construtor , como
alert.constructor===Function
. Eu estou usando uma função / método dentro do String.prototype.bigString.prototype.big.constructor.call(null, /*string*/)
Mas acessando-o diretamente de um literal de seqüência de caracteres"".big
e o transformou em notação de colchete .""['big']['constructor']['call'](0, CODE)
para poder quebrá-lo usando o\
.fonte
'
e]
pode ser removida e o programa ainda será executado com êxito.Pip , 3 bytes por linha, total de 72 bytes
Experimente online!
O Pip é extremamente flexível em relação ao espaço em branco; portanto, a única estratégia que parece viável é criar uma string, modificá-la de uma maneira que exija que as novas linhas não sejam perturbadas e avaliá-la.
Criamos uma string em que todos os outros caracteres são uma nova linha e pegamos todos os outros caracteres usando
UW
(desenrolar) e unário@
(obter o primeiro elemento):O resultado
@UW
deve ser o nosso código ApplePie, adaptado da solução FizzBuzz aqui . Se alguma nova linha da string for excluída, isso não resultará no código completo, resultando em erro de sintaxe ou saída incorreta.Ainda existem duas novas linhas fora da string. Tornamos isso obrigatório usando o
Y
operador (yank) - que aqui atua como não operacional - junto com a maneira como Pip analisa as letras maiúsculas:Portanto, se essas novas linhas são excluídas, o programa analisa de maneira diferente e não faz o que deveria.
fonte
Java 8, 7 bytes por linha, 171 bytes
Um lambda vazio tomando uma
int
. Suspeito que isso obedeça ao requisito referente às novas linhas, mas não posso prová-lo, e a verificação por força bruta levaria cerca de um mês no meu computador. Assim vai.Experimente Online
Muito chato devido aos comentários da linha. A única coisa interessante aqui é o uso de um valor nulo
System
referência , que parece ser necessária para imprimir com padrão abaixo de 8 bytes por linha. Observe também que aprint
chamada do método é o gargalo.Ungolfed sem comentários:
fonte