17

Write a program that take a single command line argument N and prints out the corresponding Roman Numeral.

Eg N = 2009 should print MMIX.

Let's say this should work for 0 < N < 3000.

(Had fun playing my first ever round of code golf with the Christmas edition, and thought this could fit for New Year. Googled to see if this has come up before elsewhere and it looks like it hasn't, but let me know if this is too hard or too easy or if the rules need changing. )

Happy MMIX!

Community
  • 1
  • 1
user4812
  • 5,942
  • 9
  • 30
  • 35

31 Answers31

17

Perl: 69 strokes (count 'em!)

Sixty-nine strokes including calling perl in the first place:

$ perl -ple's!.!($#.=5x$&*8%29628)=~y$IVCXL4620-8$XLMCDIXV$d!eg;last}{'
3484
MMMCDLXXXIV
  • Reads a single line, writes a single line.
  • Works from 0 to 3999, inclusive. (Prints empty string for 0.)
  • In Perl golf competitions, this is usually scored as 62 strokes = 58 for the code + 4 for the switches.
  • Why, yes, those are mismatched braces. Thanks for asking. =)

Credits: originally due to Ton Hospel. The trick involving the mismatched braces is from rev.pl in this post (which incidentally, is ingenious).

A. Rex
  • 31,633
  • 21
  • 89
  • 96
  • You should remove ;last}{ and save 7 chars. Furthermore i think you have not to take into account the invocation of perl interpreter, so you save 5 chars more. Count is then 57 chars ! – Toto Jul 11 '10 at 10:05
14

In C#, as an extension method to Int32:

public static class Int32Extension {
    public static string ToRomanNumeral(this int number) {
        Dictionary<int, string> lookup = new Dictionary<int, string>() {
            { 1000000, "M_" },
            { 900000, "C_D_" },
            { 500000, "D_" },
            { 400000, "C_D_" },
            { 100000, "C_" },
            { 90000, "X_C_" },
            { 50000, "L_" },
            { 40000, "X_L_" },
            { 10000, "X_" },
            { 9000, "MX_"},
            { 5000, "V_" },
            { 4000, "MV_" },
            { 1000, "M" },
            { 900, "CM" },
            { 500, "D" },
            { 400, "CD" },
            { 100,"C" },
            { 90, "XC" },
            { 50, "L" },
            { 40, "XL" },
            { 10, "X" },
            { 9, "IX" },
            { 5, "V" },
            { 4, "IV" },
            { 1, "I" }
        };

        StringBuilder answer = new StringBuilder();
        foreach (int key in lookup.Keys.OrderBy(k => -1 * k)) {
            while (number >= key) {
                number -= key;
                answer.Append(lookup[key]);
            }
        }
        return answer.ToString();
    }
}

The underscores should be overlines above the respective letter to be true Roman Numeral.

jason
  • 236,483
  • 35
  • 423
  • 525
11

Common lisp (SBCL). 63 characters counted by "wc -c".

(format t "~@R~%" (parse-integer (elt *posix-argv* 1)))
(quit)

This only works for numbers upto 3999.

user49117
  • 786
  • 3
  • 9
6

C#: 179 chars (not including spaces/tabs)

    static string c(int a)
    {
        int[] v = { 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 };
        var s = ""; 
        for ( var i = 0; i < 13; i++ )
            while (a >= v[i])
            {
                a -= v[i];
                s += "M CM D CD C XC L XL X IX V IV I".Split()[i];
            }
        return s;
    }
BenAlabaster
  • 39,070
  • 21
  • 110
  • 151
  • 1
    I think if you delimited your numerals with a space instead of a pipe you could just call `Split()` without an argument. – Phil Gan Jul 09 '10 at 13:47
  • 1
    @Phil Thanks, I learned something new today :) I never knew that worked. It makes me wonder how many times I've used split with needless params in the past. – BenAlabaster Jul 09 '10 at 18:08
5

Perl, 19 strokes. Guaranteed to work for values between 1 and 12.

sub r{chr 8543+pop}
C. K. Young
  • 219,335
  • 46
  • 382
  • 435
5

Language: JavaScript.

129 chars without the added formatting

The following code is a result of coding quiz which which took place at pl.comp.lang.javascript newsgrup several years ago. I'm not the author of the code.

function rome(N,s,b,a,o){
  for(s=b='',a=5;N;b++,a^=7)for(o=N%a,N=N/a^0;o--;)
  s='IVXLCDM'.charAt(o>2?b+N-(N&=~1)+(o=1):b)+s;return s
}

Original post by Elus

annakata
  • 74,572
  • 17
  • 113
  • 180
Tomasz Elendt
  • 1,475
  • 13
  • 14
4

Python, 173 bytes.

r=lambda n:o[n]if n<10 else''.join(dict(zip('ivxlc','xlcdm'))[c]for c in r(n//10))+o[n%10]
o=' i ii iii iv v vi vii viii ix'.split(' ')
import sys
print r(int(sys.argv[1]))

(I first saw this algorithm in Gimpel's Algorithms in Snobol4; Snobol expressed it more elegantly.)

Darius Bacon
  • 14,921
  • 5
  • 53
  • 53
  • This is great! Recursive application on n//10 is a much more terse and effective usage of the independence between digits than simply popping one off at a time, most significant first. – James Brady Dec 27 '08 at 10:29
4

Language: C, Char count: 174

#define R(s,v)for(;n>=v;n-=v)printf(#s);
main(int n,char**a){n=atoi(a[1]);R(M,1000)R(CM,900)R(D,500)R(CD,400)R(C,100)R(XC,90)R(L,50)R(XL,40)R(X,10)R(IX,9)R(V,5)R(IV,4)R(I,1)}
Boojum
  • 6,592
  • 1
  • 30
  • 34
3

Perl 5.10

perl -nE'@l=qw{1 I 4 IV 5 V 9 IX 10 X 40 XL 50 L 90 XC 100 C 400 CD 500 D 900 CM 1000 M};
$o="";while(@l){$o.=pop(@l)x($_/($c=pop @l));$_%=$c;}say$o'

You input a line, it gives you the Roman numeral equivelent. This first version even lets you input more than one line.

Here is a shorter version that only works for one line, and ignores edge cases. so 4 becomes IIII instead of IV.

perl -nE'@l=qw{1 I 5 V 10 X 50 L 100 C 500 D 1000 M};
while(@l){$o.=pop(@l)x($_/($c=pop @l));$_%=$c;}say$o'

Here is what the first version would look like as a Perl script.

use 5.010;
while(<>){
  @l=qw{1 I 4 IV 5 V 9 IX 10 X 40 XL 50 L 90 XC 100 C 400 CD 500 D 900 CM 1000 M};
  $o="";
  while(@l){
    $o .= pop(@l) x ($_/($c=pop @l));
    # $l = pop @l;
    # $c = pop @l;
    # $o .= $l x ($_/$c);

    $_ %= $c;
  }
  say $o;
}
Community
  • 1
  • 1
Brad Gilbert
  • 33,846
  • 11
  • 78
  • 129
  • Does Perl actually guarantee left-to-right execution order? I know it "works in this implementation", but is it actually guaranteed (e.g., Java guarantees it)? Curious. For example, in C, the right-hand pop is just as likely as the left-hand one to be executed first. – C. K. Young Dec 27 '08 at 20:25
  • For infix operators, like `x`, the left side is evaluated before the right side. – Brad Gilbert Dec 28 '08 at 08:23
  • I was going to post a Unicode version that would work for any positive integer, unfortunately it seems to be extremely difficult. – Brad Gilbert Jan 03 '09 at 06:34
3

Pike

60 characters, valid for 0 to 10000:

int main (int c, array a) {
    write(String.int2roman((int)a[1]));
}
some
  • 48,070
  • 14
  • 77
  • 93
3

A simple Haskell version, that still keeps clarity. 205 characters, including white space.

l = ["M","CM","L","CD","C","XC","L","XL","X","IX","V","IV","I"]
v = [1000,900,500,400,100,90,50,40,10,9,5,4,1]
roman n i
    | n == 0 = ""
    | n >= v!!i = l!!i ++ roman (n-v!!i) i
    | otherwise = roman n (i+1)
Thomas Ahle
  • 30,774
  • 21
  • 92
  • 114
2

I'm no Haskell expert, and this is too long to be a winner, but here's a solution I wrote a while back to solve Euler #89.

toRoman 0 = ""
toRoman 1 = "I"
toRoman 2 = "II"
toRoman 3 = "III"
toRoman 4 = "IV"
toRoman n
| n >= 1000 = repeatRoman 'M' 1000
| n >= 900 = subtractRoman "CM" 900
| n >= 500 = subtractRoman "D" 500
| n >= 400 = subtractRoman "CD" 400
| n >= 100 = repeatRoman 'C' 100
| n >= 90 = subtractRoman "XC" 90
| n >= 50 = subtractRoman "L" 50
| n >= 40 = subtractRoman "XL" 40
| n >= 10 = repeatRoman 'X' 10
| n >= 9 = subtractRoman "IX" 9
| n >= 5 = subtractRoman "V" 5
| otherwise = error "Hunh?"
where
    repeatRoman c n' = (take (n `div` n') (repeat c)) ++ (toRoman $ n `mod` n')
    subtractRoman s n' = s ++ (toRoman $ n - n')
Gregory Higley
  • 15,923
  • 9
  • 67
  • 96
2

J, 20 characters!

'MDCLXVI'#~(7$5 2)#:

Usage:

   'MDCLXVI'#~(7$5 2)#: 2009
MMVIIII

Okay, it doesn't do subtraction properly, but hey it's pretty cool!

Explanation;

(7$5 2)

This takes the right argument (the list 5 2) and turns it into a list of size 7 - namely 5 2 5 2 5 2 5.

(7$5 2)#: 2009

This does the "anti-base" operation - basically doing iterative div and mod operations, returning the list 2 0 0 0 0 0 1 4.

Then #~ uses the previous list as a tally to pull corresponding characters out of 'MDCLXVI'.

David
  • 7,011
  • 1
  • 42
  • 38
2

In Python - taken from ActiveState (credits: Paul Winkler) and compressed a bit:

def int2roman(n):
   if not 0 < n < 4000: raise ValueError
   ints = (1000, 900,  500, 400, 100,  90, 50,  40, 10,  9,   5,  4,   1)
   nums = ('M',  'CM', 'D', 'CD','C', 'XC','L','XL','X','IX','V','IV','I')
   result = ""
   for i in range(len(ints)):
      count = int(n / ints[i])
      result += nums[i] * count
      n -= ints[i] * count
   return result
Federico A. Ramponi
  • 46,145
  • 29
  • 109
  • 133
  • Nice - compressed down I get 293 bytes, including command-line arg reading. The implicit floor in integer division really saves some characters! – James Brady Dec 27 '08 at 03:34
2

Perl, 145 strokes (if you strip out all the newlines, which are optional), valid for 1..3999:

%t=qw(1000 M 900 CM 500 D 400 CD 100 C 90 XC 50 L 40 XL 10 X 9 IX 5 V 4 IV 1 I);
$d=pop;
for(sort{$b<=>$a}keys%t){$r.=$t{$_}x($d/$_);$d%=$_}
print$r

Some would say I could use say, but I don't have a say-capable Perl version here. Feel free to subtract 2 off the stroke count if using say works. :-)

For non-Perl programmers, this program exploits a number of useful Perl features:

  1. Hashes are constructed from lists of even length.
  2. Lists of strings can be specified in a compact syntax, using qw.
  3. Strings can auto-coerce into integers, as used in the <=> comparison operator in sorting the keys.
  4. There is an x operator which makes copies of strings/lists. Unfortunately for golfing here, x has identical precedence to /; if / were higher, the brackets would have been optional too.
C. K. Young
  • 219,335
  • 46
  • 382
  • 435
  • You can squeeze out a few characters by doing the sorting yourself. (Bonus teaching: hash slice assignment) Also, stmt mod 'for' saves 2 chars. @d=(1000,900,500,400,100,90,50,40,10,9,5,4,1);@r{@d}=qw(M CM D CD C XC L CL X IX V IV I);$d=pop;$r.=$r{$_}x($d/$_),$d%=$_ for@d;print$r – JB. Jan 02 '09 at 21:10
2

Language: dc (through shell) Char count:122

EDIT: q is equivalent of 2Q

dc -e '[I]1[IV]4[V]5[IX]9[X]10[XL]40[L]50[XC]90[C]100[CD]400[D]500[CM]900[M]?1000[szsz2Q]sq[~Sa[d0!<qrdPr1-lbx]dsbxLarz3<c]dscx10P' <<<$1

EDIT: two more chars by optimizing main loop stack manipulations

dc -e '[I]1[IV]4[V]5[IX]9[X]10[XL]40[L]50[XC]90[C]100[CD]400[D]500[CM]900[M]?1000[szsz2Q]sq[~Sa[d0!<qrdPr1-lbx]dsbxLarz3<c]dscx10P' <<<$1

EDIT: save 2 chars

dc -e '[I]1[IV]4[V]5[IX]9[X]10[XL]40[L]50[XC]90[C]100[CD]400[D]500[CM]900[M]1000?[sz2Q]sq[r~r[d0!<qSardPrLa1-lbx]dsbxrszz2<c]dscx10P' <<<$1

Previous version:

dc -e '[I]1[IV]4[V]5[IX]9[X]10[XL]40[L]50[XC]90[C]100[CD]400[D]500[CM]900[M]1000?[sz2Q]sq[r~r[d0!<qSaSadPLaLa1-lbx]dsbxrszz2<c]dscx10P' <<<$1
Hynek -Pichi- Vychodil
  • 26,174
  • 5
  • 52
  • 73
2

Ruby, 136 chars

n = $*[0].to_i
for k,v in [1e3,900,500,400,100,90,50,40,10,9,5,4,1].zip %w{M CM D CD C XC L XL X IX V IV I}
  until n < k
    n -= k
    print v
  end
end
Jules
  • 6,318
  • 2
  • 29
  • 40
1

From a vaguely C-like language called LPC (precursor of Pike):

string roman_numeral(int val) {
    check_argument(1, val, #'intp);
    unless(val)
        return "N";
    string out = "";
    if(val < 0) {
        out += "-";
        val = -val;
    }
    if(val >= 1000) {
        out += "M" * (val / 1000);
        val %= 1000;
    }
    if(val >= 100) {
        int part = val / 100;
        switch(part) {
        case 9      :
            out += "CM";
            break;
        case 6 .. 8 :
            out += "D" + ("C" * (part - 5));
            break;
        case 5      :
            out += "D";
            break;
        case 4      :
            out += "CD";
            break;
        default     :
            out += "C" * part;
            break;
        }
        val %= 100;
    }
    if(val >= 10) {
        int part = val / 10;
        switch(part) {
        case 9      :
            out += "XC";
            break;
        case 6 .. 8 :
            out += "L" + ("X" * (part - 5));
            break;
        case 5      :
            out += "L";
            break;
        case 4      :
            out += "XL";
            break;
        default     :
            out += "X" * part;
            break;
        }
        val %= 10;
    }
    switch(val) {
    case 9      :
        out += "IX";
        break;
    case 6 .. 8 :
        out += "V" + ("I" * (val - 5));
        break;
    case 5      :
        out += "V";
        break;
    case 4      :
        out += "IV";
        break;
    default     :
        out += "I" * val;
        break;
    }
    return out;
}
chaos
  • 122,029
  • 33
  • 303
  • 309
1

Python, 190 bytes. Based on snippet from ActiveState, via Federico.

A few small optimisations: removal of superfluous int() call, splitting string to get array, remove whitespace, ...

import sys
n=int(sys.argv[1])
N=(1000,900,500,400,100,90,50,40,10,9,5,4,1)
r=""
for i in range(len(N)):
 c=n/N[i]
 r+='M,CM,D,CD,C,XC,L,XL,X,IX,V,IV,I'.split(',')[i]*c
 n-=N[i]*c
print r

EDIT: superfluous, not spurious, and remove range check - thanks to Chris and dreeves! Stole idea of using symbol array inline from balabaster.

Community
  • 1
  • 1
James Brady
  • 27,032
  • 8
  • 51
  • 59
  • You can throw out the range check too, and just say that the program works only for 1..3999, which is what my Perl one says, and the Common Lisp submission. :-P – C. K. Young Dec 27 '08 at 05:56
  • You can remove the parens from N's assignment. You can also move the for onto a single line, separating the statements by semicolon. That will save you another 4 bytes. – recursive Jan 03 '09 at 22:56
1

VB: 193 chars

Function c(ByVal a)
    Dim v() = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}
    Dim s = ""
    For i = 0 To 12
        While a >= v(i)
            a -= v(i)
            s += "M|CM|D|CD|C|XC|L|XL|X|IX|V|IV|I".Split("|")(i)
        End While
    Next
    Return s
End Function
BenAlabaster
  • 39,070
  • 21
  • 110
  • 151
1

Excel 8 chars (not lincluding the number):

=ROMAN(N)

Works up to 3000.

Tongue in cheek

FinancialRadDeveloper
  • 984
  • 4
  • 13
  • 28
0

In C# (running on .NET 4 RC), with 335 chars (if you remove the extraneous formatting).

using System;
using System.Linq;
class C
{
    static void Main()
    {
        Console.WriteLine(
                Console.ReadLine()
                .PadLeft(4,'0')
                .Select(d=>d-'0')
                .Zip(new[]{"  M","MDC","CLX","XVI"},(x,y)=>new{x,y})
                .Aggregate("",(r,t)=>r+
                                    new string(t.y[2],t.x%5/4)+
                                    new string(t.y[0],t.x%5/4*t.x/5)+
                                    new string(t.y[1],Math.Abs(t.x%5/4-t.x/5))+
                                    new string(t.y[2],t.x%5%4)));
    }
}

I know it does not beat the current best C# answer (182 chars) but this is just one big LINQ one-liner. Once I saw a raytracer written as a single LINQ query, I started approaching code golfs from this perspective.

Since this approach is functional, I'm working on a Haskell version of the same algorithm (will surely be shorter).

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
0

Haskell version of my C#/LINQ answer, 234 chars:

main=putStrLn.foldr(\(y,x)s->concat[s,r(a x)(y!!2),r(a x*div x 5)(y!!0),r(abs(a x-div x 5))(y!!1),r(mod(mod x 5)4)(y!!2)])"".zip["XVI","CLX","MDC","  M"].map(read.(:[])).take 4.(++"000").reverse=<<getLine
r=replicate
a x=div(mod x 5)4
Community
  • 1
  • 1
R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
0

Real simple: pass the query to Google and screenscrape the answer. Next. :p

BTW, shouldn't this be a community wiki?

AnonJr
  • 2,759
  • 1
  • 26
  • 39
  • Yes - have changed to community mode. If you can write said screenscraper (and keep it short obviously) then go for it! – user4812 Dec 27 '08 at 02:52
  • It's not so simple. Google rejects queries that don't appear to come from a standard browser. Moreover, the resulting HTML is a mess. You won't be happy with regular expressions. – Federico A. Ramponi Dec 27 '08 at 03:38
  • 3
    google_roman() { lynx -dump http://google.com/search?q=$1+in+roman \ |awk "/^$1 = /{print \$3}"; }; google_roman 4999 – system PAUSE Apr 03 '09 at 15:36
0

Java: 286 significant characters

public class R {

    String[]x="M,CM,D,C,XC,L,X,IX,V,I".split(",");
    int[]n={1000,900,500,100,90,50,10,9,5,1};

    String p(String s,int d,int i){return 10<=i?s:n[i]<=d?p(s+x[i],d-n[i],i):p(s,d,i+1);}

    public static void main(String[] a) {
        System.out.println(new R().p("",Integer.parseInt(a[0]),0));
    }

}

By "significant characters", I mean the printing characters and required spaces (e.g. between type and argument), but not pure cosmetic whitespace (newlines and indentation).

joel.neely
  • 30,725
  • 9
  • 56
  • 64
0

Delphi (or Pascal, there's nothing Delphi-specific here):

Function ToRoman(N : Integer) : String;

Const
    V : Array [1..13] of Word = (1000,900,500,400,100,90,50,40,10.9,5,4,1);
    T : Array [1..13] of String = ('M','CM','D','CD','C','XC','L','XL','X','IX','V','I');

Var I : Word;

Begin
    I := 1;
    Repeat
        While N < V[I] do Inc(I);
        Result := Result + T[I];
        N := N - V[I];
    Until N = 0;
End;

How is everyone getting the character counts? (I count 8 essential spaces, all the rest are simply for formatting.)

Loren Pechtel
  • 8,945
  • 3
  • 33
  • 45
  • Some text editors, like vi, tell you how many bytes are in the file. Or, you can use wc. No comments about what tools are available in non-Unix platforms though. :-P – C. K. Young Dec 27 '08 at 05:54
0

Here is a C solution in 252 meaningful chars. Valid from 0 <= i < 4000. Mostly I wrote this because so many solutions include IV and IX at array points. Decoding it: t is our temp buffer that we back fill so that we don't have to reverse it on output. The buffer passed in must be at least 16 chars (for 3888 -> MMMDCCCLXXXVIII).

 char* i2r(int i, char* r) {
     char t[20];
     char* o=t+19;*o=0;
     char* s="IVXLCDMM";
     for (char*p=s+1;*p&&i;p+=2) {
         int x=i%10;
         if (x==9) {*--o=p[1];*--o=p[-1];}
         else if (x==4) {*--o=*p;*--o=p[-1];}
         else {
             for(;x&&x!=5;--x)*--o=p[-1];
             if(x)*--o=*p;
         }
         i/=10;
     }
     return strcpy(r,o);
 }

And I always forget to put the main on. So much for 252 chars:

 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 void main(int a,char**v){
     char buf[16];
     printf("%s\n",i2r(atoi(v[1])));
 }
jmucchiello
  • 18,754
  • 7
  • 41
  • 61
  • You can in fact lose characters by using main() instead of a function. Remember you can use K&R-style C, and omit your #include's. – strager Dec 27 '08 at 06:24
0

Language: C, Char count: 195

Based heavily off of me.yahoo.com/joe_mucchielle's C solution:

char t[99],*o=t+99,*s="IVXLCDMM",*p,x;n(v){*--o=p[v];}main(int i,int**v){i=atoi(v[1]);*o=0;
for(p=s+1;*p&&i;p+=2){x=i%10;if(x%5==4)n(x==9),n(-1);else{for(;x%5;--x)n(-1);if(x)n(0);}i/=10;}puts(o);}
Community
  • 1
  • 1
strager
  • 88,763
  • 26
  • 134
  • 176
0

Language: Erlang, Char count: 222

EDIT2: Erlang preprocessor allows some sort of unbalanced macros so this version is 9 chars shorter.

-module(n2).
-export([y/1]).
-define(D(V,S),n(N)when N>=V->[??S|n(N-V)];).
y(N)->io:format(n(N)).
?D(1000,M)?D(900,CM)?D(500,D)?D(400,CD)?D(100,C)?D(90,XC)?D(50,L)?D(40,XL)?D(10,X)?D(9,IX)?D(5,V)?D(4,IV)?D(1,I)n(0)->[10].

EDIT: Shorter version inspired by Darius version (231 chars)

-module(n).
-export([y/1]).
y(N)->io:format([n(N),10]).
n(N)when N>9->[Y||C<-n(N div 10),{K,Y}<-lists:zip("IVXLC","XLCDM"),K==C]++o(N rem 10);n(N)->o(N).
o(N)->lists:nth(N+1,[[]|string:tokens("I II III IV V VI VII VIII IX"," ")]).

It's less readable but save 2 chars (233 chars).

-module(n).
-export([y/1]).
-define(D(V,S),n(N)when N>=V->[??S|n(N-V)]).
y(N)->io:format(n(N)).
?D(1000,M);?D(900,CM);?D(500,D);?D(400,CD);?D(100,C);?D(90,XC);?D(50,L);?D(40,XL);?D(10,X);?D(9,IX);?D(5,V);?D(4,IV);?D(1,I);n(0)->[10].

Command line version:

-module(n).
-export([y/1]).
-define(D(V,S),n(N)when N>=V->[??S|n(N-V)]).
y([N])->io:format(n(list_to_integer(N))),init:stop().
?D(1000,M);?D(900,CM);?D(500,D);?D(400,CD);?D(100,C);?D(90,XC);?D(50,L);?D(40,XL);?D(10,X);?D(9,IX);?D(5,V);?D(4,IV);?D(1,I);n(0)->[10].

Invocation:

$ erl -noshell -noinput -run n y 2009
MMIX

EDIT: I saved 17 chars using literal macro expansion.

Community
  • 1
  • 1
Hynek -Pichi- Vychodil
  • 26,174
  • 5
  • 52
  • 73
0

Railo CFML - 53 chars, 46 without whitespace...

<cfoutput>
    #NumberFormat( N , 'roman' )#
</cfoutput>


Or, for other CF engines, not sure if these are shortest, but they'll do for now...


CFML - 350..453 characters:

<cffunction name="RomanNumberFormat">
    <cfset var D = ListToArray('M,CM,D,C,XC,L,X,IX,V,IV,I') />
    <cfset var I = [1000,900,500,100,90,50,10,9,5,4,1] />
    <cfset var R = '' />
    <cfset var x = 1 />
    <cfset var A = Arguments[1] />
    <cfloop condition="A GT 0">
        <cfloop condition="A GTE I[x]">
            <cfset R &= D[x] />
            <cfset A -= I[x] />
        </cfloop>
        <cfset x++ />
    </cfloop>
    <cfreturn R />
</cffunction>

<cfoutput>
    #RomanNumberFormat(N)#
</cfoutput>


CFScript - 219..323 characters:

<cfscript>
    function RomanNumberFormat(A)
    {
        var D = ListToArray('M,CM,D,C,XC,L,X,IX,V,IV,I');
        var I = [1000,900,500,100,90,50,10,9,5,4,1];
        var R = '';
        var x = 1;
        while ( A > 0 )
        {
            while( A >= I[x] )
            {
                R &= D[x];
                A -= I[x];
            }
            x++;
        }
        return R;
    }

    WriteOutput( RomanNumberFormat(N) );
</cfscript>
Peter Boughton
  • 110,170
  • 32
  • 120
  • 176
0

Haskell, 245 charaters.

roman = numeral [(1000,"M"),(900,"CM"),(500,"D"),(400,"CD"),(100,"C"),(90,"XC"),
    (50,"L"),(40,"XL"),(10,"X"),(9,"IX"),(5,"V"),(4,"IV"),(1,"I")]
numeral [] n = ""
numeral ((m,c):xs) n = concat (replicate (n `div` m) c) ++ numeral xs (n `mod` m)
keiter
  • 3,534
  • 28
  • 38