Inteiro vai e volta no tempo

17

Entrada:

Um inteiro.

Resultado:

  1. Primeiro converta o número inteiro para o seu numeral romano equivalente.
  2. Em seguida, converta cada letra maiúscula desse numeral romano em seu valor decimal ASCII / UNICODE.
  3. E produza a soma desses.

Exemplo:

1991 -> MCMXCI -> 77+67+77+88+67+73 -> 449
^ input                                ^ output

Algarismos romanos: Aqui está um conversor de algarismos romanos talvez útil.
insira a descrição da imagem aqui

Regras do desafio:

  • As regras do numeral romano padrão são aplicadas, portanto, nenhuma forma alternativa é como IIIIou em VIIIIvez de IVe IX. *
  • As linhas de Macron acima dos algarismos romanos anteriores a 1.000 são ¯(UNICODE nº 175). Portanto, uma linha conta como +175e duas como +350.
  • Você tem permissão para usar qualquer tipo de entrada e saída, desde que represente os números inteiros.
  • Os casos de teste estarão no intervalo de 1 - 2,147,483,647.

* Regras do numeral romano (citação da Wikipedia):

Os números são formados pela combinação de símbolos e pela adição de valores, assim IIcomo dois (dois) e XIIItreze (dez e três). Como cada numeral tem um valor fixo, em vez de representar múltiplos de dez, cem e assim por diante, de acordo com a posição, não há necessidade de zeros de "manutenção de lugar", como em números como 207 ou 1066; esses números são escritos como CCVII(duas centenas, um cinco e dois) e MLXVI(mil, cinquenta, dez, cinco e um).

Os símbolos são colocados da esquerda para a direita em ordem de valor, começando pelo maior. No entanto, em alguns casos específicos, para evitar que quatro caracteres sejam repetidos em sucessão (como IIIIou XXXX), a notação subtrativa é frequentemente usada da seguinte maneira:

  • Icolocado antes Vou Xindica um a menos, então quatro é IV(um a menos de cinco) e nove é IX(um a menos de dez)
  • Xcolocado antes Lou Cindica dez a menos, então quarenta é XL(dez a menos de cinquenta) e noventa é XC(dez a menos de cem)
  • Ccolocado antes Dou Mindica cem menos, então quatrocentos é CD(cem menos que quinhentos) e novecentos é CM(cem menos que mil)
    Por exemplo, MCMIVé mil novecentos e quatro, 1904 ( Mé mil, CMé novecentos e IVé quatro).

Alguns exemplos do uso moderno de algarismos romanos incluem:
1954 as MCMLIV; 1990 as MCMXC; 2014 como MMXIV
SOURCE

Regras gerais:

  • Isso é , então a resposta mais curta em bytes vence.
    Não permita que idiomas com código de golfe o desencorajem a postar respostas com idiomas que não sejam codegolf. Tente encontrar uma resposta o mais curta possível para 'qualquer' linguagem de programação.
  • Aplicam-se regras padrão à sua resposta, para que você possa usar STDIN / STDOUT, funções / método com os parâmetros adequados, programas completos. Sua chamada.
  • Lacunas padrão são proibidas.
  • Se possível, adicione um link com um teste para o seu código.
  • Além disso, adicione uma explicação, se necessário.

Casos de teste:

100          ->   67
1            ->   73
4            ->   159
22           ->   322
5000         ->   261
2016         ->   401
1000000000   ->   427
1991         ->   449
9999         ->   800
1111111111   ->   2344
2147483647   ->   5362
Kevin Cruijssen
fonte
Relacionado
Kevin Cruijssen 01/08/16
11
@martin 9999-> M(X)CMXCIX-> 77+263+67+77+88+67+73+88-> 800e 2147483647-> ((MMCXLV)MMCDLXXX)MMMDCXLVII-> 427+427+417+438+426+436 + 252+252+242+243+251+263+263+263 + 77+77+77+68+67+88+76+86+73+73-> 5362. Então eu corrigi o segundo, mas o 9999estava correto.
Kevin Cruijssen
11
O caso de teste 2222222222não está no intervalo especificado. Também concordo 5362.
Neil
11
O título meio que soa como uma pergunta Stack Overflow C.
User6245072
3
A palavra "quarto" no título é um trocadilho? Caso contrário, deve ser "adiante".
precisa saber é o seguinte

Respostas:

4

Mathematica, 181 173 166 151 bytes

Golfe

(q=Select[ToCharacterCode@#,64<#<99&]&/@StringSplit[RomanNumeral[#],"_"];p=PadLeft;l=Length;Total[p[q,4]+p[{350,350*Mod[l@q,2],175,0}[[-l@q;;]],4],2])&

Ungolfed

(
q = Select[
     ToCharacterCode@#,
     64<#<99&
    ]&/@StringSplit[RomanNumeral@#,"_"];
p=PadLeft;
l=Length;
Total[
   p[q,4]+
   p[{350,350*Mod[l@q,2],175,0}[[-l@q;;]],4]
   ,2]
)&

Mathematica's RomanNumeral implementação fornece o (IX) CMXCIX para 9999 e, portanto, o programa retorna 971 para esse número.

Conforme escrito, um numeral romano do tipo ((...)) (...) ... retorna uma lista aninhada dos códigos ASCII para os numerais romanos de comprimento 4, ((...)) ... retorna uma lista de comprimento 3, (...) ... retorna uma lista de comprimento 2 e ... retorna uma lista de comprimento 1. A linha final converte essas regras no número apropriado de macrons para cada seção do lista, adiciona essas macrons e soma a lista aninhada inteira para retornar a saída.

HiggstonRainbird
fonte
11
Bem-vindo ao PPCG!
precisa saber é o seguinte
@betseg Obrigado! Este foi um primeiro problema divertido.
precisa saber é o seguinte
10

Python 3, 281 278 273 269 ​​bytes

Minha primeira tentativa no codegolf, aqui vamos nós. Tentei fazê-lo sem olhar para a pergunta vinculada, então provavelmente é terrível :)

def f(n):d=len(str(n))-1;l=10**d;return 0if n<1else(n<l*4and[73,88,67,77,263,242,252,438,417,427][d]+f(n-l))or(l<=n//9and[161,155,144,340,505,494,690,855,844][d]+f(n-9*l))or(n<l*5and[159,164,135,338,514,485,688,864,835][d]+f(n-4*l))or[86,76,68][d%3]+(d//3*175)+f(n-5*l)

8 bytes menor, graças a Gábor Fekete

Ungolfed:

def f(n):
d = len(str(n)) - 1 # number of digits minus one
l = 10 ** d         # largest power of 10 that is not larger than parameter
if n == 0:
    return 0
elif n < 4 * l: # starts with X, C, M, ...
    return [
        ord('I'),
        ord('X'),
        ord('C'),
        ord('M'),
        ord('X') + 175, 
        ord('C') + 175, 
        ord('M') + 175, 
        ord('X') + 350, 
        ord('C') + 350, 
        ord('M') + 350
    ][d] + f(n - l)
elif n // 9 * 10 >= 10 * l: # starts with IX, XC, ...
    return [
        ord('I') + ord('X'), 
        ord('X') + ord('C'), 
        ord('C') + ord('M'),
        ord('M') + ord('X') + 175,
        ord('X') + ord('C') + 350,
        ord('C') + ord('M') + 350,
        ord('M') + ord('X') + 525,
        ord('X') + ord('C') + 700,
        ord('C') + ord('M') + 700
    ][d] + f(n - 9*l)
elif n < 5 * l: # starts with IV, XL, CD, ... 
    return [
        ord('I') + ord('V'),
        ord('X') + ord('L'),
        ord('C') + ord('D'),
        ord('M') + ord('V') + 175,
        ord('X') + ord('L') + 350,
        ord('C') + ord('D') + 350,
        ord('M') + ord('V') + 525,
        ord('X') + ord('L') + 700,
        ord('C') + ord('D') + 700
    ][d] + f(n - 4 * l)
else: # starts with V, L, D, ...
    return [
        ord('V'), 
        ord('L'), 
        ord('D'),
        ord('V') + 175, 
        ord('L') + 175, 
        ord('D') + 175,
        ord('V') + 350, 
        ord('L') + 350, 
        ord('D') + 350
    ][d] + f(n - 5 * l)
jDomantas
fonte
Você pode golfe alguns bytes, substituindo return 0 if n==0 elsecomreturn 0if n<1else
Gábor Fekete
A sua versão para golfe tem chamadas fquando o nome da função é g.
Gábor Fekete
Mude n//9*10>=10*lpara n//9>=lpara economizar um pouco mais.
Gábor Fekete
Corrigido o nome da função, mudei para verificar se jogava corretamente e esqueci de alterá-lo novamente.
JDomantas
3

Mathematica, 198 bytes

Tr[Tr@Flatten[ToCharacterCode/@#]+Length@#*Tr@#2&@@#&/@Partition[Join[SplitBy[Select[Characters@#/."\&"->1,MemberQ[Join["A"~CharacterRange~"Z",{1}],#]&],LetterQ]/. 1->175,{{0}}],2]]&@RomanNumeral@#&

Infelizmente, o builtin não ajuda muito aqui, embora eu tenha certeza que isso pode ser jogado muito mais.

Nota: Avalia 9999 -> 971conforme aqui .

Martin
fonte
2

Lote, 373 bytes

@echo off
set/an=%1,t=0,p=1
call:l 73 159 86 161
call:l 88 164 76 155
call:l 67 135 68 144
call:l 77 338 261 340
call:l 263 514 251 505
call:l 242 485 243 494
call:l 252 688 436 690
call:l 438 864 426 855
call:l 417 835 418 844
call:l 427 0 0 0
echo %t%
exit/b
:l
set/ad=n/p%%10,p*=10,c=d+7^>^>4,d-=9*c,t+=%4*c,c=d+3^>^>3,d-=5*c,t+=%3*c+%2*(d^>^>2)+%1*(d^&3)

Funciona através da tradução de cada dígito do número de acordo com uma tabela de consulta para os valores de 1, 4, 5 e 9. Utilizações M(V), M(X), (M(V))e (M(X)). Se preferir (IV), (IX), ((IV))e ((IX)), em seguida, usar call:l 77 509 261 511e call:l 252 859 436 861, respectivamente.

Neil
fonte
1

JavaScript (ES6), 183 bytes

f=(n,a=0)=>n<4e3?[256077,230544,128068,102535,25667,23195,12876,10404,2648,2465,1366,1183,329].map((e,i)=>(d=e>>8,c=n/d|0,n-=c*d,r+=c*(e%256+a*-~(i&1))),r=0)|r:f(n/1e3,a+175)+f(n%1e3)

Nota: não só prefere (IV)a M(V), mas também prefere (VI)a (V)M; na verdade, ele usará M apenas no início do número.

Neil
fonte
1

Python, 263 bytes

def g(m):x=0;r=[73,86,88,76,67,68,77,261,263,251,242,243,252,436,438,426,417,418,427,0,0];return sum([b%5%4*r[i+(i*1)]+((b==9)*(r[i+(i*1)]+r[(i+1)*2]))+((b==4)*(r[i+(i*1)]+r[i+1+(i*1)]))+((b in [5,6,7,8])*r[i+1+(i*1)])for i,b in enumerate(map(int,str(m)[::-1]))])
Elly G
fonte
Bem-vindo ao PPCG, boa primeira resposta!
Cobre
1

R, 115 bytes

Então ... estou postando minha solução porque acho a pergunta bastante interessante. Eu fiz o meu melhor com R 'capacidades s para lidar com números romanos sem pacotes: você só pode introduzir números entre 1e 3899, como o as.roman' s documentação explica.

É por isso que eu enganei um pouco, dando intervalo entre 1a no loop: é o comprimento do 's de saída ( ) . De fato, de acordo com este site , o número romano mais longo é (14 caracteres), o que corresponde a11 14foras.roman(3899)MMMDCCCXCIX
MMDCCCLXXXVIII2888 .

Além disso, você não pode calcular lengtha saída desta função.

a=scan();v=0;for(i in 1:14){v=c(v,as.numeric(charToRaw(substring(as.character(as.roman(a)),1:14,1:14)[i])))};sum(v)

Se alguém encontrar uma solução para lidar com os problemas acima, não hesite em comentar.

Frédéric
fonte
0

Python 3, 315 bytes

def p(n=int(input()),r=range):return sum([f*g for f,g in zip([abs(((n-4)%5)-1)]+[t for T in zip([((n+10**g)//(10**g*5))%2for g in r(10)],[(n%(10**g*5))//(10**g*4)+max((n%(10**g*5)%(10**g*4)+10**(g-1))//(10**g),0)for g in r(1,10)])for t in T],[73,86,88,76,67,68,77,261,263,251,242,243,252,436,438,426,417,418,427])])

Versão não destruída:

def p(n=int(input()),r=range):
    return sum([f*g for f,g in zip(
        [abs(((n-4)%5)-1)]+
        [t for T in zip(
            [((n+10**g)//(10**g*5))%2for g in r(10)],
            [(n%(10**g*5))//(10**g*4)+max((n%(10**g*5)%(10**g*4)+10**(g-1))//(10**g),0)for g in r(1,10)]
        )for t in T],
        [73,86,88,76,67,68,77,261,263,251,242,243,252,436,438,426,417,418,427])])

Explicação: Esta versão usa uma abordagem diferente, conta as ocorrências de números romanos no número.

[abs(((n-4)%5)-1)]é o número de Is no número romano.

[((n+10**g)//(10**g*5))%2for g in r(10)]é o número de V,L,D,(V),(L),(D),((V)),((L)),((D))s no número.

[(n%(10**g*5))//(10**g*4)+max((n%(10**g*5)%(10**g*4)+10**(g-1))//(10**g),0)for g in r(1,10)]é o número de X,C,M,(X),(C),(M),((X)),((C)),((M))s no número.

Em seguida, multiplica as ocorrências pelo valor do caractere e retorna a soma dele.

Gábor Fekete
fonte