Oracle SQL, 456 bytes
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)
Saídas:
mmdcccxxxxviiii
Observe que o tamanho real da linha é 460 bytes, porque inclui o número de entrada (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
)
Como funciona: calculo quantas letras de cada letra preciso, calculando o máximo possível com o valor mais alto (infinito para M) e, em seguida, fazendo uma divisão inteira entre o valor da letra atual e o resultado disso.
Por exemplo, 2348, quantos C
s eu preciso? trunc((2348-mod(2348,500))/100)
= 3
Então, eu listagg
letra juntos três vezes (explorando CONNECT BY
para gerar as três linhas necessárias). Finalmente eulistagg
tudo junto.
Meio volumoso, mas a maioria está select from dual
na tabela de conversão e não posso fazer muito sobre isso ...
4 -> IIII
é9 -> VIIII
assim em vez deIX
?