นับจาก 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 คงที่ขอบคุณ;)
Averroes

1
ฉันต้องการใช้ INTERCAL สำหรับสิ่งนี้จริงๆ
Weijun Zhou

สามารถคั่นด้วยการขึ้นบรรทัดใหม่ได้หรือไม่ ยังเกี่ยวกับการติดตาม / ช่องว่างนำหน้า / การขึ้นบรรทัดใหม่
แฟนต้า

คำตอบ:


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 ฉัน 9 X 8

ส่วนที่เหลือของตัวเลข ( 2-57-9) จะถูกลบออก หมายเหตุว่านี้อาจจะดีขึ้นโดยหนึ่งไบต์โดยใช้สูตรซึ่งแปล012แทนการ016ลดความซับซ้อนของการ/XVI60-9/ /XVI0-9/ฉันไม่สามารถหามันได้ แต่บางทีคุณอาจจะโชคดีกว่า

เมื่อมีการแปลงหนึ่งหลักในลักษณะนี้กระบวนการจะทำซ้ำสำหรับตัวเลขถัดไปเพิ่มผลลัพธ์และการแปลXVIs ก่อนหน้าเป็นCLXพร้อมกันการแปลสำหรับตัวเลขใหม่จะเกิดขึ้น

อัปเดตการ
ค้นหาแบบละเอียดไม่ได้เปิดเผยอะไรที่สั้นลง อย่างไรก็ตามฉันพบโซลูชัน 69 ไบต์ทางเลือก:

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

อันนี้ใช้การ0-2แทนที่IXVแต่มีโมดูโล่ที่ยาวกว่าหนึ่งหลัก


อัปเดต: 66 65 ไบต์

รุ่นนี้มีความแตกต่างอย่างเห็นได้ชัดดังนั้นฉันควรจะพูดสักสองสามคำเกี่ยวกับมัน สูตรที่ใช้จริงนานกว่าหนึ่งไบต์!

ไม่สามารถย่อสูตรให้สั้นลงกว่านี้ได้ฉันตัดสินใจตีกอล์ฟลงในสิ่งที่ฉันมี ไม่นานจนกระทั่งฉันจำเพื่อนเก่าของฉัน$\ได้ เมื่อมีการprintออก$\งบจะถูกผนวกเข้ากับส่วนท้ายของเอาต์พุตโดยอัตโนมัติ ฉันสามารถกำจัดสิ่ง$a[$_]ก่อสร้างที่น่าอึดอัดใจสำหรับการปรับปรุงสองไบต์:

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

ดีขึ้นมาก แต่$\=!print$"ก็ยังดู verbose เล็กน้อย จากนั้นฉันก็จำสูตรทางเลือกความยาวเท่ากันที่ฉันพบซึ่งไม่ได้มีตัวเลข3ในการแปลงหลักใด ๆ ดังนั้นควรใช้$\=2+printแทนและแทนที่ผลลัพธ์3ด้วยช่องว่าง:

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

นอกจากนี้ยังมี 67 ไบต์เนื่องจากช่องว่างระหว่างความจำเป็นและprintfor

แก้ไข : สิ่งนี้สามารถปรับปรุงได้ทีละหนึ่งไบต์โดยเลื่อนprintไปทางด้านหน้า:

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

เนื่องจากการทดแทนจำเป็นต้องประเมินอย่างสมบูรณ์ก่อนprintการมอบหมาย$\จะยังคงเกิดขึ้นครั้งสุดท้าย การลบช่องว่างระหว่างgeและforจะออกคำเตือนการคัดค้าน แต่ไม่ถูกต้อง

แต่ถ้ามีสูตรที่ไม่ได้ใช้1ทุกที่$\=2+printก็จะกลายเป็น$\=printเงินออมสองไบต์ แม้ว่ามันจะยาวกว่าหนึ่งไบต์ แต่ก็ยังเป็นการปรับปรุง

เมื่อปรากฎว่ามีสูตรดังกล่าวอยู่ แต่มีความยาวมากกว่าหนึ่งไบต์หนึ่งไบต์ทำให้ได้คะแนนสุดท้าย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 คำแต่ละคำที่ต่อเนื่องจะเพิ่มขึ้นตามความยาวโดยหนึ่งตัวเลข ถ้าเราต้องการที่จะสร้างแผนที่จากตัวเลขการเลขที่เราต้องการที่จะมีการแสดงออกที่ยังเพิ่มความยาวโดยหนึ่งหลักสำหรับแต่ละระยะต่อเนื่อง ตัวเลือกเชิงตรรกะคือk • 10 dโดยที่dคือตัวเลขที่สอดคล้องกันและkคือค่าคงที่จำนวนเต็มใด ๆ

ใช้งานได้สำหรับ0-3แต่4ต้องแบ่งรูปแบบ เราสามารถทำอะไรที่นี่ตะปูบนโมดูโลคือ:
k • 10 d % mที่ม.เป็นบางระหว่างk • 10 3และk • 10 4 สิ่งนี้จะทำให้ช่วง0-3ไม่ถูกแตะต้องและแก้ไข4เพื่อไม่ให้มีสี่Is หากเรา จำกัด การค้นหาอัลกอริธึมของเราเช่นนั้นสิ่งตกค้างแบบแยกส่วนของ5เราเรียกมันว่าjน้อยกว่าm / 1000นี่จะทำให้มั่นใจได้ว่าเราก็มีความสม่ำเสมอจาก5-8เช่นกัน ผลที่ได้คืออะไรเช่นนี้:

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

ในขณะที่คุณสามารถดูถ้าเราแทนที่0ด้วยI, 0-3และ5-8มีการรับประกันทั้งหมดที่จะแมปได้อย่างถูกต้อง! ค่าสำหรับ4และ9จำเป็นต้องบังคับให้เดรัจฉาน โดยเฉพาะอย่างยิ่ง4จำเป็นต้องมีหนึ่ง0และหนึ่งj(ตามลำดับที่) และ9ต้องมีหนึ่ง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 ฉันจะอัปเดตโพสต์ของฉันพร้อมข้อมูลเพิ่มเติมเกี่ยวกับวิธีการในไม่ช้า
โม่

15

HTML + JavaScript + 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​}

เอาท์พุต

รายการลำดับเลขพร้อมตัวเลขโรมัน

...

ตัวอย่างบน JSBin


1
81 byte JS-only version: document.write('<ol>'+"<li style='list-style:upper-roman'/>".repeat(100)+'</ol>')(ES6)
Paperjam

หรือ 66 ใน Chromedocument.write("<li style='list-style:upper-roman'/>".repeat(100))
Slai

10

Python 116

โค้ด golfed ที่ดีกว่าของคำตอบของ scleaver

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'


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. fพิมพ์ตัวเลขตั้งแต่ 1 ถึง 10 cเป็นตัวเลขที่ใช้ซึ่งสามารถหรือIVX XLCเรียกว่าหนึ่งครั้งสำหรับสิบครั้งสำหรับคน
2. ถ้าn%5==0- พิมพ์อะไรหรือc[n/5]ที่IหรือV(หรือLหรือC)
3. หากn%4==4- 4หรือ9- พิมพ์I(หรือX) n+1โดย
4. ถ้าn>4- พิมพ์5(เช่นVหรือL) n-5แล้ว
5. ถ้าn<4- พิมพ์Iแล้วn-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");}
แกสโทรเนอร์

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)

ตัดครั้งที่สอง:

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

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""บันทึกอักขระสองตัว เป็นอย่างอื่นดีมาก
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 อย่างมีประสิทธิภาพ

แก้ไข: เพิ่มหมายเลขรุ่นเนื่องจาก?Iใช้งานได้ใน 1.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

Ruby 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}]

ตัวเลขโรมัน


โซลูชั่นในตัว : IntegerString38 ตัวอักษร

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

MUMPS 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เพื่อรับค่าของตัวเลขโรมัน แต่ทำการแปลงด้วยตัวเอง วิธีการ builtin จะเป็น 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              

สามารถสั้นลงได้ 4 ไบต์ในดัชนีกำเนิด 0 แทน 1 แต่หมูอวกาศจริงคือการสร้างเมทริกซ์ดัชนีผ่าน:

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

PHP, 38 37 ไบต์

<ol type=I><?=str_repeat("<li>",100);

-1 ไบต์ขอบคุณ @manatwork

แนวคิดเช่นเดียวกับคำตอบของPatrickแต่ในภาษาที่กะทัดรัดกว่า Beats Mathematica !

ลองออนไลน์!


ยุติคำสั่งด้วยแล้วไม่มีความจำเป็นในการ; ?>
จัดการ

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สำหรับการแปลงตัวเลขเป็นตัวเลขโรมัน เนื่องจากคำถามไม่อนุญาตให้ใช้ฟังก์ชั่นในตัวรหัสด้านบนเป็นเวอร์ชั่น golfed ของอัลกอรึทึมแบบเดิมของคอมไพเลอร์ TeX ของ Knuth ที่ใช้สำหรับ\romannumeral(ดูTeX: The Program , § 69, print_roman_int) นำมาใช้ใหม่ใน TeX

ในขณะที่เขาต้องการออกจากความสุขของการทำให้งงว่ารหัสนี้ทำงานอย่างไรกับผู้อ่าน 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.