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
入力番号(2849)が含まれているため、行の実際のサイズは460バイトです。
ゴルフをしていない:
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
)
仕組み:より高い値の1(Mの無限大)で到達できる最大数を計算し、現在の文字の値とその結果の間で整数除算を行うことにより、必要な各文字の数を計算します。
たとえば、2348、何C
秒必要ですか?trunc((2348-mod(2348,500))/100)
= 3。
Then, I listagg
that letter together 3 times (exploiting CONNECT BY
to generate the 3 rows I need).
Finally, I listagg
everything together.
Kinda bulky, but most of it is the select from dual
s in the conversion table and I can't really do much about that...
4 -> IIII
で9 -> VIIII
も代わりのようIX
?