# ชาวโรมันผู้โลภ!

30

ให้เป็นจำนวนเต็มบวกอย่างเคร่งครัดคืนตัวเลขโรมันที่สั้นที่สุดโดยใช้กฎการบวกเท่านั้น เอาต์พุตจะต้องประกอบด้วยอักขระแต่ละตัว`MDCLXVI`ในศูนย์หรือมากกว่านั้น จำนวน`14`ดังนั้นจึงต้องให้มากกว่า`XIIII``XIV`

ค่าตัวเลขของอักขระคือ`M`= 1,000, `D`= 500, `C`= 100,`L` = 50, `X`= 10, `V`= 5, `I`= 1

### ตัวอย่าง

`3``III`

`4` → `IIII`

`9``VIIII`

`42``XXXXII`

`796``DCCLXXXXVI`

`2017``MMXVII`

`16807``MMMMMMMMMMMMMMMMDCCCVII`

1
คุณเป็นผู้ถามที่ใจดีที่ยอมให้`4 -> IIII`เป็น`9 -> VIIII`เช่นนั้นแทนที่จะเป็น`IX`?
Magic Octopus Urn

@MagicOctopusUrn `VIIII`เป็นผลลัพธ์ที่ได้รับอนุญาตเพียงรายการเดียวสำหรับ 9
2560

@ Adámเพิ่งชี้ให้เห็นว่าคุณอาจต้องการเพิ่มสิ่งนั้นเป็นตัวอย่างด้วยเนื่องจากกฎสำหรับ 4 และ 9 เหมือนกัน
Magic Octopus Urn

1

คำตอบ:

12

# ภาษาอังกฤษธรรมดา , 1059 1025 678 641 451 399 ไบต์

บันทึก 34 ไบต์โดยการลบกับดักข้อผิดพลาด จากนั้นบันทึกขนาด 384 ไบต์ด้วยการตีกอล์ฟ จากนั้นบันทึก 190 ไบต์ด้วยการรวมการดำเนินการหารเข้ากับการดำเนินการผนวก ("z") เป็นการดำเนินการใหม่ ("p") จากนั้นบันทึก 52 ไบต์โดยการเล่นกอล์ฟ

``````A s is a string.
To p a r remainder a s a x string a n number:
If the x is "", exit.
Divide the r by the n giving a q quotient and the r.
Fill a t s with the x's first's target given the q.
Append the t to the s.
To convert a r number to a s:
p the r the s "M" 1000.
p the r the s "D" 500.
p the r the s "C" 100.
p the r the s "L" 50.
p the r the s "X" 10.
p the r the s "V" 5.
p the r the s "I" 1.
``````

นี่คือเวอร์ชันสุดท้ายของโค้ดสุดท้ายที่ไม่ถูกรวมกับกับดักข้อผิดพลาดสำหรับจำนวนลบ:

``````A roman numeral is a string.

To process a remainder given a roman numeral and a letter string is a number:
If the letter is "", exit.
Divide the remainder by the number giving a quotient and the remainder.
Fill a temp string with the letter's first's target given the quotient.
Append the temp string to the roman numeral.

To convert a number to a roman numeral:
If the number is negative, exit.
Put the number in a remainder.
Process the remainder given the roman numeral and "M" is 1000.
Process the remainder given the roman numeral and "D" is  500.
Process the remainder given the roman numeral and "C" is  100.
Process the remainder given the roman numeral and "L" is   50.
Process the remainder given the roman numeral and "X" is   10.
Process the remainder given the roman numeral and "V" is    5.
Process the remainder given the roman numeral and "I" is    1.
``````

10
เดี๋ยวก่อนนี่คือภาษาการเขียนโปรแกรมใช่ไหม
อดัม

3
@Adam - ใช่ ภาษาอังกฤษล้วนรวบรวมและวิ่งและทุกอย่าง ซอร์สโค้ดและ IDE มีอยู่ที่github.com/Folds/english
Jasper

1
ลองเล่นกอล์ฟ - หลังจากทั้งหมดนี่คือรหัสกอล์ฟไม่ใช่การแสดงภาษา
Sanchises

2
ดังนั้นนี่คือภาษาที่คุณใช้ถ้าคุณไม่ต้องการให้งานเอาต์ซอร์ซของคุณไปด้วย?
corsiKa

@corsiKa - ฮ่า ๆ ! เฉพาะในกรณีที่เราเพียงพอที่จะเริ่มใช้มัน (และเพิ่มไปยังห้องสมุดของมัน) ว่ามันได้รับมวลที่สำคัญ
Jasper

5

# APL (Dyalog) , 25 22 ไบต์

``'MDCLXVI'/⍨(0,6⍴2 5)∘⊤``

ลองออนไลน์!

ดีและโดยทั่วไปฉันมีวิธีแก้ปัญหาในใจ อย่างไรก็ตามคุณสามารถใช้ replicate ( `/`) แทน reshape ( `⍴`) เพื่อให้คุณสามารถตัดแต่ละส่วนและ catenate-reduction ( `¨`และ`,/`)

นอกจากนี้คุณยังสามารถแปลงร่างเป็น tradfn และรับ input ( `⎕`) และใช้ commute ( `⍨`) เพื่อลบ parens และ compose ( `∘`)
อดัม

ขอบคุณ แต่ความคิดเห็นที่สองของคุณหมายถึงอะไร ฉันไม่สามารถคิดวิธีที่จะทำได้โดยไม่เพิ่มจำนวนไบต์
TwiNight

1

1
นั่นจะเป็นตัวอย่างถ้าคุณไม่นับ`{}`หรือ`∇f∇`ล้อมรอบฟังก์ชั่น
TwiNight

5

# เรติน่า , 57 42 ไบต์

แปลงเป็นเอกภาพจากนั้นโลภแทนที่กลุ่มของ`I`s ด้วยค่าที่สูงขึ้นตามลำดับ

``````.*
\$*I
I{5}
V
VV
X
X{5}
L
LL
C
C{5}
D
DD
M
``````

ลองออนไลน์

บันทึก 15 ไบต์ขอบคุณ Martin

มันฉลาดมาก

7
มันสั้นกว่ามากเมื่อเทียบกับวิธีอื่น: tio.run/##K0otycxL/ …
Martin Ender

คุณไม่สามารถป้อนข้อมูลด้วยการใช้`I`หน่วยเดียวหรือไม่

2
mbomb007

5

# Python 2 , 64 ไบต์

``f=lambda n,d=5,r='IVXLCD':r and f(n/d,7-d,r[1:])+n%d*ror'M'*n``

ลองออนไลน์!

แทนที่จะสร้างเอาท์พุทสตริงจากจุดเริ่มต้นด้วยการโลภส่วนที่ใหญ่ที่สุดอย่างโลภสร้างสิ่งนี้จากปลาย ตัวอย่างเช่นจำนวนของ`I`คือ`n%5`จากนั้นจำนวนของ`V`คือ`n/5%2`และอื่น ๆ นี่คือการแปลงฐานแบบผสมที่มีอัตราส่วนต่อเนื่องสลับกัน 5 และ 2

นี่เทียบเท่าซ้ำ:

Python 2 , 68 ไบต์

``````n=input();s='';d=5
for c in'IVXLCD':s=n%d*c+s;n/=d;d^=7
print'M'*n+s``````

ลองออนไลน์!

`M`'s จะต้องมีการจัดการแยกเพราะจำนวนของพวกเขาใด ๆ ที่อาจจะนำเสนอเป็นไม่มีหลักมีขนาดใหญ่ ดังนั้นหลังจากกำหนดค่าสถานที่อื่นแล้วค่าที่เหลือจะถูกแปลงเป็น`M`ของ

สำหรับการเปรียบเทียบกลยุทธ์โลภ (69 ไบต์):

Python 2 , 69 ไบต์

``f=lambda n,d=1000,r='MDCLXVI':r and n/d*r+f(n%d,d/(d%3*3-1),r[1:])``

ลองออนไลน์!

ค่าตัวเลขปัจจุบัน`d`ถูกหารด้วย 2 หรือ 5 เพื่อสร้างตัวเลขถัดไป คุณค่าของการ`d%3`บอกกับเราว่าอันไหน: ถ้า`d%3==1`หารด้วย`2`; และถ้า`d%3==2`หารด้วย 5

4

## Mathematica, 81 ไบต์

``````Table@@@Thread@{r=Characters@"MDCLXVI",#~NumberDecompose~FromRomanNumeral@r}<>""&
``````

ใช้ค่าอย่างชัดเจนและได้รับตัวเลขที่สอดคล้องกันดูเหมือนว่าจะมีความยาวหนึ่งไบต์:

``````Table@@@Thread@{RomanNumeral[n={1000,500,100,50,10,5,1}],#~NumberDecompose~n}<>""&
``````

1
ดีมาก!:`FromRomanNumeral@r`
DavidC

4

# Excel, 236 193 161 ไบต์

ณ จุดนี้คำตอบนั้นเป็นของ @ BradCจริงๆ บันทึกอีก 32 ไบต์

``````=REPT("M",A1/1E3)&REPT("D",MOD(A1,1E3)/500)&REPT("C",MOD(A1,500)/100)&REPT("L",MOD(A1,100)/50)&REPT("X",MOD(A1,50)/10)&REPT("V",MOD(A1,10)/5)&REPT("I",MOD(A1,5))
``````

จัดรูปแบบ:

``````=REPT("M",A1/1E3)
&REPT("D",MOD(A1,1E3)/500)
&REPT("C",MOD(A1,500)/100)
&REPT("L",MOD(A1,100)/50)
&REPT("X",MOD(A1,50)/10)
&REPT("V",MOD(A1,10)/5)
&REPT("I",MOD(A1,5))
``````

คุณจะได้บันทึกบางส่วนโดยการแทนที่`CONCATENATE`ด้วย`&`ระหว่างแต่ละองค์ประกอบและมี`QUOTIENT` `INT(A/B)`

2 เงินฝากออมทรัพย์เพิ่มเติมได้ที่: จะเปิดออก`REPT`แล้วตัดทอนจำนวนถ้ามันไม่ได้เป็นจำนวนเต็มเพื่อให้คุณสามารถรับส่วนลด 30 `INT()`ไบต์มากขึ้นโดยการเอาแต่ละ ประหยัดมากขึ้นอีก 2 รายการโดยแทนที่ทั้งสอง`1000`ด้วย`1E3`(แม้ว่า Excel จะไม่ต้องการให้เป็นแบบนั้นเมื่อคุณกด Enter)

ใช่เห็น`1E3`พฤติกรรม อัปเดตคำตอบแล้ว
Wernisch

3

# Perl 5 , 66 ไบต์

65 ไบต์ของรหัส + `-p`ธง

``\$s=1e3;for\$@(MDCLXVI=~/./g){\$\.=\$@x(\$_/\$s);\$_%=\$s;\$s/=--\$|?2:5}}{``

ลองออนไลน์!

โดยไม่เปลี่ยนจำนวนไบต์`MDCLXVI=~/./g`สามารถถูกแทนที่ด้วย`M,D,C,L,X,V,I`; และ`--\$|?2:5``\$|--*3+2`โดย

อีกต่อไป ( 99 ไบต์ ) มี:

``\$_=M x(\$_/1e3).D x(\$_%1e3/500).C x(\$_%500/100).L x(\$_%100/50).X x(\$_%50/10).V x(\$_%10/5).I x(\$_%5)``

3

# CJam , 35 28 ไบต์

-7 ไบต์ขอบคุณ Martin Ender

``````q~{5md\2md\}3*]W%"MDCLXVI".*
``````

ลองออนไลน์!

### คำอธิบาย

``````q~         e# Read and eval input (push the input as an integer).
{          e# Open a block:
5md\      e#  Divmod the top value by 5, and bring the quotient to the top.
2md\      e#  Divmod that by 2, and bring the quotient to the top.
}3*        e# Run this block 3 times.
]W%        e# Wrap the stack in an array and reverse it. Now we've performed the mixed-base
e# conversion.
"MDCLXVI"  e# Push this string.
.*         e# Element-wise repetition of each character by the numbers in the other array.
e# Implicitly join and print.
``````

3

# C #, 127 ไบต์

``f=n=>n>999?"M"+f(n-1000):n>499?"D"+f(n-500):n>99?"C"+f(n-100):n>49?"L"+f(n-50):n>9?"X"+f(n-10):n>4?"V"+f(n-5):n>0?"I"+f(n-1):""``

คำสั่งที่ประกอบไปด้วยรหัสยากอย่างหมดจดโดยใช้การเรียกซ้ำ

เวอร์ชันเต็ม / ฟอร์แมต:

``````using System;

class P
{
static void Main()
{
Func<int, string> f = null;
f = n => n > 999 ? "M" + f(n - 1000)
: n > 499 ? "D" + f(n - 500)
: n > 99 ? "C" + f(n - 100)
: n > 49 ? "L" + f(n - 50)
: n > 9 ? "X" + f(n - 10)
: n > 4 ? "V" + f(n - 5)
: n > 0 ? "I" + f(n - 1)
: "";

Console.WriteLine(f(3));
Console.WriteLine(f(4));
Console.WriteLine(f(42));
Console.WriteLine(f(796));
Console.WriteLine(f(2017));
Console.WriteLine(f(16807));

}
}``````

`n>0``n`เป็นเพียง
CalculatorFeline

@CalculatorFeline ไม่ใช่ใน C #, `int`ไม่สามารถส่งไปยัง a โดยปริยาย`bool`ได้
TheLethalCoder

นั่นเป็นโชคร้าย
CalculatorFeline

@CalculatorFeline ใช่แล้ว C # ถูกพิมพ์ออกมาอย่างแรงเกินไปเพราะบางครั้งมันก็ดี
TheLethalCoder

3

# 05AB1E , 29 26 25 ไบต์

``````¸5n3×Rvćy‰ì}"MDCLXVI"Ss×J
``````

ลองออนไลน์!

คำอธิบาย

``````¸                           # wrap input in a list
5n                         # push 5**2
3×                       # repeat it 3 times
Rv                     # for each digit y in its reverse
ć                    # extract the head of the list
# (div result of the previous iteration, initially input)
y‰                  # divmod with y
ì                 # prepend to the list
}                # end loop
"MDCLXVI"S      # push a list of roman numerals
s×    # repeat each a number of times corresponding to the result
# of the modulus operations
J   # join to string
``````

3

# JavaScript (ES6), 81 75 69 ไบต์

บันทึกแล้ว 6 ไบต์ขอบคุณ @Neil สำหรับคำตอบของ @ JörgHülsermann

บันทึกแล้ว 6 ไบต์ขอบคุณ @Shaggy

``````n=>'MDCLXVI'.replace(/./g,(c,i)=>c.repeat(n/a,n%=a,a/=i%2?5:‌​2),a=1e3)
``````

กรณีทดสอบ:

1
คุณควรจะสามารถย้ายวิธี`n%=x`การภายใน`repeat`เพื่อบันทึกไม่กี่ไบต์
Shaggy

1
FYI พอร์ตของคำตอบ PHP มีเพียง 69 ไบต์:`n=>'MDCLXVI'.replace(/./g,(c,i)=>c.repeat(n/a,n%=a,a/=i%2?5:2),a=1e3)`
Neil

Thanks @Neil, I've updated the post. Removes the hard coded array which I was wanting to revisit
Craig Ayre

2

# ///, 50 bytes

``````/1/I//IIIII/V//VV/X//XXXXX/L//LL/C//CCCCC/D//DD/M/
``````

Try it online!

Takes input in unary, and I'm (ab)using the footer field on TIO for input so output is preceded by a newline.

2

# Python 3, 100 97 96 94 93 91 90 bytes

• saved 4+2 bytes: use of `def`; array as default parameter reduced an indentation space; unwanted variable declaration removed
• @shooqie saved 1 byte `a%=` shorthand
• saved 2 bytes: rearranged and braces in `(a//i)` got removed
• @Wondercricket saved 1 byte: move the array from default parameter to within the function which removed `[]` at the cost of one indentation space, thus saving 1 byte.
``````def f(a):
b=1000,500,100,50,10,5,1
for i in b:print(end=a//i*'MDCLXVI'[b.index(i)]);a%=i``````

Try it online!

1
`a%=i` is a byte shorter :)
shooqie

1
You can also save a byte by storing `b` as a variable within the function. That removes the necessity of brackets - `b=1000,500,100,50,10,5,1`
Wondercricket

2

# Cubix, 69 7480 bytes

``````/.UI,..N&..0\0&/52"IVXLCDM"U,r%ws;rr3tu;pw..u;qrUosv!s.u\psq,!@Us(0;U
``````

Try it online!

``````        / . U I
, . . N
& . . 0
\ 0 & /
5 2 " I V X L C D M " U , r % w
s ; r r 3 t u ; p w . . u ; q r
U o s v ! s . u \ p s q , ! @ U
s ( 0 ; U . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
``````

Watch It Running

I have managed to compress it a bit more, but there is still some pesky no-ops, especially on the top face.

• `52"IVXLCDM"U` put the necessary divisors and characters on the stack. The 5 and 2 will be used to reduce the div/mod value and the characters will be discarded after use.
• `UIN0/&0\&,/U` u-turns onto the top face and starts a long tour to get the input and push 1000 onto the stack. An initial divide is done and a u-turn onto the `r` of the next snippet. This was an area I was looking at to make some savings.
• `,r%ws;rr` beginning of the divmod loop. integer divide, rotate the result away mod, then rearrange top of stack to be reduced input, current divisor and divide result.
• `3tus` bring the current character to the top and swap it with the divide result.
• `!vsoUs(0;U` this is the print loop. while the div result is more than 0, swap with character output, swap back, decrement, push a 0 and drop it. On 0 redirect over the pop stack (remove divide result) and around the cube.
• `\u;pwpsq,!@Urq;u` with a bit of redirection, this removes the character from the stack, brings the 5 and 2 to the top, swaps them and pushes one back down. The remaining is used to reduce the divisor. Halt if it reduces to 0, otherwise push the 5 or 2 to the bottom and re-enter the loop.

1

# Mathematica, 130 bytes

``````(f=#~NumberDecompose~{1000,500,100,50,10,5,1};""<>{Flatten@Table[Table[{"M","D","C","L","X","V","I"}[[i]],f[[i]]],{i,Length@f}]})&
``````

1

# Python 2, 109 90 bytes

``lambda n,r=[1000,500,100,50,10,5,1]:''.join(n%a/b*c for a,b,c in zip([n+1]+r,r,'MDCLXVI'))``

Try it online!

`1000` can be `1e3` (if you don't mind it being a float which shouldn't be a problem)
CalculatorFeline

@CalculatorFeline it would turn the result into a `float`, and you can't multiply a string by a float :c
Rod

1

# T-SQL, 164 bytes

``````SELECT REPLICATE('M',n/1000)+IIF(n%1000>499,'D','')
+REPLICATE('C',n%500/100)+IIF(n%100>49,'L','')
+REPLICATE('X',n%50/10)+IIF(n%10>4,'V','')
+REPLICATE('I',n%5)
FROM t
``````

This version is a lot longer (230 characters), but feels much more "SQL-like":

``````DECLARE @ INT,@r varchar(99)=''SELECT @=n FROM t
SELECT'I's,1v INTO m
INSERT m VALUES('V',5),('X',10),('L',50),('C',100),('D',500),('M',1000)
L:
SELECT @-=v,@r+=s
FROM m WHERE v=(SELECT MAX(v)FROM m WHERE v<=@)
IF @>0GOTO L
SELECT @r
``````

Makes a table m with all the char-value mappings, and then loops through finding the largest value <= the number, concatenating the matching character.

1

# Japt, 34 bytes

``````"IVXLCD"£%(U/=Y=v *3+2Y)îXÃw i'MpU
``````

Test it online!

``````"IVXLCD"£    %(U/=Y=v  *3+2Y )îXÃ w i'MpU
"IVXLCD"mXY{U%(U/=Y=Yv *3+2,Y)îX} w i'MpU : Ungolfed
: Implicit: U = input number
"IVXLCD"mXY{                    }         : Map each char X and its index Y in this string to:
Y=Yv *3+2               :   Set Y to 5 for even indexes, 2 for odd.
U/=                        :   Divide U by this amount.
U%(            ,Y)            :   Modulate the old value of U by 5.
îX          :   Repeat the character that many times.
: This returns e.g. "IIVCCCD" for 16807.
w       : Reverse the entire string.
i'MpU : Prepend U copies of 'M' (remember U is now the input / 1000).
: Implicit: output result of last expression
``````

1

## JavaScript (ES6), 65 bytes

A recursive function.

``f=(n,a=(i=0,1e3))=>n?a>n?f(n,a/=i++&1?5:2):'MDCLXVI'[i]+f(n-a):''``

### How?

The second recursive call `f(n-a)` really should be `f(n-a,a)`. By omitting the 2nd parameter, `a` and `i` are reinitialized (to 1000 and 0 respectively) each time a new Roman digit is appended to the final result. This causes more recursion than needed but doesn't alter the outcome of the function and saves 2 bytes.

1

# J, 26 23 bytes

3 bytes saved thanks to Adám.

``````'MDCLXVI'#~(_,6\$2 5)&#:
``````

Try it online!

Similar to the APL answer basically the same thing.

``````'MDCLXVI'#~(_,6\$2 5)&#:
(       )&#:   mixed base conversion from decimal
6\$2 5       2 5 2 5 2 5
_,            infinity 2 5 2 5 2 5
this gives us e.g. `0 0 0 0 1 0 4` for input `14`
'MDCLXVI'#~               shape each according to the number of times on the right
this is greedy roman numeral base conversion
``````

Not that I know J, but why `#.inv` instead of `#:`?

@Adám Ah, good point. I customarily use `#.inv` instead of `#:`, since something like `2 #: 4` is `0`, whilst `2 #.inv 4` is `1 0 0`
Conor O'Brien

Yeah, I do the same thing in APL. Now your solution is truly equivalent to the APL solution.

`#` is `/`; `~` is `⍨`; `\$` is `⍴`; `&` is `∘`; `#:` is `⊤`. The only difference is that you use infinity `_` while you could use `0` like the APL answer.

Conor O'Brien

1

## Batch, 164 bytes

``````@set/pn=
@set s=
@for %%a in (1000.M 500.D 100.C 50.L 10.X 5.V 1.I)do @call:c %%~na %%~xa
@echo %s:.=%
@exit/b
:c
@if %n% geq %1 set s=%s%%2&set/an-=%1&goto c
``````

Takes input on STDIN.

1

# 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)
``````

Outputs:

``````mmdcccxxxxviiii
``````

Please note the actual size of the line is 460bytes, because it includes the input number (2849).

Ungolfed:

``````select listagg(
(select listagg(l, '') within group(order by 1)
from dual
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
)
``````

How it works: I calculate how many of each letter I need, by calculating the most I can get to with the higher value one (infinity for M), and then doing an integer division between the current letter's value and the result of that.

E.g. 2348, how many `C`s do I need? `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...

0

# Java (OpenJDK 8), 119 118 bytes

``n->{String s="";for(int v[]={1,5,10,50,100,500,1000},i=7;i-->0;)for(;n>=v[i];n-=v[i])s+="IVXLCDM".charAt(i);return s;}``

Try it online!

Saved a byte thanks to @TheLethalCoder

1
Can you declare `v` and `i` in the first for loop to save a byte?
TheLethalCoder

@TheLethalCoder Yes, most certainly. I was on a totally other idea at first that this didn't pass my internal review :p
Olivier Grégoire

0

# Charcoal, 61 50 46 bytes

``````ＮνＡ⁰χＷφ«Ｗ¬‹νφ«§MDCLXVIχＡ⁻νφν»Ａ⁺¹χχＡ÷φ⎇﹪χ²¦²¦⁵φ
``````

Try it online!

Explanation:

``````Ｎν                   Take input as number and assign it to ν
Ａ⁰χ                  Let χ=0
Ｗφ«                  While φ>0 (φ has a predefined value of 1000)
Ｗ¬‹νφ«               While v>=φ
§MDCLXVIχ             Take the char from string "MDCLXVI" at position χ
Ａ⁻νφν»               Let ν=ν-φ
Ａ⁺¹χχ                Increment χ
Ａ÷φ⎇﹪χ²¦²¦⁵φ        If χ is odd, divide φ by 5, else divide φ by 2
``````
• 4 bytes saved thanks to Neil, while I am still trying to figure out how to proceed with the second part of his comment.

1
`Ｎν` is one byte shorter than `ＡＮν`, `¬‹` is one byte shorter than subtracting 1, and if you use `÷` (IntDivide) instead of `∕` (Divide) then you can use `φ` as the outer loop condition. However, I think you can get it down to 40 bytes by looping over `MDCLXVI` directly instead.
Neil

@Neil of course, silly me, trying to understand why there is no "greater or equal" operator when I could use "not less". Very clever trick the use of the integer division. Now allow me some time to think about the last part of your comment...
Charlie

I improved my string loop idea and posted it as a seprate answer along with a port of @xnor's Python answer, which turned out to be the same length.
Neil

0

# C++, 272 Bytes

``````#include <cstdio>
#include <map>
std::map<int,char> m = {{1000,'M'},{500,'D'},{100,'C'},{50,'L'},{10,'X'},{5,'V'},{1,'I'}};
int main(){unsigned long x;scanf("%d",&x);for(auto i=m.rbegin();i!=m.rend();++i)while(x>=i->first){printf("%c", i->second);x=x-i->first;}return 0;}
``````

0

# C, 183 Bytes

``````#include <stdio.h>
int v[]={1000,500,100,50,10,5,1};
char*c="MDCLXVI";
int main(){int x;scanf("%d",&x);for(int i=0;i<sizeof v/sizeof(int);i++)for(;x>=v[i];x-=v[i])putc(c[i],stdout);}
``````

Same algorithm as before, just using plain c arrays instead of an std::map, partially inspired by @xnor's answer and using a string to store the letters.

0

## Common Lisp, 113 bytes

This is an anonymous function, returning the result as a string.

``````(lambda(value)(setf(values a b)(floor v 1000))(concatenate 'string(format()"~v,,,v<~>"a #\M)(format nil"~@:r"b)))
``````

Ungolfed, with descriptive variable names and comments:

``````(defun format-roman (value)
;; Get "value integer-divided by 1000" and "value mod 1000"
(setf (values n_thousands remainder) (floor value 1000))
(concatenate 'string
;; Pad the empty string n_thousands times, using "M" as the
(format () "~v,,,v<~>" n_thousands #\M)
;; Format the remainder using "old-style" Roman numerals, i.e.
;; numerals with "IIII" instead of "IV"
(format nil "~@:r" remainder)))
``````

CL has built-in Roman numeral formatter. Sadly it doesn't work for numbers larger than 3999.

0

# Charcoal, 34 bytes

``````ＮςＡ²ξＦMDCLXVI«×ι÷ςφＡ﹪ςφςＡ÷φξφＡ÷χξξ
``````

Originally based on @CarlosAlego's answer. A port of @xnor's Python solution is also 34 bytes:

``````ＮθＡ⁵ξＦIVXLCD«←×ι﹪θξＡ÷θξθＡ÷χξξ»←×Mθ
``````

Edit: A port of @xnor's other Python solution turns out to be 33 bytes!

``````ＮθＦMDCLXVI«×ι÷θφＡ﹪θφθＡ÷φ⁺×³﹪φ³±¹φ
``````

Try it online! Link is to verbose version of code. Note that I've used `⁺×³﹪φ³±¹` instead of `⁻×³﹪φ³¦¹` because the deverbosifier is currently failing to insert the separator.

1
Huh, that looks more Greek than Roman.