O desafio é tornar qualquer código romano válido no idioma escolhido.
Eles não devem aparecer dentro de strings ou algo parecido, mas funcionam como quaisquer outros tokens, literais como números (em árabe ), caracteres ou strings; ou identificadores de variável / método / função etc.
Por exemplo, em Java, o seguinte teria que compilar e executar como se tivesse i
sido inicializado para 42
:
int i = XLII;
A análise real dos números é secundária; portanto, você pode usar uma biblioteca, se quiser, mas este é um concurso de popularidade; portanto, a criatividade é incentivada.
Você não pode usar nenhum idioma que realmente use algarismos romanos, se houver.
Boa sorte.
Process
ast
para analisar a fonte. Insira na parte superior do AST a definição dos números romanos de 1 a 3999. Compile tudo e execute-o. É chato escrever o código para lidar com o processo.Respostas:
C
Existem apenas numerais romanos, desde 4000 e superiores não possuem notação padrão, e o pré-processador é uma ferramenta de descompressão maravilhosa, especialmente se você não tiver problemas com o fato de o código ter um comportamento indefinido.
Isso define todos os algarismos romanos de
I
atéMMMCMXCIX
como constantes de enumeração, mais_
(que podem ser substituídos por qualquer coisa que você quiser) como zero.fonte
scanf
também :) @ klingt.net Não sei ao certo que tipo de exemplo você está procurando. Um bastante simples seriaint main() { return MMMCMXCIX - M - M - M - CM - XC - IX; }
Rubi
Todos os algarismos romanos (maiúsculos) agora serão analisados como seus equivalentes decimais. O único problema é que eles ainda são atribuíveis: você pode fazer
X = 9
, mas não10 = 9
. Eu não acho que há uma maneira de consertar isso.fonte
JavaScript (ES6)
Use
Proxy
para pegar algarismos romanos.Testável no Firefox (mais recente) no JSFiddle .
Não pode ser testado no Chrome (com Traceur), pois a
Proxy
implementação foi interrompida.Uso:
fonte
C & C ++ (resposta atualizada)
Como observado em um comentário, minha solução original teve dois problemas:
Como eu queria que meu código fosse o mais genérico possível para trabalhar em plataformas mais antigas, decidi fazer outra tentativa. É mais longo do que era antes, mas funciona em compiladores e pré-processadores configurados no modo de compatibilidade C89 / C90. Todas as macros recebem um número apropriado de argumentos no código-fonte, embora às vezes essas macros "se expandam" para nada.
O Visual C ++ 2013 (versão 12) emite avisos sobre parâmetros ausentes, mas nem o mcpp (um pré-processador de código aberto que reivindica alta conformidade com o padrão) nem o gcc 4.8.1 (com -std = iso9899: 1990 -pedantic-errors switches) emitem avisos ou erros para essas chamadas de macro com uma lista de argumentos efetivamente vazia.
Depois de revisar o padrão relevante (ANSI / ISO 9899-1990, 6.8.3, Substituição de macro), acho que há ambiguidade suficiente para que isso não deva ser considerado fora do padrão. "O número de argumentos na invocação de uma macro do tipo função deve concordar com o número de parâmetros na definição da macro ...". Parece não impedir uma lista de argumentos vazia, desde que os parênteses necessários (e vírgulas no caso de vários parâmetros) estejam disponíveis para chamar a macro
Quanto ao problema de vírgula à direita, isso é resolvido adicionando um identificador extra à enumeração (no meu caso, MMMM, que parece tão razoável quanto qualquer outra coisa para o identificador seguir 3999, mesmo que não obedeça às regras aceitas do seqüenciamento de números romanos exatamente).
Uma solução um pouco mais limpa envolveria mover a enum e dar suporte a macros para um arquivo de cabeçalho separado, como foi implícito em um comentário em outro lugar, e usar undef dos nomes de macro imediatamente após serem usados, para evitar poluir o espaço para nome. Sem dúvida, nomes de macro melhores devem ser escolhidos também, mas isso é adequado para a tarefa em questão.
Minha solução atualizada, seguida pela minha solução original:
A resposta original (que recebeu as seis primeiras votações anteriores, portanto, se ninguém mais votá-las novamente, não pense que minha solução atualizada recebeu as votações anteriores):
No mesmo espírito de uma resposta anterior, mas feita de uma maneira que deveria ser portátil usando apenas um comportamento definido (embora ambientes diferentes nem sempre concordem em alguns aspectos do pré-processador). Trata alguns parâmetros como opcionais, ignora outros, deve funcionar em pré-processadores que não suportam a
__VA_ARGS__
macro, incluindo C ++, usa macros indiretas para garantir que os parâmetros sejam expandidos antes da colagem do token e, finalmente, é mais curto e acho mais fácil de ler ( embora ainda seja complicado e provavelmente não seja fácil de ler, apenas mais fácil):fonte
__VA_ARGS__
.Lisp comum
A seguir, uma explicação bastante longa de como eu criei uma macro que você pode usar assim:
Quando uma macro é chamada no Common Lisp, ela basicamente atua como uma função, apenas que os argumentos são recebidos antes de serem avaliados. Na verdade, como no código Common Lisp são apenas dados, o que recebemos é uma lista (aninhada) representando uma árvore de sintaxe não analisada com a qual podemos fazer o que quisermos, e isso é feito em tempo de compilação.
Funções auxiliares
O primeiro passo do plano é pegar essa árvore e verificar se há algo parecido com algarismos romanos. Sendo Lisp e tudo, vamos tentar fazê-lo de alguma forma funcional: Precisamos de uma função que faça uma travessia profunda de uma árvore e retorne todos os objetos para os quais uma função fornecida
searchp
retorne verdadeira. Este é par (semi) recursivo da cauda.Depois, algum código para analisar os algarismos romanos, cortesia do Código Rosetta :
A macro real
Pegamos a árvore de sintaxe (
body
), pesquisamos com nosso procedimento de encontrar todos os detalhes e, de alguma forma, disponibilizamos os algarismos romanos que encontramos.Então o que é
1 + 2 + 3 + (4 * (5 + 6)) + 7
?E para ver o que realmente aconteceu quando a macro foi chamada:
fonte
Lua
Simplesmente um __índice substituto para a tabela global. A conversão real usando gsub ficou muito mais bonita do que eu imaginava.
fonte
Postscript
Tentei seguir o C, mas não entendi. Então eu fiz assim:
O Postscript não possui,
enum
mas podemos construir um dicionário com valores inteiros seqüenciais e dobrá-los em uma matriz. Isso reduz o problema de gerar todas as seqüências em sequência, o que é feito concatenando em 4 loops aninhados. Por isso, gera todas as strings e intercala cada string com um valor de contador crescente, resultando em uma longa série de pares <string> <int> na pilha que são agrupados em<<
...>>
para produzir um objeto de dicionário.O programa constrói e instala um dicionário mapeando todos os nomes dos algarismos romanos para o seu valor correspondente. Portanto, mencionar os nomes no texto de origem chama a pesquisa automática de nomes e gera o valor inteiro na pilha.
impressões
fonte
Smalltalk (Smalltalk / X) (87/101 caracteres)
é claro que poderíamos modificar facilmente o tokenizer do analisador (como faz parte da biblioteca de classes e, como tal, aberto a modificações e sempre presente), mas um desafio é afetar apenas as avaliações em um determinado contexto, para que o restante do sistema funciona como de costume.
Versão 1:
defina um número de variáveis no espaço para nome da avaliação. Portanto, isso afetará os DoIts interativos (também conhecidos como evals):
então eu posso fazer (em um doIt, mas não no código compilado):
-> 2019
Nota: os 101 caracteres incluem espaço em branco; na verdade, isso pode ser feito com 87 caracteres.
Observe também que, quando definido no namespace global do Smalltalk, eu veria essas constantes também no código compilado.
Versão 2:
Use um gancho methodWrapper, que permite que qualquer código existente seja quebrado sem recompilar. A seguir, envolve o tokenizador do analisador para procurar um identificador romano a ser verificado e o torna um número inteiro. A parte complicada é detectar dinamicamente se o contexto de chamada é do império romano ou não. Isso é feito usando um sinal de consulta (que é tecnicamente uma exceção possível):
defina a consulta:
Portanto, podemos solicitar a qualquer momento ("consulta InRomanScope") que fique falso por padrão.
Em seguida, envolva o método checkIdentifier do scanner:
Agora, o scanner funciona como de costume, a menos que estejamos no império romano:
-> 2525
podemos até compilar código:
boa tentativa; mas isso falha com um erro de sintaxe (que é exatamente o que queremos). No entanto, no império romano, podemos compilar:
e agora, podemos perguntar a qualquer número inteiro (enviando essa mensagem) de dentro e de fora de Roma:
-> 2525
fonte
Haskell, usando metaprogramação no Template Haskell e algarismos romanos :
Haskell reserva identificadores começando com letras maiúsculas para construtores, então usei letras minúsculas.
fonte
J - 78 car
Isso varia apenas para MMMCMXCIX = 3999, como nas outras soluções.
Quebrando-o (o recall J é geralmente lido da direita para a esquerda, a menos que seja substituído por parênteses):
M`CDM`XLC`IVX
- quatro caixas de cartas. Nós vamos usar matrizes numéricas no índice nessas letras e criar subpalavras de algarismos romanos.841,3#79bc5yuukh
- Estes são os dados numéricos, bem codificados. *(_1,~3#.inv])
- Isso decodificará os dados acima, expandindo no ternário e acrescentando -1.('';&;:(...){' ',[)&.>
- Emparelhar os números à esquerda com as caixas à direita (&.>
), decodificar as matrizes de números e usá-las para indexar as letras. Tratamos 0 como espaço acrescentando um caractere de espaço às listas de letras. Este procedimento cria listas de palavras comoI II III IV V VI VII VIII IX
eM MM MMM
.{
- Pegue o produto cartesiano dessas quatro caixas cheias de palavras. Agora temos uma matriz 4D de todos os algarismos romanos.}.,;L:1
- Execute tudo isso em uma única lista 1D de algarismos romanos e remova a string vazia na frente, pois isso criaria um erro. (L:
é uma visão rara no golfe J! Geralmente, não existem muitos níveis de boxe envolvidos.)}.i.4e3
- Os números inteiros de 0 a 4000, excluindo os pontos finais.=:
. J permite que você tenha uma lista de nomes em caixa no LHS, como uma forma de atribuição múltipla calculada, portanto, isso funciona bem.Agora, o namespace J está cheio de variáveis que representam números romanos.
* Preciso que o número 2933774030998 seja lido mais tarde na base 3. Acontece que posso expressá-lo na base 79 usando dígitos não maiores que 30, o que é bom porque J só consegue entender dígitos de até 35 (0-9 e depois az). Isso economiza 3 caracteres acima do decimal.
fonte
Python
A idéia é simples como as outras respostas. Mas, para ser limpo e não poluir o espaço para nome global, é usado um gerenciador de contexto. Isso também impõe a restrição, que você precisa declarar com antecedência, a extensão do numérico romano que planeja usar.
Nota Apenas para simplificar, e não para reinventar a roda, eu usei o pacote romano python
Implementação
Demo
fonte
Python
Esta é possivelmente a solução mais simples usando o Python:
fonte
globals()[var] = value
queexec()
.D
usando a avaliação da função de tempo de compilação de D
fonte
APL (Dyalog APL) , 77 bytes
Solicita o comprimento máximo do numeral romano e define todas as variáveis.
t←
t recebe'IVXLCDM',
Caracteres romanos seguidos por⊂
um fechado⍬
lista vaziat[
…]
Índice t com…⍉
a transposta (para obter a ordem correta)8⊥⍣¯1
largura adequada base-oito representação de⍳
os primeiros n índices, onde n é¯1+
um a menos que8*⎕
oito para o poder da entrada numérica,/
achatar linhas (cada representação){
...}¨
Aplique a seguinte função anônima em cada representação…(
…)[t⍳⍵]
Correspondendo às posições dos itens do argumento em t , selecione…∊
o alistado1 5∘ר
uma e cinco vezes cada um10*
dez para o poder de⍳4
zero a três0,⍨
acrescentar zero2(…)/
em cada janela deslizante de comprimento e dois, aplique o seguinte trem de funções anônimas…⊣×
os tempos do argumento esquerdo¯1*
negativo para o poder de<
se o argumento da esquerda é menor que o argumento da direita+/
soma⍵'←',
preceda o argumento (o número romano) e uma seta de atribuição⍕
formato (para nivelar e converter o número em texto)⍎
execute isso (faz a atribuição fora da função anônima)Experimente online! (usando o comprimento máximo 5)
fonte
PHP
Existem várias regras para números romanos válidos
Escreva o maior valor antes dos valores mais baixos
Subtrair apenas
[I,X,C]
antes dos próximos 2 valores maioresSubtraia o dobro
[I,X,C]
antes dos próximos 2 valores maioresSubtrair o dobro
[I,X,C]
antes dos valores maioresCombinar 4 + 5
Versão Online
Etapa 1 Crie as regras
é a saída JSON para todos os números romanos válidos
Etapa 2 Faça listas para todas as regras até 3999
Etapa 3 Criar constantes
Combine todas as listas e defina constantes
Saída
No exemplo, mutiply duas versões válidas do número 8
fonte
Rebol
Exemplo
Saída:
Isenção de responsabilidade: Tenho certeza de que existem outras (e provavelmente melhores!) Maneiras de fazer isso no Rebol também.
PS. Minha
roman-to-integer
função é uma transliteração do bom algoritmo Ruby do histocrata para converter a string do numeral romano em um número. Devolvido com agradecimentos! +1fonte
Lua
Isso afeta a meta-tabela da tabela global, fornecendo uma nova função de índice. Quando uma variável global que contém apenas números romanos é solicitada, por exemplo,
XVII
, ela a analisa.Fácil de testar;
Experimente online!
fonte
VBA, 204 bytes
Uma sub-rotina declarada que não recebe nenhuma entrada e, quando executada, cria o
public
ly acessívelEnum
,R
que contém todos os valores numerais romanos. Esses valores podem ser usados diretamente, sem fazer referência ao Enum.Enum mantém valores de 1 a 3999.
Nota: Os terminais
"
s nas linhas 3 e 7 são incluídos apenas para destaque de sintaxe e não contribuem para o número de bytesUngolfed e Explained
fonte