แปลงทศนิยมซ้ำเป็นเศษส่วน


23

คำถามนี้ไม่จำเป็นต้องใช้กับการยกเลิกทศนิยม - ทศนิยมซ้ำยังสามารถแปลงเป็นเศษส่วนผ่านอัลกอริทึม

งานของคุณคือการสร้างโปรแกรมที่ใช้ทศนิยมซ้ำเป็นอินพุตและส่งออกตัวเศษและส่วนที่เกี่ยวข้อง (ในเงื่อนไขต่ำสุด) ที่สร้างการขยายทศนิยม เศษส่วนมากกว่า 1 9/5ควรจะแสดงเป็นเศษส่วนที่ไม่เหมาะสมเช่น คุณสามารถสันนิษฐานได้ว่าอินพุตนั้นเป็นค่าบวก

ทศนิยมซ้ำจะได้รับในรูปแบบนี้:

5.3.87

กับทุกอย่างหลังจากจุดที่สองซ้ำแล้วซ้ำอีกเช่นนี้

5.3878787878787...

โปรแกรมของคุณจะส่งออกจำนวนเต็มสองจำนวนที่แสดงถึงตัวเศษและส่วนโดยคั่นด้วยเครื่องหมายทับ (หรือรูปแบบที่เทียบเท่าในภาษาของคุณหากคุณไม่ได้พิมพ์ข้อความธรรมดา):

889/165

โปรดทราบว่าการยกเลิกทศนิยมจะไม่มีอะไรหลังจากจุดที่สองและทศนิยมที่ไม่มีส่วนทศนิยมที่ไม่ซ้ำจะไม่มีอะไรระหว่างจุดสองจุด

กรณีทดสอบ

กรณีทดสอบเหล่านี้ครอบคลุมกรณีมุมที่ต้องการทั้งหมด:

0..3 = 1/3
0.0.3 = 1/30
0.00.3 = 1/300
0.6875. = 11/16
1.8. = 9/5
2.. = 2/1
5..09 = 56/11
0.1.6 = 1/6
2..142857 = 15/7
0.01041.6 = 1/96
0.2.283950617 = 37/162
0.000000.1 = 1/9000000
0..9 = 1/1
0.0.9 = 1/10
0.24.9 = 1/4

หากคุณต้องการคุณสามารถสันนิษฐานได้ว่าเศษส่วนที่ไม่มีส่วนจำนวนเต็มไม่มีอะไรอยู่ทางซ้ายของจุดแรก คุณสามารถทดสอบด้วยกรณีทดสอบเพิ่มเติมเหล่านี้:

.25. = 1/4
.1.6 = 1/6
..09 = 1/11
.. = 0/1

1
จำเป็นหรือไม่ที่จะทำให้เศษส่วนง่ายขึ้น? หรือมีเหตุผลที่จะทิ้งไว้ในแบบฟอร์มที่ไม่ได้ระบุ (เช่น:) 9/99?
Justin

3
(in lowest terms)เช่นเศษส่วนจะต้องง่ายขึ้น
Joe Z.

2
ฉันได้รับอนุญาตให้ส่งออก13แทน13/1?
mniip

4
ตรวจสอบให้แน่ใจว่าได้จัดการอินพุต1.9999...และเอาต์พุตนี้2/1
Thomas Eding

3
@ThomasEding 1.9999.คือ19999/10000การที่2/1คุณต้องการ1..9ใช่ไหม?
Qwertiy

คำตอบ:


8

Dyalog APL ( 75 73 69 68 ตัวอักษร)

นี่คือความพยายามครั้งที่ห้าอีกครั้ง (อาจเป็นครั้งสุดท้ายของฉัน); ฉันใช้เวลาทั้งวันพยายามเขียนโค้ดบางส่วนที่สั้นกว่า 80 ตัวอักษรและสอดคล้องกับกฎอย่างสมบูรณ์ ความท้าทายนี้ทำให้วันของฉัน!

ในที่สุดฉันก็ได้บรรทัด APL ที่ประกอบด้วยอักขระ 75 ตัวทำงานกับ Dyalog APL (แต่ไม่ใช่ในหน้าล่ามออนไลน์เพราะใช้ฟังก์ชั่น execute ) ซึ่งเป็นหนึ่งในรายการต่อไปนี้:

(N,D)÷D∨N←(⍎'0',1↓I/⍨2=+\P)+(⍎'0',I/⍨2>+\P)×D←D+0=D←⍎'0',⌽2↓⍕¯1+10⊥P←'.'=I← '1.2.3'

แน่นอนว่าฉันสามารถทำให้มันสั้นลงเล็กน้อย แต่กรณีพิเศษที่หนึ่งหรือสองหรือสามฟิลด์หายไป รหัสของฉันสามารถจัดการ..กรณีการป้อนข้อมูลได้

ฉันรู้ว่า APL อ่านยากและเนื่องจากผู้คนสนุกกับการทำความเข้าใจวิธีการใช้งานโค้ดจริง ๆ นี่คือคำอธิบายบางส่วน โดยทั่วไปฉันคำนวณตัวส่วนสุดท้ายในตัวแปร D และตัวเศษสุดท้ายในตัวแปร N

APL ถูกแยกวิเคราะห์จากขวาไปซ้าย

  • ก่อนอื่นสตริงจะถูกเก็บไว้ในตัวแปร I ( I←)
  • จากนั้นมันจะถูกจับคู่กับเวกเตอร์ของบูลลีนซึ่งระบุว่าจุดคืออะไรและเวกเตอร์นี้เรียกว่า P ( P←'.'=) ตัวอย่างเช่น '1.2.3' จะถูกแมปกับ 0 1 0 1 0
  • เวกเตอร์นี้เป็นตัวเลขในฐาน 10 ( 10⊥); ตอนนี้ '1.2.3' คือ 1010
  • จากนั้น 1 จะถูกย่อลงมาจากตัวเลขนี้ (ไม่ว่าจะด้วย1-⍨หรือกับ¯1+ที่นี่ฉันเลือกที่สอง) ตอนนี้ '1.2.3' คือ 1009
  • จากนั้นตัวเลขนี้จะถูกแปลงเป็นสตริง ( ) ตัวเลขสองหลักเริ่มต้นจะถูกลบออก ( 2↓) ซึ่งทำให้ 09 จากตัวอย่าง '1.2.3' เริ่มต้นของเรา สตริงจะถูกกลับรายการ ( )
  • ที่นี่เป็นกรณีพิเศษฉันเพิ่มอักขระเริ่มต้น 0 ตัวต่อหน้าสตริง; มันทำให้ฉันเศร้าที่ใช้ตัวละครทั้งสี่'0',แต่ฉันทำเพื่อหลีกเลี่ยงข้อผิดพลาดเมื่อทั้งสองและสามฟิลด์ว่างเปล่า สตริงจะถูกแปลงกลับไปเป็นตัวเลข ( ) และมันถูกเก็บไว้ใน D ซึ่งเป็นตัวส่วนยกเว้นเมื่อทั้งสองฟิลด์สุดท้ายว่างเปล่าเพราะในกรณีดังกล่าว D เท่ากับ 0
  • D←D+0=ชิ้นส่วนของรหัสชุด D 1 ถ้ามันกำลังเป็นโมฆะและตอนนี้ D มีตัวหาร (ก่อนส่วน GCD แต่)
  • ตัวส่วนนี้จะถูกคูณ ( ×) ด้วยเนื้อหาของสตริงเริ่มต้นที่ฉันถึงจุดที่สอง(⍎'0',I/⍨2>+\P)ซึ่งเริ่มจาก P อีกครั้ง (0 1 0 1 0 ในตัวอย่างของฉัน) เพิ่มตัวเลขต่อเนื่องโดยการสะสมพวกเขา (ซึ่งทำให้ 0 1 1 2 2 ในตัวอย่างของฉัน) ตรวจสอบว่าค่าใดมีขนาดเล็กกว่า 2 (ทำให้เวกเตอร์บูลีน 1 1 1 0 0 0) และใช้อักขระที่เกี่ยวข้องใน I; 0 อื่นถูกเพิ่มไว้ด้านหน้าของสตริงเพื่อป้องกันกับดักอื่น (ถ้าสองฟิลด์เริ่มต้นว่างเปล่า) และทั้งหมดจะถูกแปลงเป็นตัวเลข
  • ส่วนสุดท้ายของสายป้อนข้อมูลจะถูกเพิ่มเข้าไปในผลิตภัณฑ์ก่อนหน้า(⍎'0',1↓I/⍨2=+\P)ซึ่งใช้ P อีกครั้งเพิ่มโดยการสะสมอีกครั้งตรวจสอบว่าค่าใดเท่ากับ 2 (ดูคำอธิบายก่อนหน้า) นำตัวอักษรออกลบส่วนแรกซึ่งเป็นจุด เพิ่มการป้องกันอักขระ 0 เริ่มต้นและแปลงเป็นตัวเลข
  • ผลิตภัณฑ์นี้ตามด้วยผลรวมจะถูกเก็บไว้ใน N ซึ่งเป็นตัวเศษ
  • ในที่สุด GCD จะคำนวณด้วยD∨Nและตัวเลขทั้งสองจะถูกหารด้วย GCD นี้

แก้ไข:นี่คือการแก้ไขสำหรับ 73 ตัวอักษร:

(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←D+0=D←⍎'0',⌽2↓⍕¯1+10⊥P←'.'=I←

แนวคิดของการแฮ็คนี้คือการคำนวณกรณีแรกที่การเพิ่มแบบสะสมมีค่าเท่ากับ 2 เก็บไว้ใช้ในภายหลังและกลับค่ามาสก์ bitwise นี้เพื่อรับคดีแรก ดังนั้นการคำนวณกรณีถัดไปต้องการตัวอักษรน้อยลง

แก้ไข:นี่คือการแก้ไขอื่นสำหรับ 69 ตัวอักษร:

(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←⍎'1⌈0',⌽2↓⍕¯1+10⊥P←'.'=I←

แนวคิดของการแฮ็คนี้คือการฝังกรณีพิเศษที่ซับซ้อนที่สุดเป็นรหัส APL ในสตริงที่จะประเมิน (ที่ขั้นตอนการแปลงสตริงเป็นตัวเลข)

แก้ไข:นี่คือการแก้ไขอีก 68 ตัวอักษร:

(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←⍎'1⌈0',⌽3↓⍕1-10⊥P←'.'=I←

แนวคิดของการแฮ็กนี้คือการแทนที่การเพิ่ม -1 ให้กับค่าสำหรับการแทนที่1 เป็นค่านั้นโดยการดำเนินการแทนที่ค่าเป็น 1จากนั้นลบอักขระหนึ่งตัวที่จุดเริ่มต้นในภายหลัง (ซึ่งจะเป็นเครื่องหมายลบ)

แก้ไข:เปลี่ยนเครื่องสำอาง:

(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←1⌈⍎'0',⌽3↓⍕1-10⊥P←'.'=I←

ไม่มีการปรับปรุงขนาด แต่พึงพอใจที่จะรับฟังก์ชั่นสูงสุดจากโค้ดที่จะทำการประเมิน


ฉันพยายามที่จะวิ่งนี้กับ tryapl.org INVALID TOKENและมันบ่น คุณรู้ไหมว่าทำไม?
Peter Taylor

@ Peter Taylor: ใช่มันยังพูดในข้อความของฉันด้วย; นี่เป็นเพราะฉันใช้โอเปอเรเตอร์ "execute" ซึ่งอาจไม่ปลอดภัยสำหรับเซิร์ฟเวอร์ของ Dyalog และถูกปิดการใช้งานออนไลน์ (เซฟโหมด) คุณต้องลองใช้ Dyalog APL เวอร์ชันที่ติดตั้งไว้
โทมัสบารูเชล

อาน่าละอาย ฉันจะไม่ใช้จ่าย€ 60 เพื่อให้สามารถทดสอบการส่ง PCG เป็นครั้งคราว ฉันพบตัวทดสอบ APL ทางเลือกออนไลน์ แต่ดูเหมือนว่ามีบางอย่างที่เฉพาะเจาะจงของ Dyalog ในรหัสของคุณเพราะมันให้ข้อผิดพลาดในการจัดอันดับหรือความยาวที่ผิดพลาด
Peter Taylor

@ Peter Taylor; ไม่ ;-) โปรดใช้เว็บไซต์ของฉันเอง (ยังอยู่ในช่วงทดลองและไม่เป็นทางการ) กับ GNU APL; แต่ฉันต้องเพิ่มตัวละครสองตัวเพื่อให้เข้ากันได้ (วงเล็บรอบ ๆ หนึ่งI): ดูความคิดเห็น
Thomas Baruchel

15

Perl 6 (93 101 100 80 68 66 ไบต์)

$/=split ".",get;say ($0+($1+$2/(9 x$2.comb||1))/10**$1.comb).nude

ขนาดเพิ่มขึ้นเพื่อจัดการกับอะไรเลยแทนที่จะล้มเหลว Mouq เสนอให้ใช้$/ดังนั้นตอนนี้มันถูกใช้งานแล้วและรหัสสั้นกว่า 20 ไบต์ Ayiko เสนอให้แทนที่/ด้วยดังนั้นโค้ดจึงสั้นกว่า (คูณ 12 ไบต์) จากนั้น Mouq เสนอให้แทนที่charsด้วยcomb(ในบริบทตัวเลขพวกเขาเหมือนกันเพราะรายชื่อตัวละครหลังจากการแปลงเป็นจำนวนคือจำนวนตัวอักษร)

ตัวอย่างผลลัพธ์:

$ perl6 script.p6
5.3.87
889 165
$ perl6 script.p6
2.0.0
2 1
$ perl6 script.p6
0..3
1 3
$ perl6 script.p6
0.0.3
1 30
$ perl6 script.p6
0.0.0
0 1
$ perl6 script.p6
0.1.6
1 6
$ perl6 script.p6
0.01041.6
1 96
$ perl6 script.p6
0.2.283950617
37 162
$ perl6 script.p6
123.456.789
41111111 333000

น่าเสียดายที่การใช้ศูนย์เป็นตัวยึดตำแหน่งระหว่างจุดสองจุดนั้นไม่เป็นไปได้ 0..09ผลตอบแทน1/11แต่ผลตอบแทน0.0.09 1/110
Joe Z.

@JoeZ โอวตกลง. ฉันอัปเดตรหัสเพื่อจัดการกรณีและปัญหาเมื่อไม่มีการพิมพ์
Konrad Borowski

ฉันไม่ทราบ Perl 6 แต่ฉันถูกต้องในการคาดเดาที่ได้รับ 'abc' โปรแกรมของคุณใช้เลขคณิตเชิงเหตุผลที่แน่นอนในการคำนวณ c / 99 ... 9 แต่ใช้จุดลอยเพื่อคำนวณ ab? ในกรณีนั้นถ้า b มีตัวเลขหลายหลักมันจะให้คำตอบที่ไม่ถูกต้อง
โอมา

@ OmarAntolín-Camarena: ไม่มาก ใน Perl 6 ค่า rationals เป็นค่าเริ่มต้นไม่ใช่ตัวเลขทศนิยม ตัวอย่างเช่น0.1 + 0.2 == 0.3ใน Perl 6
Konrad Borowski

2
เล่นกอล์ฟถึง 80 ตัวอักษร: $/=split ".",get;say join "/",($0+($1+$2/(9 x chars $2 or 1))/10**$1.chars).nude:)
Mouq

6

J ( 85 90 89 ตัวอักษร)

ฟังก์ชั่นดั้งเดิมของฉันซึ่งสั้นกว่าตัวอักษร 5 ตัวมีข้อบกพร่องสองสามข้อ: มันไม่ได้ส่งออกจำนวนเต็มเป็น "n / 1" และให้คำตอบที่ไม่ถูกต้องกับตัวเลขที่มีตัวเลขมากกว่าสิบหลัก นี่คือฟังก์ชั่นที่ได้รับการแก้ไขใน J ซึ่งรวมเอาคำแนะนำของ Eelvex ไว้ด้วยเพื่อบันทึกอักขระ:

f=:3 :0
'a t'=.|:(".@('0','x',~]),10x^#);._1'.',y
(,'/'&,)&":/(,%+.)&1+/a%*/\1,0 1-~}.t
)

ได้รับสตริงและส่งคืนสตริง นี่คือตัวอย่างเซสชั่น:

   f '..'
0/1
   f '0.0.0'
0/1
   f '3..'
3/1
   f '..052631578947368421'
1/19
   f '0.2.283950617'
37/162
   f '.0.103092783505154639175257731958762886597938144329896907216494845360824742268041237113402061855670'
1/97

คุณควรแก้ไขฟังก์ชั่นของคุณเพื่อส่งออก0/1และ3/1inf สองกรณีทดสอบแรกดูความคิดเห็นนี้
mniip

ฉันแก้ไขเอาต์พุตสำหรับจำนวนเต็มด้วยราคา 5 chars, @mniip
โอมา

ใช้('0','x',~])และบันทึกไบต์
Eelvex

5

C, 171

ค่อนข้างนาน. อาจลดลงอีก ไม่scanfซึ่งไม่สามารถจัดการได้หากไม่มีตัวเลขระหว่างจุด strtolไม่ เพียงแค่จำนวนกระทืบ:

a,b,c,d,q;main(){while((q=getchar()-48)>-3)q<0?(d=b>0,b+=!b):d?(c=c*10+q,d*=10):(a=a*10+q,b*=10);for(a=a*--d+c,q=b*=d;q>1;a%q+b%q?--q:(a/=q,b/=q));printf("%d/%d\n",a,b);}

ทดสอบ:

rfc <<< "2..142857"
15/7

5

DC (ไม่เต็มทั่วไปลดลงเหลือ 76 ตัวอักษร)

ไม่ธรรมดา แต่โปรดลองพิจารณาดูฉันได้ทำสิ่งที่เก่าแก่ที่สุดในโลก:

5.3.87 dsaX10r^d1-rla*sasbdscX10r^dlc*rlb*rlb*la+snsdlnld[dSarLa%d0<a]dsax+dldr/rlnr/f

แก้ไข:ฉันแก้ไขโซลูชันของฉัน; มันไม่ใช่เรื่องทั่วไป แต่สั้นกว่าเล็กน้อย:

sadsbX10r^sclaX10r^dd1-dsdlblc**rla*+dsnrld*dsd[dSarLa%d0<a]dsax+dldr/rlnr/f

ใช้เป็น:

5.3.87 sadsbX10r^sclaX10r^dd1-dsdlblc**rla*+dsnrld*dsd[dSarLa%d0<a]dsax+dldr/rlnr/f
  • ไม่จำเป็นต้องกรอกข้อมูลในฟิลด์แรก:

    .1.3 sadsbX10r^sclaX10r^dd1-dsdlblc**rla*+dsnrld*dsd[dSarLa%d0<a]dsax+dldr/rlnr/f
    

    ตกลง

  • เขตข้อมูลที่สองและกระหายต้องการอย่างน้อยหนึ่งหลัก


5

Javascript, 203

นานเกินไป แต่ก็ยังสนุก การขึ้นบรรทัดใหม่เนื่องจากอัฒภาคไม่สามารถอ่านได้

s=prompt(b=1).split(".")
P=Math.pow
a=s[0]
c=s[1]
d=P(10,l=c.length)
f=(P(10,s[2].length)-1)*P(10,l)||1
e=s[2]=+s[2]
a=d*a+b*c;b*=d
a=f*a+b*e;b*=f
function g(a,b){return b?g(b,a%b):a}g=g(a,b);a/g+"/"+b/g

ฉันได้รับ889/NaNเมื่อฉันวิ่ง5.3.87... ฉันทำอะไรผิดหรือเปล่า?
rafaelcastrocouto

ฉันไม่รู้ ... หากฉันเพิ่งวางรหัสนี้ในคอนโซล Safari (Firefox หรือ Chrome ควรทำเช่นกัน) กด Enter และพิมพ์ "5.3.87" ฉันเพิ่ง"889/165"เข้าสู่คอนโซล คุณเป็นอย่างไรบ้าง @rafaelcastrocouto
tomsmeding

ไม่เป็นไร ... ฉันเดาว่าฉันทำอะไรผิดเพราะมันใช้งานได้ตอนนี้ ...
rafaelcastrocouto

1
คุณสามารถบันทึก 1 ตัวละครโดยการย้ายภายในส่วนb=1 prompt()
user2428118

1
f=(P(10,s[2].length)-1)*P(10,l),f=f?f:1=>f=(P(10,s[2].length)-1)*P(10,l)||1
f.ardelian

3

J (วิธีที่แตกต่าง)

วิธีการแก้ปัญหาอื่นขึ้นอยู่กับวิธีที่แตกต่างกันมาก คราวนี้มันเป็นเรื่องทั่วไปอย่างเต็มที่; สิ่งที่ขาดหายไปเพียงตัวเดียวคือ 1 ส่วนเมื่อส่งจำนวนเต็ม:

   ".((({.~(i.&1)),'+'"_,((":@(10&^)@#,'%~',])@}.@#~~:/\),'+%',((,~(##'9'"_),'%x:0'"_)@}.@#~2:=+/\@]))(=&'.')) '.1.3'
2r15
   ".((({.~(i.&1)),'+'"_,((":@(10&^)@#,'%~',])@}.@#~~:/\),'+%',((,~(##'9'"_),'%x:0'"_)@}.@#~2:=+/\@]))(=&'.')) '.1.'
1r10
   ".((({.~(i.&1)),'+'"_,((":@(10&^)@#,'%~',])@}.@#~~:/\),'+%',((,~(##'9'"_),'%x:0'"_)@}.@#~2:=+/\@]))(=&'.')) '1..'
1
   ".((({.~(i.&1)),'+'"_,((":@(10&^)@#,'%~',])@}.@#~~:/\),'+%',((,~(##'9'"_),'%x:0'"_)@}.@#~2:=+/\@]))(=&'.')) '1..3'
4r3

3

GolfScript (67 ตัวอักษร)

`{'.'/1$=.10\,?@-).!+0@+~}+3,/1$4$*]-1%~;*+*+].~{.@\%.}do;{/}+/'/'@

NB สิ่งนี้รองรับชิ้นส่วนจำนวนเต็มที่ว่างเปล่า

ถ้า string เป็นของแบบฟอร์ม'n.p.q'แล้วค่าเป็นn + p/E + q/(DE) = ((nD + p)E + q)/DEที่D = 10^(len p)และE = 10^(len q) - 1, ยกเว้นเมื่อlen q = 0ซึ่งในกรณีนี้E = 1(เพื่อหลีกเลี่ยงการหารด้วย 0)

ผ่า:

           # Stack: 'n.p.q'
`{         # Combined with the }+ below this pulls the value into the block
           # Stack: idx 'n.p.q'
    '.'/   # Stack: idx ['n' 'p' 'q']
    1$=    # Stack: idx str   (where str is the indexed element of ['n' 'p' 'q'])
    .10\,? # Stack: idx str 10^(len str)
    @-)    # Stack: str 10^(len str)-idx+1
           #   If idx = 0 we don't care about the top value on the stack
           #   If idx = 1 we compute D = 10^(len 'p')
           #   If idx = 2 we compute E' = 10^(len 'q') - 1
    .!+    # Handle the special case E'=0; note that D is never 0
    0@+~   # Stack: 10^(len str)-idx+1 eval('0'+str) (GolfScript doesn't treat 011 as octal)
}+         # See above
3,/        # Run the block for idx = 0, 1, 2
           # Stack: _ n D p E q
1$4$*      # Stack: _ n D p E q D*E
]-1%~;     # Stack: D*E q E p D n
*+*+       # Stack: D*E q+E*(p+D*n)
].~        # Stack: [denom' num'] denom' num'
{.@\%.}do; # Stack: [denom' num'] gcd
{/}+/      # Stack: denom num
'/'@       # Stack: num '/' denom

การสาธิตออนไลน์ซึ่งจำลองการรันโปรแกรมด้วยอินพุตการทดสอบแต่ละรายการทีละรายการ


ฉันลองแล้วดูเหมือนจะไม่เป็นไปตามกฎทั้งหมด: "โปรดทราบว่าการยกเลิกทศนิยมจะไม่มีอะไรหลังจากจุดที่สองและทศนิยมที่ไม่มีส่วนทศนิยมที่ไม่ซ้ำกันจะไม่มีอะไรเกิดขึ้นระหว่างจุดทั้งสอง" ฉันไม่สามารถทำให้โค้ดของคุณทำงานได้ด้วยการป้อนข้อมูล0.1.
Thomas Baruchel

-1 ฉันลองใหม่อีกครั้งหลังจากสังเกตว่าคุณได้คะแนน +300 มันไม่ยุติธรรมเพราะแนวทางแก้ไขปัญหาอื่น ๆ ได้ดำเนินการอย่างดีที่สุดเพื่อปฏิบัติตามกฎทั้งหมดที่คุณยังไม่ได้ทำ
โทมัสบารูเชล

@ ใช่, ฉันคัดค้านการยืนยันของคุณว่าฉันไม่ได้พยายามปฏิบัติตามกฎ ตำแหน่งของกรณีทดสอบเสริมทำให้ฉันสับสนเมื่อคิดว่าบล็อกสุดท้ายครอบคลุมทุกกรณีที่จำเป็น ปรากฎว่าฉันผิดและฉันจะแก้ไขคำถามในไม่ช้าเพื่อหลีกเลี่ยงคนอื่นที่ทำผิดพลาดเหมือนกัน ตอนนี้ฉันได้อัปเดตรหัสของฉันเพื่อจัดการกรณีมุมที่ไม่ได้จัดการก่อนหน้านี้และอัปเดตลิงก์ของฉันเพื่อทดสอบเพื่อแสดงให้เห็นว่า
Peter Taylor

ไม่เป็นไร. คุณอาจสมควรได้รับ 300 คะแนน การเป็น CodeGolf ใหม่เป็น 300 คะแนนเหล่านี้เป็นเป้าหมายที่ท้าทายสำหรับฉันและฉันก็ยังผิดหวังที่ไม่ได้รับมันในขณะที่ฉันยังคงคิดว่าในเวลาที่กำหนดรหัสของฉันนั้นสั้นที่สุดเพื่อให้เข้ากับกฎอย่างสมบูรณ์ อย่างไรก็ตามฉันมีชีวิตของฉันทั้งหมดสำหรับการชนะคะแนน ความนับถือ.
โทมัสบารูเชล

@ ברוכאל: ฉันต้องการที่จะเริ่ม 500 คะแนน (ใช่ฉันใจกว้างเช่นนั้นไม่ใช่ว่าฉันสามารถให้น้อยลง) ได้รับรางวัลและให้คะแนนเหล่านั้นกับคุณ แต่ฉันเดาว่าเริ่มมีความโปรดปรานแล้ว อะไรก็ได้ ฉันสงสัยว่าเมื่อความโปรดปรานนี้จะจบลงและใครจะได้รับคะแนนเหล่านั้น
Konrad Borowski

2

หลาม

ไม่มีไลบรารี - 156 ตัวอักษร

_=lambda a,b:b and _(b,a%b)or a;a,b,c=raw_input().split('.');d,e=int(a+b+c)-bool(c)*int(a+b),
(10**len(c)-bool(c))*10**len(b);f=_(d,e);print'%i/%i'%(d/f,e/f)

ใช้fractions- 127 ตัวอักษร

from fractions import*;a,b,c=raw_input().split('.');print Fraction(int(a+b+c)-bool(c)*int(a+b
),(10**len(c)-bool(c))*10**len(b))

fractionsรุ่นพิมพ์สิ่งที่ชอบ "เศษส่วน (7, 5)" แทน "7/5" ไม่ได้หรือไม่
โอมา

มันไม่ได้; ฉันไม่ได้ติดอันดับต้น ๆ _=lambda a,b:b and _(b,a%b)or a;a,b,c=raw_input().split('.');d,e=int(a+b+c)-bool(c)*int(a+b), ValueError: need more than 1 value to unpack
tomsmeding

@ OmarAntolín-Camarena AFAIK, printใช้เมื่อพร้อมใช้งานไม่ได้str reprนี่คือผลลัพธ์ในตอนท้ายของฉัน: puu.sh/7w64w.png
Oberon

@tomsmeding ทั้งสองอยู่ในบรรทัดเดียว; เพิ่มตัวแบ่งบรรทัดเพื่อให้พอดีกับคำตอบ _=lambda a,b:b and _(b,a%b)or a;a,b,c=raw_input().split('.');d,e=int(a+b+c)-bool(c)*int(a+b),(10**len(c)-bool(c))*10**len(b);f=_(d,e);print'%i/%i'%(d/f,e/f)ควรไปทั้งหมดในบรรทัดเดียว
Oberon

@Oberon อย่างที่คุณอาจจะเดาได้ว่าฉันไม่ได้อยู่ที่คอมพิวเตอร์ของฉันและไม่สามารถเรียกใช้รหัสได้
โอมา

2

Mathematica, 143

ตามปกติแล้ว Mathematica มีฟังก์ชั่นระดับสูงมากมายในการทำงาน แต่ให้ชื่อที่ละเอียด

x=StringTake;c=ToExpression;p=s~StringPosition~".";{o,t}=First/@p;u=StringLength@s-t;d=t-o-1;Rationalize@(c@x[s,t-1]+c@x[s,-u]/((10^u)-1)/10^d)

ตัวอย่างผลลัพธ์ที่จะเพิ่มในภายหลังเมื่อฉันมีเวลา


ดูเหมือนว่าฉันจะออกเป็นจำนวนเต็มเป็น n มากกว่า n / 1 นั่นถูกต้องใช่ไหม? (วิธีการแก้ปัญหาของฉันมีข้อผิดพลาดเดียวกัน ... :()
โอมา

อาตอนนี้ฉันเห็น .... ที่ระบุในความคิดเห็น สิ่งที่เป็นความต้องการของแปลก ... ถ้าทุกส่วนอื่น ๆ จะลดลงทำไมไม่อนุญาตให้มีn/1การลดn? ฉันจะเพิ่มพิเศษ ~ 50 ไบต์เพื่อแปลงจำนวนเต็มในภายหลัง
Jonathan Van Matre

วิธีการของคุณดี Mine ใช้ประโยชน์FromDigitsดังนั้นฉันจึงตัดสินใจโพสต์ด้วย
DavidC

2

ทับทิม - 112

x,y,z=gets.chop.split".";y||='0';z||='0';puts((y.to_i+Rational(z.to_i,10**z.length-1))/10**y.length+x.to_i).to_s

นี่เป็นการทดลองครั้งแรกของฉันกับทับทิมดังนั้นอย่าลังเลที่จะแนะนำการปรับปรุง

$ ruby20 % <<< '5.3.87'
889/165
$ ruby20 % <<< '0..3'
1/3
$ ruby20 % <<< '0.0.3'
1/30
$ ruby20 % <<< '0.00.3'
1/300
$ ruby20 % <<< '0.6875.0'
11/16
$ ruby20 % <<< '1.8.0'
9/5
$ ruby20 % <<< '2..'
2/1
$ ruby20 % <<< '..'
0/1

การลบการสนับสนุน ".. 'และ" .1.2 "หมายความว่าคุณไม่ได้ติดตามข้อมูลจำเพาะใช่ไหม (ฉันต้องการลบออกด้วย)
Omar

@ OmarAntolín-Camarena If you wishในจุดโดยเฉพาะอย่างยิ่งข้อมูลจำเพาะกล่าวว่า ฉันไม่ต้องการดังนั้นฉันจึงไม่สนับสนุนเศษส่วนหากไม่มีตัวเลข 1 หรือ 3 อย่างไรก็ตามฉันสนับสนุนเศษส่วนที่ไม่มีตัวเลขกลุ่มที่ 2 ซึ่งตรงกับข้อมูลจำเพาะ
mniip

@minip คุณอ่านสเป็คผิด: ไม่พูดว่า "ถ้าคุณต้องการคุณสามารถสนับสนุน .. และ. 1.2" มันบอกว่า "ถ้าคุณต้องการคุณสามารถสันนิษฐานได้ว่า 0 .. และ 0.1.2 จะให้เป็นเสมอ .. และ. 1.2 "
โอมา

@ OmarAntolín-Camarena Point ถ่ายไว้ แก้ไข
mniip

2

C, 164

มันคล้ายกับโซลูชัน C ของ orion แม้ว่าฉันจะทำตั้งแต่เริ่มต้นก็ตาม ฉันขอสารภาพ แต่ขโมยการปรับให้เหมาะสมจำนวนหนึ่งของเขา มันไม่ได้สั้นมาก แต่มันจัดการกับ. 25 = 1/4 และ 0.000000.1 = 1/9000000

long a,b,c,d,e;main(){while((c=getchar()-48)>-3)c+2?a=a*10+c,b*=10:b?e=a,d=b:(b=1);
b>d?a-=e,b-=d:0;for(d=2;d<=a;)a%d+b%d?d++:(a/=d,b/=d);printf("%ld/%ld\n",a,b);}

2

หลามสองคำตอบโดยไม่ใช้ไลบรารี ขั้นแรกจัดการอินพุตที่เป็นทางเลือกโดยไม่มีตัวเลขก่อนหน้าแรก และเป็น 162 ตัวอักษร

_=lambda a,b:b and _(b,a%b)or a;i,t,r=raw_input().split(".");b=r!="";d=(10**len(r)-b)*10**len(t);n=int((i+t+r)or 0)-b*int((i+t)or 0);f=_(d,n);print "%i/%i"%(n,d)

ประการที่สองไม่ได้จัดการอะไรก่อนหลักแรก แต่จัดการกับอินพุตที่ต้องการทั้งหมดอย่างถูกต้องและเป็น 150 ตัวอักษร

_=lambda a,b:b and _(b,a%b)or a;i,t,r=raw_input().split(".");b=r!="";d=(10**len(r)-b)*10**len(t);n=int(i+t+r)-b*int(i+t);f=_(d,n);print "%i/%i"%(n,d)

2

Haskell

import Data.Ratio
f n=case s '.' n of
    [x,y,z]->(r x)%1+(r y)%(10^(length y))+(r z)%((10^t-1)*(10^(length y)))
        where
            r ""=0
            r n=read n
            t = if length z==0 then 9 else length z
s _ []=[[]]
s n (x:xs) | x==n = []:(s n xs)
           | otherwise = let (l:ls)=s n xs in (x:l):ls

เฮ้นี่คือรหัสกอล์ฟคุณไม่ได้ลองเลย!
mniip

@mniip ฉันไม่เก่งเรื่อง code golf Atleast ฉันใช้ชื่อตัวแปรอักขระเดียว
PyRulez

1
คุณไม่เคยระบุภาษาหรือจำนวนตัวอักษร / ไบต์ทั้งหมดที่ใช้
Justin Fay

2
ใช้ {;} เพื่อประหยัดพื้นที่ในการเยื้องspanเพื่อใช้งานของ s เพิ่มนามแฝงสั้นสำหรับฟังก์ชั่นเอาพื้นที่ที่เป็นไปได้ import Data.Ratio v=span(/='.');w=tail;l=length;f n=(r x)%1+(r y)%p+(r z)%((10^t-1)*p)where{(x,b)=v n;(y,d)=v(w b);z=w d;p=10^(l y);r""=0;r n=read n;t=if null z then 9 else l z}- 178 ตัวอักษรลดลงจาก 321 NB Trueเป็นไวพจน์otherwise, null zเป็นlength z==0
bazzargh

2

JavaScript (ECMASCript 6) 180 175

G=(a,d)=>d?G(d,a%d):a;P=a=>+("1e"+a);L=a=>a.length;f=prompt().split(".");B=P(L(b=f[1]));D=P(L(b)+L(c=f[2]))-P(L(b))||1;alert((m=(f[0]+b||0)*D+B*(c||0))/(g=G(m,n=B*D))+"/"+n/g)

แม้ว่ามันจะไม่ใช่ผู้ชนะที่ชัดเจนสำหรับ 300 ค่าหัว แต่นี่เป็นเวลาที่สั้นที่สุดที่ฉันจะได้รับ:

  • การเปลี่ยนแปลงจากรุ่นก่อนหน้า:การเปลี่ยนแปลงเล็กน้อยในตรรกะและการเปลี่ยนแปลงPฟังก์ชั่นพลังงานโดยการเปลี่ยนเป็น+("1e"+a)แทนที่จะMath.pow(10,a)บันทึกอีกสองสามตัวอักษร ...

1

Mathematica 175

f@i_:=
If[IntegerQ[g=FromDigits[Map[IntegerDigits@ToExpression@#&,StringSplit[i,"."]/.""-> {}]
/.{a_,b_,c_}:> {{Sequence@@Join[a,b],c},Length@a}]],HoldForm[Evaluate@g]/HoldForm@1,g]

รูทีนส่วนใหญ่ไปที่การนวดอินพุต ประมาณ 50 ตัวอักษรไปจัดการจำนวนเต็ม


ตัวอย่าง

f["7801.098.765"]

frac1

ตัวอย่างเพิ่มเติม:

TableForm[
 Partition[{#, f[#]} & /@ {"19..87", "19.3.87", "5.3.87", "0.0.3", "0..3", "0.2.283950617", 
"123.456.789", "6666.7777.8888", "2.0.0","0.0.0"}, 5], TableSpacing -> {5, 5}]

frac2


ปกติแล้วมันจะสำเร็จใน Mathematica ได้อย่างไร

FromDigitsสามารถรับเศษส่วนโดยตรงจากทศนิยมซ้ำที่เกิดขึ้นซ้ำโดยมีเงื่อนไขว่าการป้อนข้อมูลของรูปแบบเฉพาะ จำนวนเต็มจะแสดงเป็นจำนวนเต็ม

z={{{1, 9, {8, 7}}, 2}, {{1, 9, 3, {8, 7}}, 2}, {{5, 3, {8, 7}}, 1}, {{{3}}, -1}, {{{3}}, 0}, 
{{2, {2, 8, 3, 9, 5, 0, 6, 1, 7}}, 0}, {{1, 2, 3, 4, 5, 6, {7, 8, 9}}, 3}, 
{{6, 6, 6, 6, 7, 7, 7, 7, {8}}, 4}, {{2}, 1}, {{0}, 1}}

FromDigits/@z

Z


เอาต์พุตของคุณอยู่ในรูปแบบที่ไม่ถูกต้องมันสวยเกินไป
โอมา

น่าแปลกที่นี่เป็นรูปแบบเริ่มต้นสำหรับการแสดงเศษส่วนใน Mathematica จะต้องใช้อักขระเพิ่มอีกหลายตัวเพื่อเปลี่ยนรูปแบบนี้ให้ง่ายขึ้น
DavidC

1

J (96 ตัวอักษร)

ฉันไม่ได้ใช้สัญลักษณ์สแลชเป็นตัวคั่น (แต่โซลูชันใน Mathematica ไม่ได้เป็นอย่างใดอย่างหนึ่งเนื่องจากใช้การแสดงกราฟิกซึ่งดีกว่าอยู่ดี) ในภาษา J เศษส่วนจะแสดงขึ้นrแทน/:

   (((-.@]#[)((".@[%#@[(10x&^)@-{.@])+({.@](10x&^)@-#@[)*<:@{:@](".%<:@(10x&^)@#)@}.[)I.@])(=&'.')) '1..3'
4r3
   (((-.@]#[)((".@[%#@[(10x&^)@-{.@])+({.@](10x&^)@-#@[)*<:@{:@](".%<:@(10x&^)@#)@}.[)I.@])(=&'.')) '123.456.789'
41111111r333000

1

APL (ไม่ใช่แบบทั่วไปทั้งหมด)

ไม่ธรรมดาอย่างสมบูรณ์ (เช่นโซลูชันสำหรับ dc); ใช้งานได้กับ Dyalog APL (แต่ไม่ใช่ในเวอร์ชันออนไลน์ของ Dyalog APL ไม่แน่ใจว่าทำไม):

(R,F)÷(F←D×N)∨R←(⍎C)+D×(⍎I/⍨2>+\P)×N←10*¯1++/≠\P⊣D←¯1+10*⍴C←1↓I/⍨2=+\P←'.'=I← '123.456.789'

ฟิลด์แรกเป็นทางเลือก แต่ต้องมีอย่างน้อยหนึ่งหลักสำหรับทั้งสองฟิลด์


1

จาวาสคริปต์ (189)

i=prompt().split(".");a=i[0];b=i[1];c=i[2];B=b.length;p=Math.pow;n=a+b+c-(a+b);d=p(10,B+c.length)-p(10,B);f=1;while(f){f=0;for(i=2;i<=n;i++)if(n%i==0&&d%i==0){n/=i;d/=i;f=1}};alert(n+"/"+d)

ตัวอย่าง:

การป้อนข้อมูล:

5.3.87

เอาท์พุท:

889/165

1

C (420 ตัวอักษรตามที่เขียนน้อยกว่าหลังจากลบพื้นที่ว่างที่ไม่จำเป็นออก)

โปรดทราบว่านี่ถือว่า 64- บิตlong(เช่น 64 บิต Linux); มันจะล้มเหลวสำหรับกรณีทดสอบ0.2.283950617บนระบบที่ใช้ long32 สิ่งนี้สามารถแก้ไขได้ที่ค่าใช้จ่ายของตัวละครบางตัวโดยการเปลี่ยนประเภทเป็นlong longและเปลี่ยนprintfสตริงรูปแบบตาม

#include <stdio.h>

long d[3], n[3], i;

int main(int c, char** v)
{
  while (c = *v[1]++)
    switch(c)
    {
    case '.':
      n[++i] = 1;
      break;
    default:
      d[i] = 10 * d[i] + c - '0';
      n[i] *= 10;
    }

  n[2] -= n[2] != 1;

  while (i--)
    d[2] += d[i] * n[i+1], n[i]*=n[i+1];

  i = d[2];
  *n = n[1];

  while (i)
    *d = i, i = *n%i, *n = *d;
  printf("%ld/%ld\n", d[2]/ *n, n[1]/ *n);
}

ดี คุณสามารถโกน 1 ตัวละครโดยการเปลี่ยนไป'0' 48
ทอดด์เลห์แมน

ฉันคิดว่าคุณยังสามารถบันทึกอีกไม่กี่โดยเขียนใหม่คำสั่งเป็นswitch if(c==46) n[++i]=1; else d[i]=10*d[i]+c-48,n[i]*=10;
ทอดด์เลห์แมน

-3

GTB , 81

`_:s;_,1,l?_)-S;_,"."
s;A;,1,S;_,".")-1
s;_,1+S;_,"."),l?_)-S;_,"."))→_
x?A;+_)►Frac

ตัวอย่าง

?3.25.
            13/4

4
จนกว่าผู้แปลจะให้บริการอย่างอิสระสำหรับภาษานี้ฉันจะ downvote ทุกคำตอบที่ใช้มัน
Gareth

1
ดูเหมือนว่าจะมีคอมไพเลอร์ในหน้าลิงค์ด้านบน?
skibrianski


2
@Gareth มี Mathematica สองสามคำตอบให้คุณลงคะแนนเสียงเช่นกัน : P
โอมา

2
@ OmarAntolín-Camarena มีผู้แปล / ล่ามสำหรับ Mathematica GTB ไม่มีเลย ตามGTBลิงค์ด้านบนหากคุณไม่เชื่อฉัน คุณจะได้รับข้อมูลที่ถูกบีบอัดสำหรับโปรแกรมที่เป็นกรรมสิทธิ์จากนั้นคุณจะค้นหาโปรแกรมนั้นและพบว่าไซต์ที่อ้างว่าให้การดาวน์โหลดบอกว่าไม่มีให้ แล้วเราจะรวบรวมได้อย่างไร
Gareth
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.