Escreva um programa que conte de 1 a 100 em algarismos romanos e imprima esses números pela saída padrão. Cada um dos números deve ser separado por espaços.
Você não pode usar nenhuma função interna para transformar em algarismos romanos, nem aplicativo ou biblioteca externa para fazer isso.
O resultado desejado é
I II III IV V VI VII VIII IX X XI XII XIII XIV XV XVI XVII XVIII XIX XX XXI XXII XXIII XXIV XXV XXVI XXVII XXVIII XXIX XXX XXXI XXXII XXXIII XXXIV XXXV XXXVI XXXVII XXXVIII XXXIX XL XLI XLII XLIII XLIV XLV XLVI XLVII XLVIII XLIX L LI LII LIII LIV LV LVI LVII LVIII LIX LX LXI LXII LXIII LXIV LXV LXVI LXVII LXVIII LXIX LXX LXXI LXXII LXXIII LXXIV LXXV LXXVI LXXVII LXXVIII LXXIX LXXX LXXXI LXXXII LXXXIII LXXXIV LXXXV LXXXVI LXXXVII LXXXVIII LXXXIX XC XCI XCII XCIII XCIV XCV XCVI XCVII XCVIII XCIX C
Por se tratar de um desafio de código de golfe, o código mais curto vence .
Respostas:
Perl 69 bytes
Funciona por meio de fórmula mágica. A expressão
"32e$&"%72726
transforma cada dígito da seguinte maneira:0⇒32, 1⇒320, 2⇒3200, 3⇒32000, 4⇒29096, 5⇒56, 6⇒560, 7⇒5600, 8⇒56000, 9⇒50918
Depois de aplicar a tradução
y/016/IXV/
, temos o seguinte:0⇒32, 1⇒32 I , 2⇒32 II , 3⇒32 III , 4⇒29 I 9 V , 5⇒5 V , 6⇒5 VI , 7⇒5 VII , 8⇒5 VIII , 9⇒5 I 9 X 8
O restante dos dígitos (
2-57-9
) é removido. Observe que isso pode ser melhorado em um byte usando uma fórmula que traduz em012
vez de016
, simplificando/XVI60-9/
para/XVI0-9/
. Não consegui encontrar um, mas talvez você tenha mais sorte.Depois que um dígito é transformado dessa maneira, o processo se repete para o próximo dígito, acrescentando o resultado e convertendo os
XVI
s anteriores paraCLX
ao mesmo tempo em que ocorre a tradução para o novo dígito.Atualizar
Pesquisa exaustiva não revelou nada mais curto. No entanto, encontrei uma solução alternativa de 69 bytes:
Este usa uma
0-2
substituição paraIXV
, mas possui um módulo com um dígito a mais.Atualização:
6665 bytesEsta versão é notavelmente diferente, então eu provavelmente deveria dizer algumas palavras sobre ela. A fórmula usada é na verdade um byte a mais!
Incapaz de encurtar a fórmula mais do que é, decidi jogar golfe o que tinha. Não demorou muito até eu lembrar do meu velho amigo
$\
. Quando umaprint
declaração é emitida, ela$\
é automaticamente anexada ao final da saída. Consegui me livrar da$a[$_]
construção estranha de uma melhoria de dois bytes:Muito melhor, mas isso
$\=!print$"
ainda parecia um pouco detalhado. Lembrei-me de uma fórmula alternativa de igual comprimento que encontrei que não continha o número3
em nenhuma de suas transformações de dígitos. Portanto, deve ser possível usá-lo$\=2+print
e substituir o resultante3
por um espaço:Também 67 bytes, devido ao espaço em branco necessário entre
print
efor
.Mas, se houvesse uma fórmula que não usasse um
1
em qualquer lugar,$\=2+print
torna-se$\=print
por mais dois bytes valor de poupança. Mesmo se fosse um byte mais longo, ainda seria uma melhoria.Acontece que essa fórmula existe, mas é um byte mais longo que o original, resultando em uma pontuação final de 65 bytes :
Metodologia
A pergunta foi feita sobre como alguém poderia encontrar essa fórmula. Em geral, encontrar uma fórmula mágica para generalizar qualquer conjunto de dados é uma questão de probabilidade. Ou seja, você deseja escolher um formulário com a maior probabilidade possível de produzir algo semelhante ao resultado desejado.
Examinando os primeiros algarismos romanos:
há alguma regularidade a ser vista. Especificamente, de 0 a 3 e, novamente, de 5 a 8 , cada termo sucessivo aumenta de comprimento em um numeral. Se quisermos criar um mapeamento de dígitos para numerais, gostaríamos de ter uma expressão que também aumente em um dígito para cada termo sucessivo. Uma escolha lógica é k • 10 d, em que d é o dígito correspondente ek é qualquer constante inteira.
Isso funciona para 0-3 , mas 4 precisa quebrar o padrão. O que podemos fazer aqui é aderir a um módulo:
k • 10 d % m , onde m está em algum lugar entre k • 10 3 e k • 10 4 . Isso deixará o intervalo de 0 a 3 intocado e modificará 4 para que não contenha quatro
I
s. Se restringirmos adicionalmente nosso algoritmo de pesquisa, de modo que o resíduo modular de 5 , vamos chamá-lo de j , seja menor que m / 1000 , isso garantirá que também tenhamos regularidade de 5 a 8 também. O resultado é algo como isto:Como você pode ver, se substituirmos
0
porI
, 0-3 e 5-8 têm a garantia de serem mapeados corretamente! Os valores para 4 e 9 precisam ser forçados brutalmente. Especificamente, 4 precisa conter um0
e umj
(nessa ordem) e 9 precisa conter um0
, seguido por outro dígito que não apareça em nenhum outro lugar. Certamente, existem várias outras fórmulas que, por alguma coincidência, podem produzir o resultado desejado. Alguns deles podem até ser mais curtos. Mas não creio que exista alguém com tanta probabilidade de sucesso como este.Também experimentei várias substituições
I
e / ouV
com algum sucesso. Mas, infelizmente, nada menor do que o que eu já tinha. Aqui está uma lista das soluções mais curtas que encontrei (o número de soluções de 1 a 2 bytes mais pesadas são muitas para listar):fonte
HTML + JavaScript + CSS (137)
HTML (9)
JavaScript (101)
CSS (27)
Saída
...
Demonstração no JSBin
fonte
document.write('<ol>'+"<li style='list-style:upper-roman'/>".repeat(100)+'</ol>')
(ES6)document.write("<li style='list-style:upper-roman'/>".repeat(100))
Python 116
melhor código de golfe da resposta do scleaver:
fonte
Python, 139
fonte
C,
177160147 caracteresExistem soluções mais curtas, mas nenhuma em C, então aqui está minha tentativa.
Nova solução, completamente diferente da anterior:
Solução anterior (160 caracteres):
Lógica:
1.
f
imprime um número de 1 a 10.c
são os dígitos usados, que podem serIVX
ouXLC
. Chamado uma vez para as dezenas uma vez para os.2. Se
n%5==0
- imprima nada ou oc[n/5]
que éI
ouV
(ouL
ouC
).3. Se
n%4==4
-4
ou9
- imprimirI
(ouX
), porn+1
.4. Se
n>4
- imprima5
(V
ou sejaL
) entãon-5
.5. Se
n<4
- imprimaI
entãon-1
(ien
horasI
).fonte
f(c,n){printf("%.*s",n%5>3?2:n%5+n/5,"XLXXXCIVIIIX "+c+(n%5>3?n%4*4:2-n/5));}main(i){for(;i<100;f(12,4))f(0,i/10),f(6,i++%10);puts("C");}
JavaScript, 123
Inspirado por uma versão mais longa, me deparei com um grupo de notícias polonês (pelo menos, o Chrome pensava que era polonês).
fonte
Q (
8180)2º corte:
1º corte:
fonte
Python, 168
Explicação
Usando esses valores, pegue o maior valor que não seja maior que n e subtraia-o de n. Repita até n ser 0.
fonte
r=lambda n,l,v:n and(n<v[0]and r(n,l[1:],v[1:])or l[0]+r(n-v[0],l,v))or""
salva dois caracteres. Caso contrário, muito bom.Rubi 1.9,
140132Isso literalmente conta de 1 a 100 em algarismos romanos. Inicia com uma sequência em branco e, em seguida, passa pelo anexo "I" e aplica repetidamente uma série de regras de substituição, adicionando efetivamente 1.
Edit: Adicionado o número da versão, já que
?I
funciona apenas em 1.9, e usou as alterações de @ Howard para aparar alguns caracteres.fonte
r while
->0while
,r.sub!(*q)
->r.sub! *q
. Você também pode arrastar a impressão para dentro do loop e usar em100.times{...}
vez da instrução map.(%w[IIII VIV XXXX LXL]<</(.)((?!\1)[^I])\1/).zip(%w(IV IX XL XC)<<'\2')
salva 7 caracteres.Ruby 112 chars
Basicamente, usando o
to_roman
método explicado aqui , mas usando uma matriz compactada para resumir.fonte
Mathematica
159 150142Solução integrada :
IntegerString
38 caracteresfonte
perl 205
Golfe:
fonte
MUMPS 184
O mesmo algoritmo que @cardboard_box, de quem eu tirei a explicação literalmente -
Explicação
Usando esses valores, pegue o maior valor que não seja maior que n e subtraia-o de n. Repita até n ser 0.
fonte
R , 85 bytes
Experimente online!
Usa a
utils
variável de pacote aleatório.romans
para obter os valores dos números romanos, mas faz a conversão por si só; a abordagem integrada seria 20 bytes:cat(as.roman(1:100))
fonte
cat(paste(as.roman(1:100)))
ou simplesmenteas.roman(1:100)
. Esquisito.cat
indicam que ele realiza menos conversões do queprint
e só funciona ematomic
vetores - o que explica isso!APL 128
Eu tentei uma solução de indexação no APL:
Pode ser 4 bytes mais curto na origem do índice 0 em vez de 1, mas o espaço real é a geração da matriz de índices via:
Até agora não consegui gerar os índices rapidamente!
fonte
LaTeX (138)
fonte
Python, 125
fonte
PHP,
3837 bytes<ol type=I><?=str_repeat("<li>",100);
-1 byte graças a @manatwork
Mesma ideia da resposta de Patrick , mas em uma linguagem mais compacta. Beats Mathematica !
Experimente Online!
fonte
;
, então não há necessidade?>
.VBA (Excel), 245 bytes
Função criada para Repetição e Substituição - 91 bytes
Function s(a,b):s=String(a,b):End Function Function b(x,y,z):b=Replace(x,y,z):End Function
usando janela imediata ( 154 bytes )
p="I":for x=1to 100:?b(b(b(b(b(b(b(b(s(x,p),s(100,p),"C"),s(90,p),"XC"),s(50,p),"L"),s(40,p),"XL"),s(10,p),"X"),s(9,p),"IX"),s(5,p),"V"),s(4,p),"IV"):next
fonte
Java (OpenJDK 8) , 152 bytes
Experimente online!
Explicação:
fonte
TeX, 354 bytes
Alguma explicação: O TeX fornece um comando
\romannumeral
interno para converter números em números romanos. Como a pergunta não permite o uso de funções internas, o código acima é uma versão em golf do mesmo algoritmo que o compilador TeX original de Knuth usa para\romannumeral
(consulte TeX: The Program , § 69,print_roman_int
) reimplementado no TeX.Como ele quer deixar a alegria de descobrir como esse código funciona para o leitor, Knuth se recusa a dar uma explicação para essa parte do código. Então, seguirei o exemplo e darei uma versão não-gasta e levemente modificada, mais próxima do original do que o código acima:
fonte