สลับออกบางส่วนเป็นระยะและไม่เป็นระยะ


21

ในการแทนทศนิยมของทุกจำนวนตรรกยะp/qคุณมีหางเป็นระยะหัวที่ไม่เป็นระยะและส่วนที่อยู่หน้าจุดทศนิยมในรูปแบบต่อไปนี้:

(before decimal point).(non-periodic)(periodic)

ตัวอย่างบางส่วน ได้แก่ :

1/70 = 0.0142857... = (0).(0)(142857)
10/7 = 1.428571... = (1).()(428571)            ## no non-periodic part
1/13 = 0.076923... = (0).()(076923)
3/40 = 0.075 = (0).(075)()                    ## no periodic part
-2/15 = -0.13... = -(0).(1)(3)                ## negative
75/38 = 1.9736842105263157894... = (1).(9)(736842105263157894)
                                              ## periodic part longer than float can handle
25/168 = 0.148809523... = (0).(148)(809523)
120/99 = 40/33 = 1.212121... = (1).()(21)
2/1 = 2 = (2).()()                            ## no periodic, no non-periodic
0/1 = 0 = (0).()()
0/2 = 0 = (0).()()
299/792 = 0.37752... = (0).(377)(52)
95/-14 = -6.7857142... = -(6).(7)(857142)
-95/-14 = 6.7857142... = (6).(7)(857142)

ความท้าทายคือการสลับชิ้นส่วนเป็นระยะและไม่เป็นระยะ ๆ ปล่อยให้before decimal pointอยู่ตามลำพังเพื่อสร้างหมายเลขใหม่ ตัวอย่างเช่น:

25/168 = 0.148809523... = (0).(148)(809523)
       => (0).(809523)(148) = 0.809523148148... = 870397/1080000

หากตัวเลขไม่มีส่วนตามระยะเวลาเช่น0.25เปลี่ยนหมายเลขนั้นเป็นหมายเลขใหม่และกลับกัน

1/4 = 0.25 = (0).(25)() => (0).()(25) = 0.252525... = 25/99
4/9 = 0.444444... = (0).()(4) => (0).(4)() = 0.4 = 2/5
5/1 = 5 = (5).()() => (5).()() = 5 = 5/1

ความท้าทาย

  • ใช้เศษส่วนxเป็นอินพุตเป็นสตริงสองอินพุตจำนวนตรรกยะหรือวิธีใดก็ตามที่เหมาะกับภาษาของคุณ
  • สลับส่วนที่เป็นคาบและไม่เป็นงวดของการแทนทศนิยมของxเพื่อสร้างตัวเลขใหม่โดยปล่อยให้ส่วนนั้นอยู่ก่อนหน้าทศนิยมเพียงอย่างเดียว ส่วนที่เป็นคาบจะเริ่มโดยเร็วที่สุดเพื่อให้ส่วนที่ไม่ใช่ระยะสั้นที่สุดเท่าที่จะทำได้ ตัวอย่างด้านล่าง
  • ส่งคืนหมายเลขที่สลับเป็นเศษส่วนใหม่ อินพุตไม่จำเป็นต้องลดลงแม้ว่าเอาต์พุตควรเป็น รูปแบบอินพุตอนุญาตให้แตกต่างจากรูปแบบเอาต์พุต
  • ตัวเศษpของxจะเป็นจำนวนเต็มที่มีค่าสัมบูรณ์ของหนึ่งล้านหรือน้อยกว่าและตัวส่วนqของxจะเป็นจำนวนเต็มที่ไม่เป็นศูนย์ที่มีค่าสัมบูรณ์ของหนึ่งล้านหรือน้อยกว่า
  • ตัวเศษrและส่วนsของผลลัพธ์ไม่ได้รับประกันว่าจะน้อยกว่าหนึ่งล้าน เมื่อพิจารณาความยาวของส่วนที่เป็นระยะของตัวเลขเหล่านี้ขอแนะนำให้คุณหลีกเลี่ยงการแปลงเป็นแบบลอยตัวโดยตรง
  • นี่คือรหัสกอล์ฟ คำตอบที่สั้นที่สุดในการชนะไบต์

ตัวอย่าง

1/70 = (0).(0)(142857)     => (0).(142857)(0) = (0).(142857)() = 0.142857 = 142857/1000000
10/7 = (1).()(428571)      => (1).(428571)() = 1.428571 = 1428571/1000000
1/13 = (0).()(076923)      => (0).(076923)() = 0.076293 = 76923/1000000
3/40 = (0).(075)()         => (0).()(075) = 0.075075... = 75/999 = 25/333
-2/15 = -(0).(1)(3)        => -(0).(3)(1) = -0.311111... = -28/90 = -14/45
75/38 = (1).(9)(736842105263157894)
      => (1).(736842105263157894)(9) = (1).(736842105263157895)()  ## since 0.999... = 1
      = 1.736842105263157895 = 1736842105263157895/1000000000000000000
      = 347368421052631579/200000000000000000
25/168 = (0).(148)(809523) => (0).(809523)(148) = 0.809523148148... = 870397/1080000
120/99 = (1).()(21)        => (1).(21)() = 1.21 = 121/100
2/1 = (2).()()             => (2).()() = 2 = 2/1
0/1 = (0).()()             => (0).()() = 0 = 0/1
0/2 = (0).()()             => (0).()() = 0 = 0/1
299/792 = (0).(377)(52)    => (0).(52)(377) = 0.52377377... = 2093/3996
95/-14 = -(6).(7)(857142)  => -(6).(857142)(7) = -6.857142777... = -12342857/1800000
-95/-14 = (6).(7)(857142)  => (6).(857142)(7) = 6.857142777... = 12342857/1800000

มีขาดหายไปคือ0ในตอนท้ายของกรณีทดสอบ 2 (คน10/7) ที่ควรจะเป็น1428571/100000 1428571/1000000
JungHwan Min

1
ตามที่ระบุไว้จะไม่มีคำตอบเฉพาะสำหรับอินพุตที่กำหนด 1/7อาจจะแสดงเป็น(0).()(142857) หรือ(0).(1)(428571), 1อาจจะแสดงเป็น(1).()(), (0).()(9), (0).()(99), (0).(9)(9)ฯลฯ
ngenisis

@ngenisis นั่นเป็นนัยในตัวอย่าง แต่ฉันได้ทำให้มันชัดเจน ขอบคุณสำหรับความคิดเห็น :)
Sherlock9

@ R.Kap ฉันได้ระบุไว้แล้วในความท้าทายที่ดีที่สุดคือหลีกเลี่ยงการใช้ลอยที่นี่ มีวิธีการหาตัวเลขทศนิยมของตัวเลขโดยไม่แปลงเป็นทศนิยม ฉันหวังว่าสิ่งนี้จะตอบคำถามของคุณ :)
Sherlock9

ทั้ง p และ q เป็นลบได้ไหม?
edc65

คำตอบ:


5

Python 2, 292 ไบต์

def x(n,d):
 L=len;s=cmp(n*d,0);n*=s;b=p=`n/d`;a={};n%=d
 while not n in a:
  a[n]=p;q=n/d;n=n%d
  if q==0:n*=10;p+=' '
  p=p[:-1]+`q`
 p=p[L(a[n]):];a=a[n][L(b):]
 if n==0:p=''
 n=int(b+p+a);d=10**L(p+a)
 if a!='':n-=int(b+p);d-=10**L(p)
 import fractions as f;g=f.gcd(n,d);return(n/g*s,d/g)

รุ่น Ungolfed ใช้งานได้ทั้ง python 2 และ 3 พิมพ์การแทนค่าทศนิยม

def x(n,d):
# sign handling
 s=n*d>0-n*d<0
 n*=s
# b, a, p: BEFORE decimal, AFTER decimal, PERIODIC part
 b=p=str(n//d)
 a={}
 n%=d
# long division
 while not n in a:
  a[n]=p
  q=n//d
  n=n%d
  if q==0:
   n*=10
   p+=' '
  p=p[:-1]+str(q)
# a/p still contain b/ba as prefixes, remove them
 p=p[len(a[n]):]
 a=a[n][len(b):]
 if n==0: p=''
# print decimal representation
 print("(" + b + ").(" + a + ")(" + p + ")")
# reassemble fraction (with a and p exchanged)
 n=int(b+p+a)
 d=10**len(p+a)
 if a!='':
  n-=int(b+p)
  d-=10**len(p)
# reduce output
 from fractions import gcd
 g=gcd(n,d)
 return(n//g*s,d//g)

ลองd=10**len(p+a)
Sherlock9

1
นี่คือลิงค์ TIO สำหรับการทดสอบที่ง่าย: ลองออนไลน์!
Kritixi Lithos

ทำได้ดีกับคำตอบของคุณ: D เคล็ดลับเพิ่มเติมในการเล่นกอล์ฟใช้งาน: ใช้อัฒภาคอื่น ๆ ที่เป็นไปได้ที่จะกำจัดของพื้นที่ในบรรทัดif n==0: p=''ใช้``ในสถานที่ที่คุณใช้ทุกstrเช่น`n/d`แทนstr(n/d)และเปลี่ยนชื่อlenไปLกับL=len;ที่จุดเริ่มต้นของการทำงาน
Sherlock9

@ Sherlock9 ฉันไม่รู้ด้วยซ้ำเกี่ยวกับ backticks ขอบคุณสำหรับคำแนะนำทั้งหมด
Rainer P.

ไม่ใช่ปัญหา. นี่คือบางส่วนเพิ่มเติม: D สองสถานที่สำหรับอัฒภาคและn=int(b+p+a);d=10**L(p+a) import fractions as f;g=f.gcd(n,d);return(n/g*s,d/g)นอกจากนี้ฉันยังได้รับ 295 ไบต์สำหรับการแก้ไขปัจจุบันของคุณ มีการขึ้นบรรทัดใหม่พิเศษที่คุณลืมออกไปหรือไม่?
Sherlock9

2

เยลลี่ , 102 101 89 87 83 81 79 78 77 74 ไบต์

วิธีนี้ใช้เวลานานในการเขียนนานเกินกว่าที่จะทำการดีบั๊กและต้องการเล่นกอล์ฟจำนวนมาก ( แปดเจ็ดหก ห้าสี่ลิงก์วัวศักดิ์สิทธิ์) แต่มันก็เป็นสิ่งที่ดีที่สุดสำหรับความรู้ของฉันถูกต้อง ขอบคุณเดนนิสมากมายสำหรับความช่วยเหลือของเขาที่นี่โดยเฉพาะอย่างยิ่งกับลิงก์สองรายการแรก ต้องขอขอบคุณ Rainer P. เป็นอย่างมากในขณะที่ฉันลงเอยด้วยการยืมอัลกอริทึมมากมายในคำตอบของ Python

การแก้ไขการเล่นกอล์ฟ: -1 ไบต์ขอบคุณ Xanderhall แก้ไขข้อผิดพลาดจากการไม่ใช้ตรรกะที่ไม่ถูกต้องในตัว -13 ไบต์จากการเล่นกอล์ฟลิงก์ตัวเศษ +1 ไบต์จากการแก้ไขข้อผิดพลาดในเชิงลบdด้วยขอบคุณเดนนิส ปรับโครงสร้างการเชื่อมโยงใหม่เพื่อให้การสร้างตัวเศษตั้งอยู่ในลิงก์เดียว -2 ไบต์จากการรวมลิงค์ที่สองและสาม -4 ไบต์จากการย้ายองค์ประกอบทั่วไปของลิงก์ที่สามและสี่ไปยังลิงค์ที่สองและลิงค์หลัก -2 ไบต์จากการลบตัวดำเนินการโซ่ฟุ่มเฟือยบางส่วน -2 ไบต์จากการจัดเรียงลิงก์ตัวเลขใหม่ -1 ไบต์จากการย้ายḢ€ไปยังจุดสิ้นสุดของลิงก์ที่สอง แก้ไขข้อบกพร่องในลิงค์หลัก -1 ไบต์จากการเปลี่ยนไปṪ ... ,Ḣ Ḣ ... ṭ-3 ไบต์จากการย้ายลิงค์ตัวเศษไปยังลิงก์หลัก

ยินดีต้อนรับคำแนะนำการเล่นกอล์ฟ! ลองออนไลน์!

2ị×⁵d⁴
ÇÐḶ,ÇÐĿḟ@\µḢḅÐfıṭµḢḊṭµḢ€€µF,ḢQ
ÇL€⁵*
×Ṡ©⁸×%µ³,⁴A:/;Ѐ2ĿḌ×®,Ç_/€µ:g/

คำอธิบาย

ก่อนอื่นฉันจะอธิบายลิงก์หลักซึ่งเรียกลิงค์อื่น ๆ

×Ṡ©⁸×%µ³,⁴A:/;Ѐ2ĿḌ×®,Ç_/€µ:g/  Main link. Left argument: n (int), right argument: d (int)
                                Split into three chains.
×Ṡ©⁸×%  First chain
×       Multiply n by d.
 Ṡ©     Yield sign(n*d) and save it to the register.
   ⁸×   Multiply by n.
     %  Yield n*sgn(n*d) modulo d.

µ³,⁴A:/;Ѐ2ĿḌ×®,Ç_/€  Second chain
                        What follows is the formula for the numerator.
                        (+) means combining the digits of two numbers into one number.
                        ( `integer (+) periodic (+) non-periodic` - `integer (+) periodic` )
µ                     Start a new monadic chain with n*sgn(n*d)%d.
 ³,⁴                  Pair the original two arguments as a nilad.
    A                 Get their absolute values.
     :/               Integer divide to get the integer part of abs(n)/abs(d).
          2Ŀ          Yield the results of the second link.
       ;Ѐ            Append the integer part to each item in the right argument.
                        This appends to both lists from the second link.
            Ḍ         Convert each list from decimal to integer.
             ×®       Multiply by sign(n*d) retrieved from the register.
               ;Ç     Concatenate with the result of the third link (our new denominator).
                 _/€  Reduced subtract over each list.
                        Yields the proper numerator and denominator.

µ:g/  Third chain
µ     Start a new monadic chain with [numerator, denominator].
  g/  Yield gcd(numerator, denominator).
 :    Divide [numerator, denominator] by the gcd.
      Return this as our new fraction.

จากนั้นลิงก์แรกที่ได้รับตัวเลข

2ị×⁵d⁴  First link: Gets the decimal digits one at a time in the format:
          [digit, remainder to use in the next iteration]
2ị      Gets the second index (the remainder).
  ×⁵    Multiply by 10.
    d⁴  Divmod with d.

ตอนนี้การเชื่อมโยงที่สองที่ได้รับชิ้นส่วนเป็นระยะและไม่เป็นระยะn/dและการยกอื่น ๆ จำนวนมาก

ÇÐḶ,ÇÐĿḟ@\µḢḅÐfıṭµḢḊṭµḢ€€µF,ḢQ  Second link: Loops the first link,
                                  separates the periodic digits and non-periodic digits,
                                  removes the extras to get only the decimal digits,
                                  and prepares for the third and fourth links.
                                Split into five chains.
ÇÐḶ,ÇÐĿḟ@\  First chain
ÇÐḶ         Loop and collect the intermediate results **in the loop**.
    ÇÐĿ     Loop and collect **all** of the intermediate results.
   ,        Pair into one list.
       ḟ@\  Filter the loop results out the list of all results,
              leaving only [[periodic part], [non-periodic part]].

µḢḅÐfıṭµḢḊṭ  Second and third chains
µ            Start a new monadic chain.
 Ḣ           Get the head [periodic part].
   Ðf        Filter out any [0, 0] lists from a non-periodic number,
  ḅ  ı        by converting to a complex number before filtering.
               Only removes 0+0j. This removes extra zeroes at the end.
      ṭ      Tack the result onto the left argument again.
       µ     Start a new monadic chain.
        Ḣ    Get the head [non-periodic and extra baggage].
         Ḋ   Dequeue the extra baggage.
          ṭ  Tack the result onto the left argument again.

µḢ€€µF,ḢQ  Fourth and fifth chains
µ          Start a new monadic chain with the processed periodic and non-periodic parts.
 Ḣ€€       Get the head of each list (the digits)
            in both the periodic and non-periodic parts.
    µ      Start a new monadic chain with these lists of digits.
     F     Left argument flattened.
       Ḣ   Head of the left argument.
      ,    Pair the flattened list and the head into one list.
        Q  Uniquify this list. (Only removes if non-periodic part is empty)
             Removes any duplicates resulting from a purely periodic n/d.

การเชื่อมโยงที่สามซึ่งมีอัตราผลตอบแทนส่วนของเราใหม่

ÇL€⁵*  Third link: Generate the denominator.
         What follows is the formula for the denominator.
         ( 10**(num_digits) - ( 10**(num_periodic_digits) if len(non-periodic) else 0 ) )
Ç      Yield the results of the second link.
 L€    Get the length of each item in the list.
         The number of digits in total and the number of digits in the periodic part.
   ⁵*  10 to the power of each number of digits.
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.