ローマ数字で1から100までカウントします…


29

ローマ数字で1から100までカウントするプログラムを作成し、これらの数値を標準出力で出力します。数字はそれぞれスペースで区切る必要があります。

組み込み関数を使用してローマ数字に変換したり、外部アプリケーションやライブラリを変換することはできません。

望ましい結果は

I II III IV V VI VII VIII IX X XI XII XIII XIV XV XVI XVII XVIII XIX XX XXI XXII XXIII XXIV XXV XXVI XXVII XXVIII XXIX XXX XXXI XXXII XXXIII XXXIV XXXV XXXVI XXXVII XXXVIII XXXIX XL XLI XLII XLIII XLIV XLV XLVI XLVII XLVIII XLIX L LI LII LIII LIV LV LVI LVII LVIII LIX LX LXI LXII LXIII LXIV LXV LXVI LXVII LXVIII LXIX LXX LXXI LXXII LXXIII LXXIV LXXV LXXVI LXXVII LXXVIII LXXIX LXXX LXXXI LXXXII LXXXIII LXXXIV LXXXV LXXXVI LXXXVII LXXXVIII LXXXIX XC XCI XCII XCIII XCIV XCV XCVI XCVII XCVIII XCIX C

それはコードゴルフの挑戦なので、最短のコードが勝ちます。


4
39はX.が不足している
トール

@Thor固定、感謝;)
アベロエス

1
私は本当にこれにINTERCALを使いたいです。
ウェイジュン周

改行で区切ることはできますか?また、末尾/先頭のスペース/改行についてはどうですか?
FantaC

回答:


68

Perl 69バイト

s;.;y/XVI60-9/CLXVIX/dfor$a[$_].="32e$&"%72726;gefor 1..100;print"@a"

魔法の式で動作します。式"32e$&"%72726は、次の方法で各桁を変換します:
0⇒32、1⇒320、2⇒3200、3⇒32000、4⇒29096、5⇒56、6⇒560、7⇒5600、8⇒56000、9⇒50918

翻訳を適用した後y/016/IXV/、我々は、この代わりに:
0⇒32、1⇒32 I、2⇒32 II、3⇒32 III、4⇒29 I 9 V、5⇒5 V、6⇒5 VI、7⇒5 VII、8⇒5 VIII、9⇒5 I 9 X 8

残りの数字(2-57-9)は削除されます。この変換式使用して1つのバイトによって改善され得ることに注意012の代わりを016簡素化/XVI60-9/します/XVI0-9/。私はそれを見つけることができませんでしたが、多分あなたはより良い運を持っているでしょう。

この方法で1つの数字が変換されると、次の数字についてプロセスが繰り返され、結果が追加され、新しい数字の変換が行われると同時に前XVICLXが変換されます。

更新
検索では、短いものは何も見つかりませんでした。ただし、69バイトの代替ソリューションを見つけました。

s;.;y/XVI0-9/CLXIXV/dfor$a[$_].="57e$&"%474976;gefor 1..100;print"@a"

これはの0-2置換を使用しますIXVが、モジュロが1桁長くなります。


更新:66 65バイト

このバージョンは著しく異なっているので、おそらくそれについていくつかの言葉を言う必要があります。使用する式は実際には1バイト長くなります!

それ以上に式を短くすることができなかったので、私は自分が持っていたものをゴルフダウンすることにしました。私は昔の友達を思い出すまで長くはかからなかった$\。ときprintなステートメントが発行され、$\自動的に出力の最後に追加されます。$a[$_]2バイトの改善のために、厄介な構成を取り除くことができました。

s;.;y/XVI60-9/CLXVIX/dfor$\.="32e$&"%72726;ge,$\=!print$"for 1..100

はるかに優れていますが、$\=!print$"それでも少し冗長に見えます。3それから、桁変換のいずれにも番号が含まれていない代替の等しい長さの式を思い出しました。したがって、$\=2+print代わりに使用して、結果3をスペースに置き換えることができるはずです:

s;.;y/XVI0-9/CLXIIX V/dfor$\.="8e$&"%61535;ge,$\=2+print for 1..100

また、printとの間の必要な空白のために、67バイトfor

編集:これはprint、先頭に移動することにより、1バイト改善することができます:

$\=2+print!s;.;y/XVI0-9/CLXIIX V/dfor$\.="8e$&"%61535;gefor 1..100

置換はの前に完全に評価する必要があるため、へprintの割り当て$\は最後に行われます。geとの間の空白を削除するとfor、非推奨の警告が発行されますが、それ以外は有効です。

使用しなかった式があった場合でも、1どこでも、$\=2+printとなり$\=print貯蓄の別の2バイト分のために。1バイト長くても、改善されます。

結局のところ、そのような式は存在しますが、元の式よりも1バイト長く、最終的なスコアは65バイトになります

$\=print!s;.;y/XVI60-9/CLXXI V/dfor$\.="37e$&"%97366;gefor 1..100

方法論

このような式を見つけるにはどうすればよいかという質問がありました。一般に、データのセットを一般化するための魔法の公式を見つけることは確率の問題です。つまり、目的の結果に似たものを生成する可能性の高いフォームを選択する必要があります。

最初のいくつかのローマ数字を調べる:

0:
1: I
2: II
3: III
4: IV
5: V
6: VI
7: VII
8: VIII
9: IX

いくつかの規則性が見られます。具体的には、0〜3から5〜8まで、連続する各用語の長さが1桁ずつ増加します。我々は数字の桁からのマッピングを作成したい場合は、私たちは、表現したいでしょうまた、それぞれの連続した期間のために一桁の長さの増加を。論理的な選択であるK•10 D dは、対応する数字であり、そしてK任意の整数定数です。

これは0〜3で機能しますが、4はパターンを壊す必要があります。ここでできることは、モジュロのタックです:
k•10 d%m、ここでmk•10の間です 3 k•10 4の間です。これにより、 0〜3の範囲はそのままになり、 4が含まれないように 4が変更されIます。モジュラー剰余 5 jと呼ぶ)が m / 1000未満になるように検索アルゴリズムをさらに制約する場合、これにより 5-8からの規則性も確保されます。結果は次のようになります。

0: k
1: k0
2: k00
3: k000
4: ????
5: j
6: j0
7: j00
8: j000
9: ????

あなたが見ることができるように、我々は交換した場合0I0-35-8は、すべて正しくマップされることが保証されます!ただし、49の値はブルートフォースにする必要があります。具体的には、4は1 0と1をj(この順序で)含む必要があり、9は1を含む必要があり0、その後に他のどこにも現れない1つの数字が続きます。確かに、他の多くの式があり、偶然の一致によって望ましい結果が得られる可能性があります。それらのいくつかはさらに短いかもしれません。しかし、これほど成功する可能性のあるものはないと思います。

私はまたのために複数の代替品で実験Iおよび/またはVいくつかの成功を収めて。しかし、悲しいかな、私がすでに持っていたものよりも短いものはありません。ここに私が見つけた最短のソリューションのリストがあります(1〜2バイト重いソリューションの数はリストするには多すぎます)。

y/XVI60-9/CLXVIX/dfor$\.="32e$&"%72726
y/XVI0-9/CLXIXV/dfor$\.="57e$&"%474976
y/XVI0-9/CLXIVXI/dfor$\.="49e$&"%87971

y/XVI0-9/CLXIIXIV/dfor$\.="7e$&"%10606  #
y/XVI0-9/CLXIIXIV/dfor$\.="7e$&"%15909  # These are all essentially the same
y/XVI0-9/CLXIIXIV/dfor$\.="7e$&"%31818  #

y/XVI0-9/CLXIIX V/dfor$\.="8e$&"%61535  # Doesn't contain 3 anywhere

y/XVI60-9/CLXXI V/dfor$\.="37e$&"%97366 # Doesn't contain 1 anywhere

3
どのようにして魔法の式を見つけましたか?
ルーベンバーボル

1
@RubenVerborgh方法論に関する詳細な情報を掲載した投稿をすぐに更新します。
primo

15

HTML + JavaScript + CSS(137)

HTML(9)

<ol></ol>

JavaScript(101)

for(i=1;i<=100;i++){document.getElementsByTagName('ol')[0].appendChild(document.createElement('li'))}

CSS(27)

ol{list-style:upper-roman​}

出力

ローマ数字付きの番号付きリスト

...

JSBinのデモ


1
81バイトのJS専用バージョン:document.write('<ol>'+"<li style='list-style:upper-roman'/>".repeat(100)+'</ol>')(ES6)
Paperjam

またはChromeで66document.write("<li style='list-style:upper-roman'/>".repeat(100))
Slai

10

Python 116

スクリーバーの答えのより良いゴルフコード:

r=lambda a,b,c:('',a,2*a,3*a,a+b,b,b+a,b+a+a,b+3*a,a+c);print' '.join(i+j for i in r(*'XLC')for j in r(*'IVX'))+' C'

8

Python、139

print' '.join(' '.join(i+j for  j in ' _I_II_III_IV_V_VI_VII_VIII_IX'.split('_'))for i in ' _X_XX_XXX_XL_L_LX_LXX_LXXX_XC'.split('_'))+' C'

6

C、177の 160 147文字

短い解決策がありますが、Cにはありませんので、ここで試してみます。

以前のソリューションとはまったく異なる新しいソリューション:

char*c;
f(n){
    printf("%.*s",n%5>3?2:n%5+n/5,c+=n%5>3?n%4*4:2-n/5);
}
main(i){
        for(;i<100;putchar(32))
                c="XLXXXC",f(i/10),
                c="IVIIIX",f(i++%10);
        puts("C");
}

以前のソリューション(160文字):

ロジック:
1. f1〜10の数字を出力します。c使用される数字は、IVXまたはXLCです。十代のために一回呼び出されます。
2. n%5==0If-何も印刷しないかc[n/5]Iorまたはor V(or LまたはC)です。
3.もしn%4==4- 4または9-印刷I(またはX)、によってn+1
4.もしn>4-プリント5(すなわちVまたはL)、その後n-5
5. n<4If- I次に印刷しますn-1(つまり、nI)。

char*c;
p(c){putchar(c);}
f(n){
        n%5?
                n%5>3?
                        f(1),f(n+1):
                        n>4?
                                f(5),f(n-5):
                                f(n-1,p(*c)):
                n&&p(c[n/5]);
}
main(i){
        for(;++i<101;p(32))
                c="XLC",f(i/10),
                c="IVX",f(i%10);
        p(10);
}

137:f(c,n){printf("%.*s",n%5>3?2:n%5+n/5,"XLXXXCIVIIIX "+c+(n%5>3?n%4*4:2-n/5));}main(i){for(;i<100;f(12,4))f(0,i/10),f(6,i++%10);puts("C");}
ガストプナー

5

JavaScript、123

長いバージョンに触発されて、ポーランド語のニュースグループで出会いました(少なくとも、Chromeはそれがポーランド語だと思っていました)。

for(i=100,a=[];n=i--;a[i]=r)
  for(r=y='',x=5;n;y++,x^=7)
    for(m=n%x,n=n/x^0;m--;)
      r='IVXLC'[m>2?y+n-(n&=-2)+(m=1):+y]+r;
alert(a)

5

Q(81 80)

2番目のカット:

1_,/'[($)``X`XX`XXX`XL`L`LX`LXX`LXXX`XC cross``I`II`III`IV`V`VI`VII`VIII`IX],"C"

最初のカット:

1_,/'[$:[``X`XX`XXX`XL`L`LX`LXX`LXXX`XC cross``I`II`III`IV`V`VI`VII`VIII`IX]],"C"

4

Python、168

r=lambda n,l,v:(r(n,l[1:],v[1:])if n<v[0]else l[0]+r(n-v[0],l,v))if n else''
for i in range(1,101):print r(i,'C XC L XL X IX V IV I'.split(),[100,90,50,40,10,9,5,4,1]),

説明

これらの値を使用して、n以下の最大値を取得し、nから減算します。nが0になるまで繰り返します。

'C'  = 100
'XC' = 90
'L'  = 50
'XL' = 40
'X'  = 10
'IX' = 9
'V'  = 5
'IV' = 4
'I'  = 1

1
r=lambda n,l,v:n and(n<v[0]and r(n,l[1:],v[1:])or l[0]+r(n-v[0],l,v))or""2文字を保存します。そうでなければ非常にいい。
cemper93

4

ルビー1.9、140 132

r=" "
100.times{r+=?I
0while[[?I*4,"IV"],["VIV","IX"],[?X*4,"XL"],["LXL","XC"],[/(.)((?!\1)[^I])\1/,'\2']].any?{|q|r.sub! *q}
$><<r}

これは、文字通りローマ数字で1から100までカウントします。空白の文字列で始まり、「I」を追加してループし、一連の置換ルールを繰り返し適用して、1を効果的に追加します。

編集:?I1.9でのみ動作するため、バージョン番号を追加し、@ Howardの変更を使用して一部の文字をトリミングしました。


2つの文字を保存できます:r while-> 0whiler.sub!(*q)-> r.sub! *q。ループ内でprintをドラッグして100.times{...}、mapステートメントの代わりに使用することもできます。
ハワード

(%w[IIII VIV XXXX LXL]<</(.)((?!\1)[^I])\1/).zip(%w(IV IX XL XC)<<'\2')7文字節約します。
steenslag

4

ルビー112文字

101.times{|n|r=' ';[100,90,50,40,10,9,5,4,1].zip(%w(C XC L XL X IX V IV I)){|(k,v)|a,n=n.divmod k;r<<v*a};$><<r}

基本的にここ説明したto_romanメソッドを使用しますが、簡潔にするために圧縮配列を使用します。


4

Mathematica 159 150 142

c = {100, 90, 50, 40, 10, 9, 5, 4, 1};
Table["" <> Flatten[ConstantArray @@@ Thread@{StringSplit@"C XC L XL X IX V IV I", 
  FoldList[Mod, k, Most@c]~Quotient~c}], {k, 100}]

ローマ数字


組み込みソリューションIntegerString、38文字

IntegerString[k, "Roman"]~Table~{k, 100}

2

perl 205

@r = split //, "IVXLC";
@n = (1, 5, 10, 50, 100);

for $num (1..100) {
  for($i=@r-1; $i>=0; $i--) {
    $d = int($num / $n[$i]);
    next if not $d;
    $_ .= $r[$i] x $d;
    $num -= $d * $n[$i];
  }
  $_ .= " ";
}
s/LXXXX/XC/g;
s/XXXX/XL/g;
s/VIIII/IX/g;
s/IIII/IV/g;
print;

ゴルフ:

@r=split//,"IVXLC";@n=(1,5,10,50,100);for$num(1..100){for($i=@r-1;$i>=0;$i--){$d=int($num/$n[$i]);next if!$d;$_.=$r[$i]x$d;$num-=$d*$n[$i];}$_.=" ";}s/LXXXX/XC/g;s/XXXX/XL/g;s/VIIII/IX/g;s/IIII/IV/g;print;

2

ムンプス184

S V(100)="C",V(90)="XC",V(50)="L",V(40)="XL",V(10)="X",V(9)="IX",V(5)="V",V(4)="IV",V(1)="I" F I=1:1:100 S S=I,N="" F  Q:'S  S N=$O(V(N),-1) I S&(S'<N ) S S=S-N W V(N) S N="" w:'S " "

@cardboard_boxと同じアルゴリズム。説明の元になったもの-

説明

これらの値を使用して、n以下の最大値を取得し、nから減算します。nが0になるまで繰り返します。

'C'  = 100
'XC' = 90
'L'  = 50
'XL' = 40
'X'  = 10
'IX' = 9
'V'  = 5
'IV' = 4
'I'  = 1

2

R、85バイト

R=.romans
for(r in 1:100){while(r>0){cat(names(R[I<-R<=r][1]))
r=r-R[I][1]}
cat(" ")}

オンラインでお試しください!

ランダムutilsパッケージ変数.romansを使用してローマ数字のを取得しますが、変換はそれ自体で行います。組み込みのアプローチは20バイトになります。cat(as.roman(1:100))


驚いたことに、あなたが言及している組み込みのアプローチはそのままでは機能しません... 1つcat(paste(as.roman(1:100)))または単に入力する必要がありますas.roman(1:100)。奇妙な。
JayCe

@JayCe奇数; 私は実際にそれをテストしていないはずです...ドキュメントcatは、それがベクトルよりも少ない変換を実行しprintatomicベクトルでのみ動作することを示すため、これを説明しています!
ジュゼッペ

1

APL 128

APLでインデックス作成ソリューションを試しました。

r←⍬                                                                             
i←1                                                      
l:r←r,' ',('   CXI LV CX'[,⍉((1+(4 4 2 2⊤0 16 20 22 24 32 36 38 39 28)[;1+(3⍴10)⊤i])×3)-4 3⍴2 1 0])~' '
→(100≥i←i+1)/l                                                                  
r              

インデックスの起点は1ではなく4バイト短くなる可能性がありますが、実空間の占有は以下を介したインデックスマトリックスの生成です。

4 4 2 2⊤0 16 20 22 24 32 36 38 39 28

これまでのところ、その場でインデックスを生成することはできませんでした!


1

ラテックス(138)

\documentclass{minimal}
\usepackage{forloop}
\begin{document}
\newcounter{i}
\forloop{i}{1}{\value{i} < 101}{\roman{i}\par}
\end{document}

1
-1:質問は「あなたはローマ数字に変換する機能で構築されたいずれかを使用することはできません」と言う
izabera

1

Python、125

' '.join(i+j for i in['']+'X XX XXX XL L LX LXX LXXX XC C'.split()for j in['']+'I II III IV V VI VII VIII IX'.split())[1:-38]


1

VBA(Excel)、245バイト

反復および置換用に作成された関数-91 バイト

Function s(a,b):s=String(a,b):End Function Function b(x,y,z):b=Replace(x,y,z):End Function

イミディエイトウィンドウを使用(154バイト

p="I":for x=1to 100:?b(b(b(b(b(b(b(b(s(x,p),s(100,p),"C"),s(90,p),"XC"),s(50,p),"L"),s(40,p),"XL"),s(10,p),"X"),s(9,p),"IX"),s(5,p),"V"),s(4,p),"IV"):next


0

Java(OpenJDK 8)、152バイト

a->{String[] t=",X,XX,XXX,XL,L,LX,LXX,LXXX,XC,,I,II,III,IV,V,VI,VII,VIII,IX".split(",");for(int i=1;i<100;i++){a+=t[i/10]+t[i%10+10]+" ";}return a+"C";}

オンラインでお試しください!

説明:

String[] t=",X,XX,XXX,XL,L,LX,LXX,LXXX,XC,,I,II,III,IV,V,VI,VII,VIII,IX".split(",");
//Create an array of numerals, first half represents tens place, second half represents ones place
    for(int i=1;i<100;i++){             
//Loop 99 times
        a+=t[i/10]+t[i%10+10]+" ";   
//Add tens place and ones place to the string
    }return a+"C";                         
//Add numeral for 100 and return the string

0

TeX、354バイト

\let~\let~\d\def~\a\advance~\b\divide~\x\expandafter~\f\ifnum{~~\newcount~\n~\i~\j~\k~\u~\v}~~\or\d\p#1{\ifcase#1C~2~L~5~X~2~V~5~I\fi}\d\q#1{\p{#1~}}\d\r{\j0
\v100\d\m{\d\w{\f\n<\v\else\p\j\a\n-\v\x\w\fi}\w\f\n>0\k\j\u\v\d\g{\a\k2\b\u\q\k}\g\f\q\k=2\g\fi\a\n\u\f\n<\v\a\n-\u\a\j2\b\v\q\j\else\p\k\fi\x\m\fi}\m}\i1\d\c{
\f\i<101 \n\i\r\a\i1 \x\c\fi}\c\bye

説明:TeXには、\romannumeral数字をローマ数字に変換するための組み込みコマンドが用意されています。質問では組み込み関数を使用できないため、上記のコードは、Knuthの元のTeXコンパイラーがTeXで再実装\romannumeralTeX:The Program、§69を参照)するために使用するのと同じアルゴリズムのゴルフ版ですprint_roman_int

Knuthは、このコードがどのように機能するかを読者に戸惑う喜びを残したいので、コードのこの部分の説明を拒否します。したがって、私は追随して、上記のコードよりもオリジナルに近い、変更されていないわずかに修正されたバージョンを提供します。

\newcount\n
\newcount\j
\newcount\k
\newcount\u
\newcount\v

\def\chrnum#1{\ifcase#1m\or 2\or d\or 5\or c\or 2\or l\or 5\or x\or 2\or v\or 5\or i\fi}
\def\chrnumM#1{\chrnum{#1\or}}

\def\roman#1{%
    \n=#1\relax
    \j=0\relax
    \v=1000\relax
    \def\mainloop{%
        \def\while{%
            \ifnum\n<\v
            \else
                \chrnum\j
                \advance\n -\v
                \expandafter\while
            \fi
        }\while
        \ifnum\n>0\relax
            \k=\j \advance\k 2\relax
            \u=\v \divide\u \chrnumM\k
            \ifnum\chrnumM\k=2\relax
                \advance\k 2\relax
                \divide\u \chrnumM\k
            \fi
            \advance\n \u
            \ifnum\n<\v
                \advance\n -\u
                \advance\j 2\relax
                \divide\v \chrnumM\j
            \else
                \chrnum\k
            \fi
            \expandafter\mainloop
        \fi
    }\mainloop
}

\newcount\i \i=1
\def\countloop{%
    \ifnum\i<100\relax
        \roman\i\ 
        \advance\i 1
        \expandafter\countloop
    \fi
}\countloop
\bye
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.