Перетворити на римське число!


13

Ваше завдання - перетворити задане додатне ціле число з арабської цифри в римську цифру.

Все стає складним, коли ти рахуєш до 4000.

Римляни зробили це, додавши рядок над символом, щоб помножити цей символ на 1 000. Однак натяг не точно відображається в ASCII. Також є подвійні накреслення для множення символу на 1 000 000, а потім потрійне накреслення для множення символу на 1 000 000 000тощо.

Тому я вирішив використовувати дужки для заміни рядків.

Символи можуть бути окремо розміщені в дужках. Наприклад, обидва (VI)і (V)(I)є дійсними уявленнями про 6 000. (V)Mтакож є дійсним представленням 6000.

(I)є дійсним способом представлення 1 000.

Тестові шафи

Input: 1
Output: I
Input: 2
Output: II
Input: 3
Output: III
Input: 4
Output: IV
Input: 15
Output: XV
Input: 40
Output: XL
Input: 60
Output: LX
Input: 67
Output: LXVII
Input: 400
Output: CD
Input: 666
Output: DCLXVI
Input: 3000
Output: MMM
Input: 3999
Output: MMMCMXCIX
Input: 4000
Output: M(V)
Input: 4999
Output: M(V)CMXCIX
Input: 6000
Output: (VI)
Input: 6000000
Output: ((VI))
Input: 6006000
Output: ((VI)VI)
Input: 6666666666
Output: (((VI)DCLXVI)DCLXVI)DCLXVI

Оцінка балів

Це . Найкоротший код виграти в байтах.


1
Виправдання того, чому це не дублікат, захаращує специфікацію. Було б краще без нього ІМО.
Мего

Де я б додав обґрунтування?
Leaky Nun

1
Залиште це. Якщо хтось ставить під сумнів, чи це дублікат, чи слід обговорити його в коментарях чи в чаті.
Мего

@Mego Готово. :-)
Лина монашка

Чи (IV)прийнятне представлення 4000?
Ніл

Відповіді:


9

Математика, 67 байт

Fold["("<>#<>")"<>#2&,RomanNumeral[#~IntegerDigits~1000]/."N"->""]&

Уникайте будь-яких проблем з Mперетворенням вхідного сигналу в базовий 1000 та перетворення кожної цифри окремо за допомогою RomanNumeral. Потім складаємо їх, вставляючи (...)зліва.

На жаль, Mathematica представляє нулі, Nтому їх потрібно позбутися.


1
чорт математика зі своїми вбудованими для всього> :(
OldBunny2800

1
@ OldBunny2800 Я був би здивований, якби це все одно не побило жодної з мов для гри в гольф.
Мартін Ендер

@ OldBunny2800 І це коштує реальних грошей, щоб отримати його. Це погано.
Ерік Аутгольфер

@ MartinBüttner Я думав, що просто це RomanNumeralможна зробити?
Лина монашка

1
@KennyLau Він виводить MMMMдля 4000, він тільки починає працювати на специфікації 5000(і тоді ви отримуєте ту ж проблему для 4000000і т.д.). Вже тоді він використовує переклади замість дужок. Якщо ви добре з цим, вам слід сказати про це в специфікації виклику.
Мартін Ендер

7

JavaScript (ES6), 136 байт

f=n=>n<4e3?"M1000CM900D500CD400C100XC90L50XL40X10IX9V5IV4I1".replace(/(\D+)(\d+)/g,(_,r,d)=>r.repeat(n/d,n%=d)):`(${f(n/1e3)})`+f(n%1e3)

Для чисел під 4000 повторює кожну римську "букву" якомога більше разів, використовуючи список римських "букв" та їх десяткові значення. В іншому випадку рекурсивно формується відповідь з підрозділу та модуля з 1000. На щастя, repeatскорочується, тому мені не доведеться цього робити самому.


3

Загальна Лісп, 108

(defun p(n)(if(> n 0)(if(< n 4000)(format()"~@R"n)(format()"(~A)~@[~A~]"(p(floor n 1000))(p(mod n 1000))))))

Безумовно

(defun p(n)
  (if (> n 0)
      (if (< n 4000)

          ;; Built-in Roman formatter (between 1 and 3999)
          (format () "~@R" n)

          ;; Divide N by 1000, as 1000*Q + R.
          ;; First print (p Q) in parentheses (recursively)
          ;; Then, if it is not NIL, the remainder R.
          (format () "(~A)~@[~A~]"
                  (p (floor n 1000))
                  (p (mod n 1000))))))

Тести

Два тести дають різні результати, ніж ті, які є у запитанні:

(loop for (in out) in '((1 "I")
                        (2 "II")
                        (3 "III")
                        (4 "IV")
                        (15 "XV")
                        (40 "XL")
                        (60 "LX")
                        (67 "LXVII")
                        (400 "CD")
                        (666 "DCLXVI")
                        (3000 "MMM")
                        (3999 "MMMCMXCIX")
                        (4000 "M(V)")
                        (4999 "M(V)CMXCIX")
                        (6000 "(VI)")
                        (6000000 "((VI))")
                        (6006000 "((VI)VI)")
                        (6666666666 "(((VI)DCLXVI)DCLXVI)DCLXVI"))
   for computed = (p in)
   unless (string= out computed)
   collect (list in out computed))

=> ((4000 "M(V)" "(IV)")
    (4999 "M(V)CMXCIX" "(IV)CMXCIX"))

2

R, 134

m=1000;x=scan();while(x[1]>=m)x=c(floor(x[1]/m),x[1]%%m,x[-1]);cat(rep("(",length(x)),sep="");cat(as.character(as.roman(x)),sep=")")

Це майже не найкращий варіант, але я думаю, що ідея повинна бути схожою на цю.


1

Пітон, 188 194

-6 байт, щоб позбутися деякого пробілу

Цей виклик повернув мене, коли я вперше навчився програмувати ...

def f(x,s=zip("M CM D CD C XC L XL X IX V IV I".split(),[1e3,900,500,400,100,90,50,40,10,9,5,4,1])):
 r=""if x<4e3else"("+f(x/1e3)+")";x%=1e3
 for a,b in s:
    while x>=b:r+=a;x-=b
 return r

Це може бути не найкоротшим рішенням, але мені було весело гольфувати цю проблему.

Спробуй!


1

Рубі, 137 134 130 байт

Рекурсивна функція, яка повертає рядок. Я намагаюсь побільшити цифри кодування трохи більше, якщо можливо, але не знаю як.

Ну, це практично прямий порт відповіді @ Neil на ES6 зараз.

f=->x{(x<t=1e3)?"CM900D500CD400C100XC90L50XL40X10IX9V5IV4I1".gsub(/(\D+)(\d+)/){v=$2.to_i;s=x/v;x%=v;$1*s}:"(#{f[x/t]})#{f[x%t]}"}

1

Рубі, 185 161 144 байт

r=->i{i>(t=1e3)? "(#{r[i/t]})"+r[i%t]:(s=?I*i;"IVXXLCCDM".scan(/(.)(.)(.)/){|x,y,z|{x*5=>y,x*4=>x+y,y*2=>z,y+x+y=>x+z}.map{|x,y|s.gsub!x,y}};s)}

Через рік після початкової публікації я думаю, що я дізнався щось про гольф.

Дякуємо Value Ink за ваші цінні коментарі.


gsubможе взяти рядок як перший аргумент, усунувши необхідність заміни у схемі регулярних виразів, оскільки s.gsub! x,yце робиться автоматично. Крім цього, ви, ймовірно, можете просто відмовитись від призначення aмасиву, оскільки використовуєте його лише один раз, і вводите його безпосередньо у each_sliceвиклик.
Значення чорнила

"IVXXLCCDM".scan(/(.)(.)(.)/){|x,b,c|...також працює
Value Ink

Також r[x]функціонально еквівалентний r.(x)будь-коли, коли задіяні стійкі лямбди
Value Ink

@ValueInk дякую Цей r[x]трюк стане корисним для всього мого рекурсивного гольфу в рубіні!
MegaTom

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