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
в таблице преобразования, и я не могу ничего с этим поделать ...
4 -> IIII
,9 -> VIIII
а неIX
?