Целое число идет вперед и назад во времени

17

Входные данные:

Целое число

Выход:

  1. Сначала преобразуйте целое число в его эквивалент римской цифрой.
  2. Затем преобразуйте каждую заглавную букву этого римского числа в десятичное значение ASCII / UNICODE.
  3. И выведите сумму тех.

Пример:

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

Римские цифры: Вот, возможно, полезный конвертер римских цифр.
введите описание изображения здесь

Правила соревнований:

  • Применяются стандартные правила римской цифры, поэтому нет альтернативных форм, таких как IIIIили VIIIIвместо IVи IX. *
  • Линии Макрона над римскими цифрами после 1000 ¯(Юникод № 175). Таким образом, одна строка считается как +175и две как +350.
  • Вам разрешено использовать любой тип ввода и вывода, если он представляет целые числа.
  • Тестовые случаи будут в диапазоне 1 - 2,147,483,647.

* Правила римских цифр (цитата из Википедии):

Числа формируются путем объединения символов и добавления значений, IIравно как два (два) и XIIIтринадцать (десять и три). Поскольку каждая цифра имеет фиксированное значение, а не представляет собой кратные десять, сто и т. Д., В соответствии с положением, нет нужды в «хранении мест» нулей, как в числах, таких как 207 или 1066; эти числа записываются как CCVII(две сотни, пять и два) и MLXVI(тысяча, пятьдесят, десять, пять и один).

Символы располагаются слева направо в порядке значения, начиная с наибольшего. Однако в некоторых конкретных случаях, чтобы избежать повторения четырех символов подряд (например, IIIIили XXXX), вычитающая запись часто используется следующим образом:

  • Iставится перед Vили Xуказывает на один меньше, поэтому четыре - это IV(один меньше пяти), а девять - IX(один меньше десяти)
  • Xперед Lили Cуказывает на десять меньше, поэтому сорок XL(десять меньше пятидесяти) и девяносто XC(десять меньше ста)
  • Cпомещается перед Dили Mуказывает на сотню меньше, поэтому четыреста - это CD(сто меньше пятисот), а девятьсот - это CM(сто меньше тысячи).
    Например, MCMIVэто одна тысяча девятьсот четыре, 1904 ( Mэто тысяча, CMэто девятьсот IVчетыре

Некоторые примеры современного использования римских цифр включают в себя:
1954 как MCMLIV; 1990 как MCMXC; 2014 как MMXIV
ИСТОЧНИК

Основные правила:

  • Это , поэтому выигрывает самый короткий ответ в байтах.
    Не позволяйте языкам кода-гольфа отговаривать вас от публикации ответов на языках, не относящихся к кодексу. Попробуйте придумать как можно более короткий ответ для «любого» языка программирования.
  • К вашему ответу применяются стандартные правила , поэтому вы можете использовать STDIN / STDOUT, функции / метод с правильными параметрами, полные программы. Ваш звонок.
  • По умолчанию лазейки запрещены.
  • Если возможно, добавьте ссылку с тестом для вашего кода.
  • Также, пожалуйста, добавьте объяснение, если это необходимо.

Тестовые случаи:

100          ->   67
1            ->   73
4            ->   159
22           ->   322
5000         ->   261
2016         ->   401
1000000000   ->   427
1991         ->   449
9999         ->   800
1111111111   ->   2344
2147483647   ->   5362
Кевин Круйссен
источник
Связанный
Кевин Круйссен
1
@martin 9999-> M(X)CMXCIX-> 77+263+67+77+88+67+73+88-> 800и 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. Я исправил второе, но это 9999было правильно.
Кевин Круйссен
1
Контрольный пример 2222222222не находится в заданном диапазоне. Также я согласен с 5362.
Нейл
1
Название звучит как вопрос о переполнении стека C.
user6245072
3
Является ли слово «четвертый» в названии каламбуром? Если нет, то должно быть «вперед».
Монти Хардер

Ответы:

4

Mathematica, 181 173 166 151 байт

Golfed

(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]
)&

RomanNumeralРеализация Mathematica дает (IX) CMXCIX для 9999, и поэтому программа возвращает 971 для этого числа.

Как написано, римская цифра типа ((...)) (...) ... возвращает вложенный список кодов ASCII для римских цифр длины 4, ((...)) ... возвращает список длины 3, (...) ... возвращает список длины 2 и ... возвращает список длины 1. Последняя строка преобразует эти правила в соответствующее число макронов для каждого раздела list, добавляет эти макроны, а затем суммирует весь вложенный список, чтобы вернуть выходные данные.

HiggstonRainbird
источник
1
Добро пожаловать в PPCG!
Betseg
@betseg Спасибо! Это была забавная первая проблема.
HiggstonRainbird
10

Python 3, 281 278 273 269 ​​байт

Моя первая попытка на Codegolf, здесь мы идем. Пытался сделать это, не глядя на связанный вопрос, так что, наверное, ужасно :)

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 байтов меньше благодаря Габору Фекете

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
источник
Вы можете сыграть в гольф несколько байтов, заменив return 0 if n==0 elseнаreturn 0if n<1else
Габор Фекете
Ваша версия для игры fв гольф имеет вызовы, когда имя функции g.
Габор Фекете
Перейдите n//9*10>=10*lна, n//9>=lчтобы сохранить еще немного.
Габор Фекете
Исправлено имя функции, я изменил его, чтобы проверить, правильно ли я играл в гольф, и забыл изменить его обратно.
jDomantas
3

Mathematica, 198 байт

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@#&

К сожалению, встроенные функции здесь не сильно помогают, хотя я уверен, что это можно сделать гораздо лучше.

Примечание: оценивает 9999 -> 971согласно здесь .

Мартин
источник
2

Пакетный, 373 байта

@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)

Работает путем перевода каждой цифры числа в соответствии с таблицей перекодировки для значений 1, 4, 5 и 9. использованию M(V), M(X), (M(V))и (M(X)). Если вы предпочитаете (IV), (IX), ((IV))а ((IX))затем использовать call:l 77 509 261 511и call:l 252 859 436 861соответственно.

Нил
источник
1

JavaScript (ES6), 183 байта

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)

Примечание: не только предпочитает , (IV)чтобы M(V), но и предпочитает , (VI)чтобы (V)M; на самом деле он будет использовать только М в самом начале числа.

Нил
источник
1

Python, 263 байта

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]))])
Элли Джи
источник
Добро пожаловать в PPCG, хороший первый ответ!
Медь
1

R, 115 байт

Итак ... Я публикую свое решение, потому что нахожу вопрос довольно интересным. Я сделал все возможное с R «s потенциала для борьбы с римскими цифрами без пакетов: Вы можете только ввести числа между 1и 3899, так как as.roman» s документации объясняет.

Вот почему я обманул немного, давая диапазон между 1к в петле: это длина от выхода «s ( ) . На самом деле, согласно этому сайту , самое длинное римское число (14 символов), что соответствует11 14foras.roman(3899)MMMDCCCXCIX
MMDCCCLXXXVIII2888 .

Кроме того, вы не можете вычислить lengthвыход этой функции.

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)

Если кто-то видит решение для решения вышеуказанных проблем, пожалуйста, не стесняйтесь комментировать.

Фредерик
источник
0

Python 3, 315 байт

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])])

Безголовая версия:

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])])

Объяснение: этой версии используется другой подход, он подсчитывает вхождения римских цифр в число.

[abs(((n-4)%5)-1)]число Is в римской цифре.

[((n+10**g)//(10**g*5))%2for g in r(10)] это число V,L,D,(V),(L),(D),((V)),((L)),((D)) s в числе.

[(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)] это число X,C,M,(X),(C),(M),((X)),((C)),((M)) s в числе.

Затем он умножает вхождения на значение символа и возвращает его сумму.

Габор Фекете
источник