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)
Salidas:
mmdcccxxxxviiii
Tenga en cuenta que el tamaño real de la línea es de 460 bytes, ya que incluye el número de entrada (2849).
Sin golf:
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
)
Cómo funciona: calculo la cantidad de cada letra que necesito, calculando lo máximo que puedo obtener con el valor más alto uno (infinito para M), y luego haciendo una división entera entre el valor de la letra actual y el resultado de eso.
Por ejemplo, 2348, ¿cuántos C
s necesito? trunc((2348-mod(2348,500))/100)
= 3.
Luego, escribo listagg
esa carta 3 veces (explotando CONNECT BY
para generar las 3 filas que necesito) Finalmente, listagg
todo junto.
Un poco voluminoso, pero la mayor parte es el select from dual
s en la tabla de conversión y realmente no puedo hacer mucho al respecto ...
4 -> IIII
es9 -> VIIII
también en lugar deIX
?