Oracle SQL, 456 byte
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)
Uscite:
mmdcccxxxxviiii
Si noti che la dimensione effettiva della linea è 460 byte, poiché include il numero di input (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
)
Come funziona: calcolo il numero di ciascuna lettera di cui ho bisogno, calcolando il massimo che posso ottenere con il valore più alto uno (infinito per M) e quindi facendo una divisione intera tra il valore della lettera corrente e il risultato di quello.
Ad esempio 2348, quanti C
s ho bisogno? trunc((2348-mod(2348,500))/100)
= 3.
Quindi, listagg
quella lettera insieme 3 volte (sfruttandoCONNECT BY
per generare le 3 file di cui ho bisogno). Alla fine, ho listagg
tutto insieme.
Un po 'ingombrante, ma la maggior parte è la select from dual
s nella tabella di conversione e non posso davvero fare molto al riguardo ...
4 -> IIII
è9 -> VIIII
anche invece diIX
?