17

単一のコマンド ライン引数 N を取り、対応するローマ数字を出力するプログラムを作成します。

たとえば、N = 2009 は MMIX を出力する必要があります。

これが 0 < N < 3000 で機能するとしましょう。

(クリスマス エディションでコード ゴルフの初めてのラウンドを楽しんで、これは新年に合うと思いました。これが他の場所で前に出てきたかどうかを確認するためにグーグルで検索しましたが、そうではないようですが、これがあれば教えてください難しすぎる、簡単すぎる、またはルールを変更する必要がある場合。)

ハッピーMMIX!

4

31 に答える 31

17

Perl: 69 ストローク (数えてみてください!)

最初に perl を呼び出すことを含む69 回のストローク:

$ perl -ple's!.!($#.=5x$&*8%29628)=~y$IVCXL4620-8$XLMCDIXV$d!eg;last}{'
3484
MMMCDLXXXIV
  • 1 行を読み取り、1 行を書き込みます。
  • 0 から 3999 までの範囲で機能します。(0 の場合は空の文字列を出力します。)
  • Perl のゴルフ競技では、これは通常 62 ストローク = コードの 58 + スイッチの 4 として採点されます。
  • なぜ、はい、それら中括弧の不一致です。質問してくれてありがとう。=)

クレジット: 元はTon Hospelによるものです。中括弧の不一致に関するトリックはrev.plこの投稿にあります(ちなみに、これは独創的です)。

于 2009-01-14T21:46:32.147 に答える
14

C# では、次の拡張メソッドとして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();
    }
}

真のローマ数字であるためには、アンダースコアをそれぞれの文字の上にオーバーラインにする必要があります。

于 2008-12-27T02:49:21.317 に答える
11

Common Lisp (SBCL)。「wc -c」で数えた63文字。

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

これは 3999 までの数字に対してのみ機能します。

于 2008-12-27T02:55:21.337 に答える
6

C#: 179 文字 (スペース/タブを除く)

    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;
    }
于 2008-12-27T03:49:49.913 に答える
5

言語: JavaScript .

書式設定を追加しない場合の 129 文字

pl.comp.lang.javascript次のコードは、数年前にニュースグループで行われたコーディングクイズの結果です。私はコードの作者ではありません。

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
}

Elusによる元の投稿

于 2008-12-27T10:35:55.697 に答える
5

パール、19ストローク。1 ~ 12 の値で動作することが保証されています。

sub r{chr 8543+pop}
于 2008-12-27T03:10:38.887 に答える
4

言語: C、文字数: 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)}
于 2008-12-27T20:33:53.553 に答える
4

Python、173 バイト。

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]))

(このアルゴリズムは Gimpel's Algorithms in Snobol4で初めて見ました。Snobol はそれをよりエレガントに表現しました。)

于 2008-12-27T08:28:29.820 に答える
3

シンプルなHaskellバージョンであり、それでも明快さを保ちます。空白を含む205文字。

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)
于 2010-10-27T13:07:56.800 に答える
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'

行を入力すると、同等のローマ数字が表示されます。この最初のバージョンでは、複数の行を入力することさえできます。

これは、1 行でのみ機能し、エッジ ケースを無視する短いバージョンです。の代わりになり4ます。IIIIIV

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'

最初のバージョンを Perl スクリプトとして表示すると、次のようになります。

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;
}
于 2008-12-27T05:57:25.460 に答える
3

パイク

60 文字、有効範囲は 0 ~ 10000:

int main (int c, array a) {
    write(String.int2roman((int)a[1]));
}
于 2008-12-27T06:14:18.907 に答える
2

私はHaskellの専門家ではなく、これは長すぎて勝者にはなりませんが、オイラー#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')
于 2009-07-04T18:59:31.393 に答える
2

Perl、145 ストローク (オプションのすべての改行を取り除いた場合)、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

を使用できると言う人もいますが、ここには 対応の Perl バージョンsayがありません。作品sayを使用する場合は、画数から自由に 2 を引いてください。say:-)

Perl を使用しないプログラマーにとって、このプログラムは多くの便利な Perl 機能を利用します。

  1. ハッシュは、偶数の長さのリストから構築されます。
  2. 文字列のリストは、 を使用してコンパクトな構文で指定できますqw
  3. <=>キーの並べ替えの比較演算子で使用されるように、文字列は整数に自動変換できます。
  4. x文字列/リストのコピーを作成する演算子があります。残念ながら、ここでゴルフをする場合は、 ;xと同じ優先順位があります。/より高い場合/、ブラケットもオプションでした。
于 2008-12-27T05:41:38.537 に答える
2

ルビー、136文字

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
于 2009-01-02T10:27:42.777 に答える
2

J、20キャラ!

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

使用法:

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

引き算がうまくできませんが、かなりクールです。

説明;

(7$5 2)

これは正しい引数 ( list 5 2) を取り、それをサイズ 7 のリスト、つまり に変換します5 2 5 2 5 2 5

(7$5 2)#: 2009

これは「アンチベース」操作を行います - 基本的に反復的な div および mod 操作を行い、 list を返します2 0 0 0 0 0 1 4

次に#~、前のリストを集計として使用して、対応する文字を から引き出し'MDCLXVI'ます。

于 2010-04-15T17:13:27.337 に答える
2

言語: dc (シェル経由) 文字数:122

編集: q は 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:メインループスタック操作を最適化することにより、さらに2文字

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

編集:2文字を保存

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

前のバージョン:

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
于 2008-12-27T10:22:27.487 に答える
2

Python の場合 - ActiveState (クレジット: Paul Winkler) から取得し、少し圧縮したもの:

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
于 2008-12-27T03:05:31.830 に答える
1

Excel 8 文字 (数字を含まない):

=ローマン(N)

3000まで動作します。

頬の舌

于 2010-11-29T16:11:54.930 に答える
1

Python、190 バイトFederico経由のActiveStateからのスニペットに基づいています。

いくつかの小さな最適化: 余分な int() 呼び出しの削除、配列を取得するための文字列の分割、空白の削除、...

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

編集:余分で、スプリアスではなく、範囲チェックを削除します-Chrisdreevesに感謝します! balabasterからインラインでシンボル配列を使用するというアイデアを盗みました。

于 2008-12-27T03:44:37.443 に答える
1

VB: 193 文字

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
于 2008-12-27T03:56:56.173 に答える
1

LPC (Pike の前身) と呼ばれる漠然と C に似た言語から:

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;
}
于 2008-12-27T02:50:25.417 に答える
0

Haskell、245文字。

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)
于 2010-11-29T17:24:54.733 に答える
0

言語: C、文字数: 195

me.yahoo.com/joe_mucchielleの C ソリューションに大きく基づいています:

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);}
于 2008-12-27T07:35:54.873 に答える
0

C# (.NET 4 RC で実行) では、335 文字 (余分な書式を削除した場合)。

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)));
    }
}

現在の C# の最良の回答 (182 文字) に勝るものはないことはわかっていますが、これは大きな LINQ ワンライナーの 1 つにすぎません。単一の LINQ クエリとして記述された raytracer を見た後、私はこの観点からコード ゴルフに取り組み始めました。

このアプローチは機能的であるため、同じアルゴリズムの Haskell バージョンに取り組んでいます (確実に短くなります)。

于 2010-03-05T07:49:27.067 に答える
0

Java: 有効文字数 286 文字

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));
    }

}

「重要な文字」とは、印刷文字と必要なスペース (型と引数の間など) を意味しますが、純粋な装飾的な空白 (改行とインデント) は意味しません。

于 2008-12-27T05:09:59.143 に答える
0

Delphi (または Pascal、ここには Delphi 固有のものは何もありません):

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;

みんなはどうやって文字数を数えているの?(私は 8 つの重要なスペースを数えます。残りはすべてフォーマット用です。)

于 2008-12-27T05:51:30.277 に答える
0

言語: Erlang、文字数: 222

EDIT2: Erlang プリプロセッサはある種の不均衡なマクロを許可するため、このバージョンは 9 文字短くなっています。

-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].

編集:ダライアスバージョンに触発された短いバージョン(231 文字)

-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"," ")]).

読みにくいですが、2 文字 (233 文字) 節約できます。

-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].

コマンド ライン バージョン:

-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].

呼び出し:

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

編集: リテラル マクロ展開を使用して 17 文字を保存しました。

于 2008-12-27T09:45:10.977 に答える
0

これは、意味のある 252 文字の C ソリューションです。0 <= i < 4000 から有効です。多くのソリューションには配列ポイントに IV と IX が含まれているため、ほとんどの場合、これを書きました。デコード: t は、出力時に逆にする必要がないように、バックフィルする一時バッファーです。渡されるバッファーは、少なくとも 16 文字でなければなりません (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);
 }

そしていつもメインを載せるのを忘れてしまう。252文字でこれだけです:

 #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])));
 }
于 2008-12-27T06:11:16.820 に答える
0

私のC#/ LINQ回答のHaskellバージョン、234文字:

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
于 2010-03-05T09:07:36.190 に答える
0

本当に簡単です。クエリを Google に渡し、回答をスクリーンスクレイピングするだけです。次。:p

ところで、これはコミュニティ ウィキではないでしょうか。

于 2008-12-27T02:41:56.540 に答える
0

Railo CFML - 53 文字、空白なしで 46 文字...

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


または、他のCFエンジンの場合、これらが最短かどうかはわかりませんが、今のところそうです...


CFML - 350..453 文字:

<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 文字:

<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>
于 2009-01-02T22:49:06.857 に答える