Эти жадные римляне!


30

Если задано строго положительное целое число, верните самую короткую римскую цифру, используя только аддитивное правило. Вывод должен состоять из нуля или более каждого из символов MDCLXVIв этом порядке. Следовательно, число 14должно давать, XIIIIа не XIV.

Числовые значения символов: M= 1000, D= 500, C= 100, L= 50, X= 10, V= 5, I= 1.

Примеры

3III

4 → IIII

9VIIII

42XXXXII

796DCCLXXXXVI

2017MMXVII

16807MMMMMMMMMMMMMMMMDCCCVII


1
Вы доброжелательный спрашивающий 4 -> IIII, 9 -> VIIIIа не IX?
Волшебная урна осьминога


@MagicOctopusUrn VIIIIявляется единственным разрешенным выходом для 9.
Adám

@ Adám только что указал, что вы можете добавить это в качестве примера, потому что правила для 4 и 9 одинаковы.
Волшебная Урна Осьминога

Ответы:


12

Простой английский , 1059 1025 678 641 451 399 байт

Сохранено 34 байта путем удаления сообщения об ошибке. Тогда сэкономил 384 байта, играя в гольф. Затем сохранили 190 байтов, объединив операцию деления с операцией добавления («z») в новую операцию («p»). Затем сэкономил 52 байта, играя в гольф.

A s is a string.
To p a r remainder a s a x string a n number:
If the x is "", exit.
Divide the r by the n giving a q quotient and the r.
Fill a t s with the x's first's target given the q.
Append the t to the s.
To convert a r number to a s:
p the r the s "M" 1000.
p the r the s "D" 500.
p the r the s "C" 100.
p the r the s "L" 50.
p the r the s "X" 10.
p the r the s "V" 5.
p the r the s "I" 1.

Вот не окончательная версия окончательного кода, а также ошибка для отрицательного числа:

A roman numeral is a string.

To process a remainder given a roman numeral and a letter string is a number:
  If the letter is "", exit.
  Divide the remainder by the number giving a quotient and the remainder.
  Fill a temp string with the letter's first's target given the quotient.
  Append the temp string to the roman numeral.

To convert a number to a roman numeral:
  If the number is negative, exit.
  Put the number in a remainder.
  Process the remainder given the roman numeral and "M" is 1000.
  Process the remainder given the roman numeral and "D" is  500.
  Process the remainder given the roman numeral and "C" is  100.
  Process the remainder given the roman numeral and "L" is   50.
  Process the remainder given the roman numeral and "X" is   10.
  Process the remainder given the roman numeral and "V" is    5.
  Process the remainder given the roman numeral and "I" is    1.

10
Подождите, это язык программирования?
Адам

3
@ Адам - ​​Да. Простой английский компилирует, и запускает, и все. Исходный код и IDE доступны на github.com/Folds/english
Jasper

1
Хотя играйте в гольф - в конце концов, это кодовый гольф, а не демонстрация языка.
Sanchises

2
Так что это язык, который вы используете, если вы не хотите, чтобы ваша работа была отдана на аутсорсинг?
CorsiKa

@corsiKa - LOL! Только если достаточное количество из нас начнет использовать его (и добавлять в его библиотеки), что он достигает критической массы.
Джаспер

5

APL (Dyalog) , 25 22 байта

'MDCLXVI'/⍨(0,62 5)∘⊤

Попробуйте онлайн!


Хорошее, и в основном решение, которое я имел в виду. Тем не менее, вы можете использовать копировщик ( /) вместо Reshape ( ) , так что вы можете вырезать каждый и в сцеплять обжатие ( ¨а ,/).
Адам

Кроме того, вы можете конвертировать в tradfn body и использовать input ( ) и использовать commute ( ) для удаления паренов и compose ( ).
Адам

Спасибо, но что вы подразумеваете под своим вторым комментарием? Я не могу придумать, как это сделать без увеличения числа байтов
TwiNight,


1
Это будет отрывок, если вы не посчитаете {}или не ∇f∇
включите

5

Retina , 57 42 байта

Преобразует в одинарный, затем жадно заменяет сгустки Is с более высокими значениями в порядке.

.*
$*I
I{5}
V
VV
X
X{5}
L
LL
C
C{5}
D
DD
M

Попробуйте онлайн

Сэкономили 15 байтов благодаря Мартину


Это очень умно.
Адам


Не могли бы вы принять ввод в унарном виде в Iкачестве единицы?
Адам

2
@ Adám Учитывая, что Retina теперь может легко обрабатывать целочисленные данные, я думаю, что это довольно дешево.
mbomb007

5

Python 2 , 64 байта

f=lambda n,d=5,r='IVXLCD':r and f(n/d,7-d,r[1:])+n%d*r[0]or'M'*n

Попробуйте онлайн!

Вместо того, чтобы создавать выходную строку с самого начала, жадно занимая большую часть, это создает ее с конца. Например, число I's' n%5, затем число V's' n/5%2и так далее. Это смешанное базовое преобразование с чередующимися соотношениями 5 и 2.

Вот итерационный эквивалент:

Python 2 , 68 байт

n=input();s='';d=5
for c in'IVXLCD':s=n%d*c+s;n/=d;d^=7
print'M'*n+s

Попробуйте онлайн!

Их Mнужно обрабатывать отдельно, потому что может присутствовать любое их количество, так как нет большей цифры. Таким образом, после назначения других значений места оставшееся значение преобразуется в M's'.

Для сравнения жадная стратегия (69 байт):

Python 2 , 69 байт

f=lambda n,d=1000,r='MDCLXVI':r and n/d*r[0]+f(n%d,d/(d%3*3-1),r[1:])

Попробуйте онлайн!

Текущее значение цифры dделится на 2 или 5 для получения следующей цифры. Значение d%3скажите нам, какой: если d%3==1, разделите на 2; и если d%3==2, разделите на 5.


4

Mathematica, 81 байт

Table@@@Thread@{r=Characters@"MDCLXVI",#~NumberDecompose~FromRomanNumeral@r}<>""&

Явное использование значений и получение соответствующих цифр кажется на один байт длиннее:

Table@@@Thread@{RomanNumeral[n={1000,500,100,50,10,5,1}],#~NumberDecompose~n}<>""&

1
Ницца !:FromRomanNumeral@r
DavidC

4

Excel, 236 193 161 байт

43 байта сэкономлено благодаря @ BradC

На данный момент ответ действительно полностью принадлежит @ BradC . Еще 32 байта сохранены.

=REPT("M",A1/1E3)&REPT("D",MOD(A1,1E3)/500)&REPT("C",MOD(A1,500)/100)&REPT("L",MOD(A1,100)/50)&REPT("X",MOD(A1,50)/10)&REPT("V",MOD(A1,10)/5)&REPT("I",MOD(A1,5))

отформатирован:

=REPT("M",A1/1E3)
    &REPT("D",MOD(A1,1E3)/500)
    &REPT("C",MOD(A1,500)/100)
    &REPT("L",MOD(A1,100)/50)
    &REPT("X",MOD(A1,50)/10)
    &REPT("V",MOD(A1,10)/5)
    &REPT("I",MOD(A1,5))

Вы сэкономите, заменив некоторые CONCATENATEс &между каждым элементом, и QUOTIENTс INT(A/B).
BradC

Еще 2 сбережения: оказывается, REPTуже сокращает число, если оно не является целым числом , поэтому вы можете сохранить еще 30 байтов, удалив каждый INT(). Сохраните еще 2, заменив оба 1000на 1E3(хотя, похоже, Excel не захочет сохранять его таким, как только вы нажмете Enter).
BradC

Да, видел 1E3поведение. Ответ обновлен.
Верниш

3

Perl 5 , 66 байт

65 байт кода + -pфлаг.

$s=1e3;for$@(MDCLXVI=~/./g){$\.=$@x($_/$s);$_%=$s;$s/=--$|?2:5}}{

Попробуйте онлайн!

Без изменения количества байтов, MDCLXVI=~/./gможно заменить на M,D,C,L,X,V,I; и --$|?2:5по $|--*3+2.

Гораздо дольше ( 99 байт ) есть:

$_=M x($_/1e3).D x($_%1e3/500).C x($_%500/100).L x($_%100/50).X x($_%50/10).V x($_%10/5).I x($_%5)

3

CJam , 35 28 байт

-7 байт благодаря Мартину Эндеру

q~{5md\2md\}3*]W%"MDCLXVI".*

Попробуйте онлайн!

объяснение

q~         e# Read and eval input (push the input as an integer).
{          e# Open a block:
 5md\      e#  Divmod the top value by 5, and bring the quotient to the top.
 2md\      e#  Divmod that by 2, and bring the quotient to the top.
}3*        e# Run this block 3 times.
]W%        e# Wrap the stack in an array and reverse it. Now we've performed the mixed-base
           e# conversion.
"MDCLXVI"  e# Push this string.
.*         e# Element-wise repetition of each character by the numbers in the other array.
           e# Implicitly join and print.

3

C #, 127 байт

f=n=>n>999?"M"+f(n-1000):n>499?"D"+f(n-500):n>99?"C"+f(n-100):n>49?"L"+f(n-50):n>9?"X"+f(n-10):n>4?"V"+f(n-5):n>0?"I"+f(n-1):""

Чисто жестко закодированное троичное выражение, использующее рекурсию.

Полная / Отформатированная версия:

using System;

class P
{
    static void Main()
    {
        Func<int, string> f = null;
        f = n => n > 999 ? "M" + f(n - 1000)
                         : n > 499 ? "D" + f(n - 500)
                                   : n > 99 ? "C" + f(n - 100)
                                            : n > 49 ? "L" + f(n - 50)
                                                     : n > 9 ? "X" + f(n - 10)
                                                             : n > 4 ? "V" + f(n - 5)
                                                                     : n > 0 ? "I" + f(n - 1)
                                                                             : "";

        Console.WriteLine(f(3));
        Console.WriteLine(f(4));
        Console.WriteLine(f(42));
        Console.WriteLine(f(796));
        Console.WriteLine(f(2017));
        Console.WriteLine(f(16807));

        Console.ReadLine();
    }
}

n>0это просто n.
CalculatorFeline

@CalculatorFeline Не в C #, не intможет быть неявно приведен к bool.
TheLethalCoder

Это неудачно.
CalculatorFeline

@CalculatorFeline Да, C # слишком сильно напечатан, чтобы иногда его использовать.
TheLethalCoder

3

05AB1E , 29 26 25 байт

¸5n3×Rvćy‰ì}"MDCLXVI"Ss×J

Попробуйте онлайн!

объяснение

¸                           # wrap input in a list
 5n                         # push 5**2
   3×                       # repeat it 3 times
     Rv                     # for each digit y in its reverse
       ć                    # extract the head of the list 
                            # (div result of the previous iteration, initially input)
        y‰                  # divmod with y
          ì                 # prepend to the list
           }                # end loop
            "MDCLXVI"S      # push a list of roman numerals
                      s×    # repeat each a number of times corresponding to the result
                            # of the modulus operations
                        J   # join to string

3

JavaScript (ES6), 81 75 69 байт

Сохранено 6 байтов благодаря @Neil за перенос @ ответа Йорг Хюльсерманна

Сохранено 6 байтов благодаря @Shaggy

n=>'MDCLXVI'.replace(/./g,(c,i)=>c.repeat(n/a,n%=a,a/=i%2?5:‌​2),a=1e3)

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


1
Вы должны иметь возможность перемещать n%=xвнутри repeatметода, чтобы сохранить несколько байтов.
Лохматый

1
К вашему сведению, порт ответа PHP составляет всего 69 байт:n=>'MDCLXVI'.replace(/./g,(c,i)=>c.repeat(n/a,n%=a,a/=i%2?5:2),a=1e3)
Нил

Спасибо @Neil, я обновил пост. Удаляет жестко закодированный массив, к которому я хотел вернуться
Крейг Эйр,

2

/// , 50 байт

/1/I//IIIII/V//VV/X//XXXXX/L//LL/C//CCCCC/D//DD/M/

Попробуйте онлайн!

Принимает ввод в унарном виде, и я (ab) использую поле нижнего колонтитула на TIO для ввода, поэтому выводу предшествует символ новой строки.


2

Python 3 , 100 97 96 94 93 91 90 байт

  • сохранено 4 + 2 байта: использование def; массив как параметр по умолчанию уменьшил пространство отступа; объявление нежелательной переменной удалено
  • @shooqie сохранил 1 байтовое a%=сокращение
  • сохранено 2 байта: переставлены и (a//i)удалены скобки
  • @Wondercricket сохранено 1 байт: переместите массив из параметра по умолчанию в функцию, которая была удалена []за счет одного отступа, таким образом экономя 1 байт.
def f(a):
 b=1000,500,100,50,10,5,1
 for i in b:print(end=a//i*'MDCLXVI'[b.index(i)]);a%=i

Попробуйте онлайн!


1
a%=iна байт короче :)
shooqie

1
Вы также можете сохранить байт, сохранив его bкак переменную внутри функции. Это устраняет необходимость в скобках -b=1000,500,100,50,10,5,1
Wondercricket

2

Cubix , 69 74 80 байт

/.UI,..N&..0\0&/52"IVXLCDM"U,r%ws;rr3tu;pw..u;qrUosv!s.u\psq,!@Us(0;U

Попробуйте онлайн!

        / . U I
        , . . N
        & . . 0
        \ 0 & /
5 2 " I V X L C D M " U , r % w
s ; r r 3 t u ; p w . . u ; q r
U o s v ! s . u \ p s q , ! @ U
s ( 0 ; U . . . . . . . . . . .
        . . . .
        . . . .
        . . . .
        . . . .

Смотреть это работает

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

  • 52"IVXLCDM"Uпоместите необходимые делители и символы в стек. 5 и 2 будут использоваться для уменьшения значения div / mod, а символы будут отбрасываться после использования.
  • UIN0/&0\&,/UРазвернитесь на верхнюю грань и начните длинный тур, чтобы получить ввод и толкнуть 1000 в стек. Начальное деление сделано и разворот на rследующий фрагмент. Это была область, на которую я смотрел, чтобы сэкономить.
  • ,r%ws;rrначало цикла divmod. целочисленное деление, поверните результат без мода, затем переставьте верхнюю часть стека, чтобы уменьшить ввод, делитель тока и результат деления.
  • 3tus вывести текущий символ наверх и поменять его местами с результатом деления.
  • !vsoUs(0;Uэто цикл печати. в то время как результат div больше 0, поменяйте местами вывод символов, поменяйте местами назад, уменьшите, нажмите 0 и отбросьте его. На 0 перенаправить через поп стек (удалить результат деления) и вокруг куба.
  • \u;pwpsq,!@Urq;uс небольшим перенаправлением это удаляет персонажа из стека, поднимает 5 и 2 на вершину, меняет их местами и толкает один обратно вниз. Остальное используется для уменьшения делителя. Остановитесь, если оно уменьшится до 0, в противном случае сдвиньте 5 или 2 вниз и снова войдите в цикл.

1

Mathematica, 130 байт

(f=#~NumberDecompose~{1000,500,100,50,10,5,1};""<>{Flatten@Table[Table[{"M","D","C","L","X","V","I"}[[i]],f[[i]]],{i,Length@f}]})&

1

Python 2 , 109 90 байт

lambda n,r=[1000,500,100,50,10,5,1]:''.join(n%a/b*c for a,b,c in zip([n+1]+r,r,'MDCLXVI'))

Попробуйте онлайн!


1000может быть 1e3(если вы не возражаете, это плавание, которое не должно быть проблемой)
CalculatorFeline

@CalculatorFeline это превратит результат в a float, и вы не можете умножить строку на число с плавающей точкой: c
Rod


1

T-SQL, 164 байта

SELECT REPLICATE('M',n/1000)+IIF(n%1000>499,'D','')
      +REPLICATE('C',n%500/100)+IIF(n%100>49,'L','')
      +REPLICATE('X',n%50/10)+IIF(n%10>4,'V','')
      +REPLICATE('I',n%5)
FROM t

Добавлены разрывы строк только для удобства чтения.

Эта версия намного длиннее (230 символов), но ощущается гораздо более похожей на SQL:

DECLARE @ INT,@r varchar(99)=''SELECT @=n FROM t
SELECT'I's,1v INTO m
INSERT m VALUES('V',5),('X',10),('L',50),('C',100),('D',500),('M',1000)
L:
    SELECT @-=v,@r+=s 
    FROM m WHERE v=(SELECT MAX(v)FROM m WHERE v<=@)
IF @>0GOTO L
SELECT @r

Создает таблицу m со всеми сопоставлениями значений символов, а затем перебирает нахождение наибольшего значения <= число, объединяя соответствующий символ.


1

Japt , 34 байта

"IVXLCD"£%(U/=Y=v *3+2Y)îXÃw i'MpU

Проверьте это онлайн!

"IVXLCD"£    %(U/=Y=v  *3+2Y )îXÃ w i'MpU
"IVXLCD"mXY{U%(U/=Y=Yv *3+2,Y)îX} w i'MpU : Ungolfed
                                          : Implicit: U = input number
"IVXLCD"mXY{                    }         : Map each char X and its index Y in this string to:
                  Y=Yv *3+2               :   Set Y to 5 for even indexes, 2 for odd.
               U/=                        :   Divide U by this amount.
            U%(            ,Y)            :   Modulate the old value of U by 5.
                              îX          :   Repeat the character that many times.
                                          : This returns e.g. "IIVCCCD" for 16807.
                                  w       : Reverse the entire string.
                                    i'MpU : Prepend U copies of 'M' (remember U is now the input / 1000).
                                          : Implicit: output result of last expression

1

JavaScript (ES6), 65 байт

Рекурсивная функция.

f=(n,a=(i=0,1e3))=>n?a>n?f(n,a/=i++&1?5:2):'MDCLXVI'[i]+f(n-a):''

Как?

Второй рекурсивный вызов f(n-a)действительно должен быть f(n-a,a). Опуская второй параметр, aи iповторно инициализируются (до 1000 и 0 соответственно) каждый раз, когда новая римская цифра добавляется к окончательному результату. Это вызывает больше рекурсии, чем необходимо, но не изменяет результат функции и сохраняет 2 байта.

Контрольные примеры


1

J , 26 23 байта

3 байта сэкономлено благодаря Адаму.

'MDCLXVI'#~(_,6$2 5)&#:

Попробуйте онлайн!

Похоже на APL ответ в основном одно и то же.

'MDCLXVI'#~(_,6$2 5)&#:
           (       )&#:   mixed base conversion from decimal
              6$2 5       2 5 2 5 2 5
            _,            infinity 2 5 2 5 2 5
                          this gives us e.g. `0 0 0 0 1 0 4` for input `14`
'MDCLXVI'#~               shape each according to the number of times on the right
                          this is greedy roman numeral base conversion

Не то чтобы я знал J, но почему #.invвместо #:?
Адам

@ Adám Ах, хорошо. Я обычно использую #.invвместо #:, так как что-то вроде 2 #: 4есть 0, а 2 #.inv 4есть1 0 0
Конор О'Брайен

Да, я делаю то же самое в APL. Теперь ваше решение действительно эквивалентно решению APL.
Адам

#есть /; ~есть ; $есть ; &есть ; #:есть . Разница лишь в том, что вы используете бесконечность, в _то время как вы можете использовать 0как ответ APL.
Адам

@ Адам Да, круто.
Конор О'Брайен

1

Пакет, 164 байта

@set/pn=
@set s=
@for %%a in (1000.M 500.D 100.C 50.L 10.X 5.V 1.I)do @call:c %%~na %%~xa
@echo %s:.=%
@exit/b
:c
@if %n% geq %1 set s=%s%%2&set/an-=%1&goto c

Принимает участие в STDIN.


1

Oracle SQL, 456 байт

select listagg((select listagg(l)within group(order by 1)from dual start with trunc((n-nvl(n-mod(n,p),0))/v)>0 connect by level<=trunc((n-nvl(n-mod(n,p),0))/v)))within group(order by v desc)from (select 2849n from dual)cross join(select 1000v,null p,'m'l from dual union select 500,1000,'d'from dual union select 100,500,'c'from dual union select 50,100,'l'from dual union select 10,50,'x'from dual union select 5,10,'v'from dual union select 1,5,'i'from dual)

Выходы:

mmdcccxxxxviiii

Обратите внимание, что фактический размер строки составляет 460 байт, поскольку он включает в себя номер ввода (2849).

Ungolfed:

select listagg(
            (select listagg(l, '') within group(order by 1) 
             from dual 
             start with trunc((n-nvl(p*trunc(n/p),0))/v) > 0 
             connect by level <= trunc((n-nvl(p*trunc(n/p),0))/v) )
        ) within group(order by v desc)
from (select 2348 n
    from dual
) cross join (
    select 1000v, null p, 'm' l from dual union 
    select 500, 1000, 'd' from dual union
    select 100, 500, 'c' from dual union
    select 50, 100, 'l' from dual union
    select 10, 50, 'x' from dual union
    select 5, 10, 'v' from dual union
    select 1, 5, 'i' from dual     
)

Как это работает: я вычисляю, сколько каждой буквы мне нужно, вычисляя максимум, что я могу получить с более высоким значением (бесконечность для M), а затем делаю целочисленное деление между значением текущей буквы и результатом этого.

Например, 2348, сколько Cмне нужно? trunc((2348-mod(2348,500))/100)= 3

Затем я listaggпереписываю это письмо 3 раза (используя CONNECT BYдля генерации 3 нужных мне строк). Наконец-то у меня listaggвсе вместе.

Вроде громоздко, но большинство из них select from dualв таблице преобразования, и я не могу ничего с этим поделать ...


0

Java (OpenJDK 8) , 119 118 байт

n->{String s="";for(int v[]={1,5,10,50,100,500,1000},i=7;i-->0;)for(;n>=v[i];n-=v[i])s+="IVXLCDM".charAt(i);return s;}

Попробуйте онлайн!

Сохраненный байт благодаря @TheLethalCoder


1
Можете ли вы объявить vи iв первом цикле for сохранить байт?
TheLethalCoder

@TheLethalCoder Да, конечно. Сначала у меня была совершенно другая идея, что это не прошло мою внутреннюю рецензию: p
Оливье Грегуар

0

Древесный уголь , 61 50 46 байтов

NνA⁰χWφ«W¬‹νφ«§MDCLXVIχA⁻νφν»A⁺¹χχA÷φ⎇﹪χ²¦²¦⁵φ

Попробуйте онлайн!

Объяснение:

Nν                   Take input as number and assign it to ν
A⁰χ                  Let χ=0
Wφ«                  While φ>0 (φ has a predefined value of 1000)
    W¬‹νφ«               While v>=φ 
        §MDCLXVIχ             Take the char from string "MDCLXVI" at position χ
        A⁻νφν»               Let ν=ν-φ
    A⁺¹χχ                Increment χ
    A÷φ⎇﹪χ²¦²¦⁵φ        If χ is odd, divide φ by 5, else divide φ by 2
  • Благодаря Нилу сэкономлено 4 байта, а я все еще пытаюсь понять, как поступить со второй частью его комментария.

1
Nνна один байт короче ANν, ¬‹на один байт короче, чем вычитание 1, и если вы используете ÷(IntDivide) вместо (Divide), то вы можете использовать φв качестве условия внешнего цикла. Тем не менее, я думаю, что вы можете уменьшить его до 40 байт, зациклившись MDCLXVIнапрямую.
Нил

@ Нейл, конечно, глупый я, пытаясь понять, почему нет оператора «больше или равно», когда я мог бы использовать «не меньше». Очень умный трюк с использованием целочисленного деления. Теперь позвольте мне подумать о последней части вашего комментария ...
Чарли

Я улучшил свою идею строкового цикла и опубликовал ее как отдельный ответ вместе с портом ответа @ xnor's Python, который оказался такой же длины.
Нил

0

C ++, 272 байта

#include <cstdio>
#include <map>
std::map<int,char> m = {{1000,'M'},{500,'D'},{100,'C'},{50,'L'},{10,'X'},{5,'V'},{1,'I'}};
int main(){unsigned long x;scanf("%d",&x);for(auto i=m.rbegin();i!=m.rend();++i)while(x>=i->first){printf("%c", i->second);x=x-i->first;}return 0;}

0

C 183 байта

#include <stdio.h>
int v[]={1000,500,100,50,10,5,1};
char*c="MDCLXVI";
int main(){int x;scanf("%d",&x);for(int i=0;i<sizeof v/sizeof(int);i++)for(;x>=v[i];x-=v[i])putc(c[i],stdout);}

Тот же алгоритм, что и раньше, только использование простых массивов c вместо std :: map, частично вдохновленных ответом @ xnor, и использование строки для хранения букв.



0

Common Lisp, 113 байт

Это анонимная функция, возвращающая результат в виде строки.

(lambda(value)(setf(values a b)(floor v 1000))(concatenate 'string(format()"~v,,,v<~>"a #\M)(format nil"~@:r"b)))

Ungolfed, с описательными именами переменных и комментариями:

(defun format-roman (value)
  ;; Get "value integer-divided by 1000" and "value mod 1000"
  (setf (values n_thousands remainder) (floor value 1000))
  (concatenate 'string
               ;; Pad the empty string n_thousands times, using "M" as the 
               ;; padding character
               (format () "~v,,,v<~>" n_thousands #\M)
               ;; Format the remainder using "old-style" Roman numerals, i.e. 
               ;; numerals with "IIII" instead of "IV"
               (format nil "~@:r" remainder)))

CL имеет встроенный форматер римских цифр. К сожалению, это не работает для чисел больше 3999.


0

Древесный уголь , 34 байта

NςA²ξFMDCLXVI«×ι÷ςφA﹪ςφςA÷φξφA÷χξξ

Первоначально основано на ответе @ CarlosAlego. Порт Python-решения @ xnor также составляет 34 байта:

NθA⁵ξFIVXLCD«←×ι﹪θξA÷θξθA÷χξξ»←×Mθ

Изменить: Порт другого решения Python @ xnor оказывается 33 байта!

NθFMDCLXVI«×ι÷θφA﹪θφθA÷φ⁺׳﹪φ³±¹φ

Попробуйте онлайн! Ссылка на подробную версию кода. Обратите внимание, что я использовал ⁺׳﹪φ³±¹вместо, ⁻׳﹪φ³¦¹потому что в настоящее время девербозификатор не может вставить разделитель.


1
Да, это выглядит больше по-гречески, чем по-римски.
Адам
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.