Trao đổi một số phần định kỳ và không định kỳ


21

Trong biểu diễn thập phân của mỗi số hữu tỷ p/q, bạn có đuôi định kỳ, đầu không định kỳ và phần trước dấu thập phân theo định dạng sau:

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

Một số ví dụ bao gồm:

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)

Thách thức là hoán đổi các phần định kỳ và không định kỳ, để lại before decimal pointmột mình, để tạo ra một số mới. Ví dụ:

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

Nếu một số không có phần định kỳ như 0.25biến số đó thành số định kỳ mới và ngược lại.

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

Các thách thức

  • Lấy một phân số xlàm đầu vào, dưới dạng chuỗi, hai đầu vào, số hữu tỷ hoặc bất kỳ phương thức nào phù hợp với ngôn ngữ của bạn.
  • Hoán đổi các phần định kỳ và không định kỳ của biểu diễn thập phân của xđể tạo một số mới, để lại phần trước số thập phân một mình. Phần định kỳ luôn bắt đầu càng sớm càng tốt để phần không định kỳ càng ngắn càng tốt. Ví dụ dưới đây.
  • Trả về số đã hoán đổi dưới dạng một phần mới. Đầu vào không nhất thiết phải giảm mặc dù đầu ra nên được. Định dạng đầu vào được phép khác với định dạng đầu ra.
  • Tử số pcủa xsẽ là một số nguyên có giá trị tuyệt đối từ một triệu trở xuống và mẫu số qcủa xsẽ là một số nguyên khác không có giá trị tuyệt đối từ một triệu trở xuống.
  • Tử số rvà mẫu số scủa kết quả không được đảm bảo dưới một triệu. Với độ dài của các phần định kỳ của những con số này, bạn nên tránh chuyển đổi trực tiếp thành phao.
  • Đây là mã golf. Câu trả lời ngắn nhất trong byte thắng.

Ví dụ

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

Có một thiếu sót 0ở cuối trường hợp thử nghiệm 2 ( 10/7): 1428571/100000nên 1428571/1000000.
JungHwan Min

1
Như đã nêu, sẽ không có câu trả lời duy nhất cho đầu vào cụ thể. 1/7có thể được biểu diễn như (0).()(142857) hoặc (0).(1)(428571), 1có thể được biểu diễn như (1).()(), (0).()(9), (0).()(99), (0).(9)(9)vv
ngenisis

@ngenisis Điều đó đã tiềm ẩn trong các ví dụ, nhưng tôi đã làm cho nó rõ ràng. Cảm ơn phản hồi :)
Sherlock9

@ R.Kap Tôi đã tuyên bố trong thử thách rằng tốt nhất là tránh sử dụng phao ở đây. Có nhiều cách để tìm các chữ số thập phân của một số mà không chuyển đổi thành dấu phẩy. Tôi hy vọng điều này trả lời câu hỏi của bạn :)
Sherlock9

cả p và q có thể âm?
edc65

Câu trả lời:


5

Python 2, 292 byte

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)

Phiên bản Ungolfed, hoạt động trong cả python 2 & 3. Cũng in đại diện thập phân.

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)

Hãy thửd=10**len(p+a)
Sherlock9

1
Đây là một liên kết TIO để kiểm tra dễ dàng: Hãy thử trực tuyến!
Kritixi Lithos

Làm tốt câu trả lời của bạn: D. Một số lời khuyên chơi golf hơn nữa: sử dụng nhiều dấu chấm phẩy nếu có thể, thoát khỏi không gian trong dòng if n==0: p='', sử dụng ``ở mọi nơi bạn sử dụng str, chẳng hạn như `n/d`thay vì str(n/d), và đổi tên lenđể Lvới L=len;lúc bắt đầu của hàm.
Sherlock9

@ Sherlock9 Tôi thậm chí còn không biết về backticks. Cảm ơn vì tất cả những lời khuyên.
Rainer P.

Không thành vấn đề. Đây là một số chi tiết: D Hai vị trí cho dấu chấm phẩy: 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). Ngoài ra, tôi nhận được 295 byte cho chỉnh sửa hiện tại của bạn. Có một dòng mới nào bạn đang quên để lại?
Sherlock9

2

Thạch , 102 101 89 87 83 81 79 78 77 74 byte

Điều này mất rất nhiều thời gian để viết, quá lâu để gỡ lỗi và chắc chắn cần rất nhiều môn đánh gôn ( tám bảy sáu năm bốn liên kết, bò thần thánh), nhưng theo sự hiểu biết tốt nhất của tôi, chính xác. Rất, rất cám ơn Dennis vì sự giúp đỡ của anh ấy ở đây, đặc biệt là với hai liên kết đầu tiên. Rất cám ơn Rainer P., vì cuối cùng tôi đã mượn rất nhiều thuật toán trong câu trả lời Python của họ.

Chỉnh sửa chơi gôn: -1 byte nhờ Xanderhall. Sửa lỗi từ không sử dụng logic KHÔNG được xây dựng chính xác. -13 byte từ việc đánh gôn các liên kết tử số. +1 byte từ việc sửa lỗi cho âm bản dnhờ có Dennis. Tái cấu trúc các liên kết sao cho việc tạo tử số là tất cả trong một liên kết. -2 byte từ việc kết hợp các liên kết thứ hai và thứ ba. -4 byte từ việc di chuyển một số phần tử phổ biến của liên kết thứ ba và thứ tư sang liên kết thứ hai và liên kết chính. -2 byte từ việc loại bỏ một số toán tử chuỗi thừa. -2 byte từ sắp xếp lại liên kết tử số. -1 byte từ di chuyển Ḣ€đến cuối liên kết thứ hai. Đã sửa lỗi trong liên kết chính. -1 byte từ thay đổi Ṫ ... ,Ḣthành Ḣ ... ṭ. -3 byte từ việc di chuyển liên kết tử số vào liên kết chính.

Gợi ý chơi golf chào mừng! Hãy thử trực tuyến!

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

Giải trình

Đầu tiên, tôi sẽ giải thích liên kết chính , gọi các liên kết khác.

×Ṡ©⁸×%µ³,⁴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.

Sau đó, liên kết đầu tiên có được các chữ số.

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.

Bây giờ, liên kết thứ hai có được các phần định kỳ và không định kỳ n/d, và rất nhiều nâng nặng khác.

ÇÐḶ,ÇÐĿḟ@\µḢḅÐ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.

Các liên kết thứ ba , trong đó sản lượng mẫu mới của chúng tôi.

Ç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.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.