로마 숫자로 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

@Thor Fixed, thanks;)
Averroes

1
나는 이것을 위해 INTERCAL을 사용하고 싶습니다.
Weijun Zhou

줄 바꿈으로 구분할 수 있습니까? 또한 후행 / 선행 공백 / 줄 바꿈은 어떻습니까?
FantaC

답변:


68

펄 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/. 하나를 찾지 못했지만 운이 좋을 것입니다.

한자리 이와 같이 형질 전환 된 후, 처리 결과를 추가하고, 변환 이전의 다음 자리에 대해 반복 XVI을들 CLX새 자리에 대한 변환이 발생하는 동시에.

최신 정보
철저한 검색 더 짧은 것이 발견되지 않았습니다. 그러나 대안적인 69 바이트 솔루션을 찾았습니다.

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

이것은 하나를 사용 0-2 대체물을IXV 하지만 한 자리 더 긴 모듈로를 가지고 있습니다.


업데이트 : 66 65 바이트

이 버전은 눈에 띄게 다르므로 아마도 그것에 대해 몇 마디 말해야 할 것입니다. 그것이 사용하는 공식은 실제로 1 바이트 더 길다!

공식을 더 이상 단축시킬 수 없어서 내가 가진 것을 골라 내려고 결심했습니다. 오래 된 친구를 기억할 때까지 오래지 않았다 $\. 때 print한 Statment 발행, $\자동 출력의 끝에 추가된다. $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절감의 또 다른 두 바이트의 가치에 대해. 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 3k • 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: ????

당신이 볼 수 있듯이, 우리가 바꿀 경우 0I, 0-35-8은 모든 올바르게 매핑이 보장된다! 49 의 값은 무차별 적이어야합니다. 구체적으로, 4 는 1 0과 1 j을 순서대로 포함해야 하고 9 는 1을 포함해야합니다0 그 뒤에 다른 곳에 나타나지 않는 다른 숫자가 있어야합니다. 확실히, 우연의 충돌로 인해 원하는 결과를 얻을 수있는 다른 많은 공식이 있습니다. 그들 중 일부는 더 짧을 수도 있습니다. 그러나 나는 이것만큼 성공할만한 것이 없다고 생각합니다.

또한 여러 번의 교체 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
마법의 공식을 어떻게 찾았습니까?
Ruben Verborgh

1
@RubenVerborgh 나는 방법론에 관한 더 많은 정보로 내 게시물을 업데이트 할 것입니다.
primo December

15

HTML + 자바 스크립트 + CSS (137)

HTML (9)

<ol></ol>

자바 스크립트 (101)

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

CSS (27)

ol{list-style:upper-roman​}

산출

Numbered list with roman numerals

...

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

파이썬 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

파이썬, 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==0-아무것도 인쇄하지 않거나c[n/5] 어떤이 없다 I거나 V(또는 LC).
3. 만약 n%4==4- 4또는 9- 인쇄 I(또는 X)에 의해 n+1.
4. if n>4-print 5(예 : V또는 L) n-5.
5. 만약 n<4- 인쇄 In-1(즉 n시간 I).

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

5

자바 스크립트, 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 차 컷 :

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

4

파이썬, 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""두 문자를 저장합니다. 그렇지 않으면 아주 좋습니다.
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의 변경 사항을 사용하여 일부 문자를 자릅니다.


r while-> 0while, r.sub!(*q)-> 두 문자를 저장할 수 있습니다 r.sub! *q. 루프 내에서 인쇄를 드래그 100.times{...}하여 map 문 대신 사용할 수도 있습니다 .
Howard

(%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

매쓰 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}]

roman numerals


내장 솔루션 : IntegerString, 38 자

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

2

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


그대로 놀랍게도,이 내장 방식이 언급하는 작업을하지 않는 ... 하나의 입력이 cat(paste(as.roman(1:100)))단순히 나 as.roman(1:100). 기묘한.
JayCe

@JayCe 홀수; 실제로 테스트해서는 안됩니다 ... 문서는 벡터 cat보다 변환을 덜 수행 print하고 atomic벡터 에서만 작동 한다는 것을 나타냅니다 .
주세페

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 대신에 인덱스 원점 0에서 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

파이썬, 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

자바 (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 컴파일러가 사용하는 것과 동일한 알고리즘의 골프 버전입니다 \romannumeral( TeX : The Program 참조) .print_roman_int 에서 다시 구현 된 , § 69, ) .

Knuth는이 코드가 독자에게 어떻게 작동하는지 수수께끼의 기쁨을 남기고 자하기 때문에 코드의이 부분에 대한 설명을 거부합니다. 그래서 나는 소송을 따르고 위 코드보다 원본에 더 가까운 ungolfed 및 약간 수정 된 버전을 제공합니다.

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