Перетворіть зашифровані римські цифри в арабські десятичні знаки


16

Напишіть алгоритм для інтерпретації послідовності літер як римської цифри. (див. правила римських цифр нижче)

Кожна окрема літера має відповідне арабське десяткове значення, не максимум. Але заздалегідь у вас немає ключа, тому {A=10, I=1, X=5, ... Z=1000000}це визначається вашою інтерпретацією.

Виклик

  1. Прочитайте вхід через STDINабо еквівалент і запишіть вихід через STDOUTабо еквівалент
  2. Дійсні введення - це комбінації великих і малих літер, тобто відповідності \[a-zA-Z]+\
  3. Введення має бути підтверджено, щоб побачити, чи можна послідовність літер трактувати як дійсну римську цифру
  4. Якщо вхід проходить перевірку, дійсний вихід повинен бути найменшою арабською десятковою інтерпретацією, а ключ, що використовується, тобто Aaінтерпретується як 4 {a=5, A=1} ні 6 {A=5, a=1} або 9 {a=10, a=1}

Римські чисельні правила

  1. Лише букви, що представляють потужність десять, можуть повторюватися, максимум три рази поспіль і всього чотири рази, наприклад II III XXXIX

  2. Якщо одна чи кілька літер розміщені після іншої літери більшої цінності, додайте цю суму

    AAaa   => 22 {A=10, a=1}          (20 + 2 = 22)  
    bbAAaa => 222 {b=100, A=10, a=1}  (200 + 20 + 2 = 222)   
    
  3. Якщо лист ставиться перед іншою літерою більшої вартості, відніміть цю суму

    Aa    => 4 {a=5, A=1}                 (5 – 1 = 4)  
    AaA   => 19 {A=10, a=1}               (10 + 10 – 1 = 19)  
    BbBaA => 194 {B=100, b=10, A=5, a=1}  (100 + 100 - 10 + 5 - 1 = 194)  
    

    Для віднімання сум з римських цифр застосовується кілька правил:

    • Віднімайте лише сили десять, тобто 1, 10, 100... ні 5, 50, 500...
    • Отже, жодне подвійне віднімання 18не записується як XVIII ні IIXX (10 + 10 - 1 - 1)
    • Не віднімайте число від одного, яке більш ніж у десять разів більше.
      Ви можете відняти 1з 5 або 10 , але НЕ з50, 100, 500...

Приклад

Input:

Aa  
BAa  
CCCXLVII   
MMMCDVII  
ABADDF  
XVVX  
FAASGSH  
DXCCDA  
AaBbcDEf   

Output:

4 {a=5, A=1}  
14 {B=10, a=5, A=1}  
347 {C=100, L=50, X=10, V=5, I=1}  
347 {M=100, D=50, C=10, V=5, I=1}  
1921 {A=1000, B=100, D=10, F=1}  
'XVVX' failed Roman numeral test  
7191 {F=5000, A=1000, S=100, G=10, H=1}  
'DXCCDA' failed Roman numeral test
4444 {a=5000, A=1000, b=500, B=100, D=50, c=10, f=5, E=1}  

3
@IamOgbz це перетворилося на чудове запитання, але попутно викликало багато питань у коментарях. Тепер, коли у вас достатньо репутації, я рекомендую пісочницю . Я вважаю це дуже корисним для отримання питань безпосередньо перед публікацією.
трихоплакс

Чи не буде CCCLXVII трактуватися як CCCXLVII, даючи 347?
Skyler

@Skyler Ви абсолютно праві, оновите зараз! Спасибі.
iamogbz

Я не бачу жодних обмежень щодо того, які значення можуть мати окремі букви (і справді ви згадуєте 20, що не є значенням стандартної римської цифри). Ви хочете сказати, що будь-яке додатне ціле число може бути представлене римською цифрою? У цьому випадку Aaмає значення 1 (A = 1, a = 2).
msh210

@ msh210, оскільки букви можна інтерпретувати лише як римські цифри, звідси випливає, що значення окремих літер можуть бути потужністю 10 або 5 разів потужністю 10. 20 згадувалося лише стосовно поєднання двох римських цифр (і підкреслюючи, що IXX = 19 не є дійсним відніманням). Сподіваюся, що це очистить це за вас.
iamogbz

Відповіді:


1

Python 2, 415 444 440 419 416 байт

Зрештою, не так багато римських цифр. Цей скрипт створює їх усіх і перевіряє всі перестановки вхідних даних, а потім повертає найменшу відповідність.

a=raw_input()
g=range
b=list(set(a))+[' ']*9
from itertools import*
c=[]
s={}
u=1000
for i in g(10*u):
 t,f=(10*u,9*u,5*u,4*u,u,900,500,400,100,90,50,40,10,9,5,4,1),i;r=""
 for j in g(17):k=i/t[j];r+=('W MW Q MQ M CM D CD C XC L XL X IX V IV I').split()[j]*k;i-=t[j]*k
 s[r]=f
for i in permutations(b[:9]):
 r=''
 for j in a:r+='IVXLCMQWE'[i.index(j)]
 if r in s:c+=[s[r]]
print c and min(c)or'%s failed Roman numeral test'%a

Це гарна відповідь на виклик, як зараз. Але в розмові з коментарями, яка була викреслена рано, було натякано, що ця (не реальна) система продовжується після M = 1000, маючи символи для 5k, 10k тощо. Подивіться перший приклад зверху: {A = 10, I = 1, X = 5, ... Z = 1000000} вирішується вашою інтерпретацією
edc65

.., і останній приклад, a = 5000 ...
edc65

Я оновив його для обробки всіх поданих тестових випадків. Я сумніваюсь, що цей підхід можна продовжити на 10 000, оскільки це займе O (n!) Час для кількості римських цифр.
Skyler

@Skyler тестові випадки не є вичерпними. Програма повинна обробляти всі можливі перестановки дійсних входів, які можна інтерпретувати відповідно до правил римської цифри, при цьому перевага надається меншим числам у неоднозначних випадках. Також ваш код не міг обробити останнє посилання
iamogbz

Чи не, import itertools as iа потім i.permutationsкоротше?
кіт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.