Bazı periyodik ve periyodik olmayan parçaları çıkarın


21

Her rasyonel sayının ondalık gösteriminde, p/qperiyodik bir kuyruğa, periyodik olmayan bir başa ve ondalık sayıdan önce aşağıdaki biçimde bir bölüme sahipsiniz:

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

Bazı örnekler:

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)

Buradaki zorluk, periyodik ve periyodik olmayan parçaları, before decimal pointtek başına bırakarak yeni bir sayı oluşturmak için değiştirmektir. Örneğin:

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

Bir sayının periyodik bir bölümü yoksa, 0.25bu sayıyı yeni bir periyodik sayıya çevirin ve bunun tersi de geçerlidir.

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

Meydan okuma

  • xGirdi, dize, iki giriş, rasyonel bir sayı veya dilinize uygun herhangi bir yöntem gibi bir kesir alın .
  • Takas ondalık temsil periyodik ve periyodik olmayan parçalar xtek başına ondalık önce kısmını bırakarak yeni bir numara oluşturun. Periyodik kısım daima mümkün olan en kısa sürede başlar, böylece periyodik olmayan kısım mümkün olduğu kadar kısa olur. Örnekler aşağıdadır.
  • Değiştirilen sayıyı yeni bir kesir olarak döndür. Çıktı olması gerektiği halde girdi mutlaka azaltılmaz. Giriş formatının, çıkış formatından farklı olmasına izin verilir.
  • Pay parasında xmutlak bir milyon ya da daha az bir değer ve payda bir tamsayı olacaktır qve xbir olacaktır sıfır olmayan bir milyon ya da daha az bir mutlak değere sahip bir tam sayı.
  • Sonucun pay rve paydasının sbir milyondan az olması garanti edilmez. Bu sayıların periyodik kısımlarının uzunluğu göz önüne alındığında, doğrudan yüzer maddelere dönüşmekten kaçınmanız önerilir.
  • Bu kod golfü. Bayt cinsinden en kısa cevap kazanır.

Örnekler

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

0Testin sonunda bir eksiklik var (2 10/7): 1428571/100000olmalıdır 1428571/1000000.
JungHwan Min

1
Belirtildiği gibi, belirli bir girdi için benzersiz bir cevap olmayacak. 1/7olarak temsil edilebilir (0).()(142857) ya da (0).(1)(428571), 1temsil edilebilir olarak (1).()(), (0).()(9), (0).()(99), (0).(9)(9), vb
ngenisis

@ ngenisis Örneklerde dolaylı olan budur, ancak bunu açıkça ortaya koydum. Geri bildiriminiz için teşekkürler :)
Sherlock9

@ R.Kap Ben burada yüzer kullanmaktan kaçınmanın en iyisi olduğunu söylemiştim. Bir sayının ondalık basamağını bir yüzgene dönüştürmeden bulmanın yolları vardır. Umarım bu sorunuza cevap verir :)
Sherlock9

Hem p hem de q negatif olabilir mi?
edc65

Yanıtlar:


5

Python 2,292 bayt

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 versiyonu, hem python 2 & 3 hem de çalışır. Ayrıca ondalık gösterimi yazdırır.

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)

Deneyind=10**len(p+a)
Sherlock9

1
İşte kolay test için bir TIO linki: Çevrimiçi deneyin!
Kritixi Lithos

Cevabınıza aferin: D. Bazı başka golf ipuçları: Kullanım fazla noktalı virgül mümkün, hat alan kurtulmak if n==0: p='', kullanım ``kullandığınız her yerde strgibi, `n/d`yerine str(n/d)ve yeniden adlandırma leniçin Lbirlikte L=len;işlevi başında.
Sherlock9

@ Sherlock9 Ben backticks hakkında bile bilmiyordum. Tüm tavsiyeler için teşekkürler.
Rainer P.

Problem değil. İşte biraz daha: D Noktalı virgül için iki yer: n=int(b+p+a);d=10**L(p+a)ve import fractions as f;g=f.gcd(n,d);return(n/g*s,d/g). Ayrıca, geçerli düzenlemeniz için 295 bayt alıyorum. Dışarıda bırakmayı unuttuğun fazladan bir yeni hat var mı?
Sherlock9

2

Jelly , 102 101 89 87 83 81 79 78 77 74 bayt

Bu yazı yazmak çok uzun sürdü, hata ayıklamak için çok uzun sürdü ve kesinlikle çok fazla golfe ( sekiz yedi altı beş dört bağlantı, kutsal inek) ihtiyaç duyuyordu, ama bu benim bildiğim kadarıyla doğru. Buradaki yardımları için Dennis'e çok, çok teşekkürler, özellikle de ilk iki bağlantıyla. Rainer P.'e çok teşekkürler, Python'un cevabındaki algoritmanın çoğunu ödünç aldım.

Golf düzenlemeleri: Xanderhall sayesinde -1 bayt. Doğru mantıksal NOT yerleşik değil kullanarak hata düzeltme. - Numaratör bağlantılarını golf oynamaktan 13 byte. dDennis sayesinde negatif bir hatayı düzeltmek için +1 bayt . Bağlantıları, pay oluşturmayı tamamen tek bir bağlantıda olacak şekilde yeniden yapılandırdık. İkinci ve üçüncü bağlantıları birleştirmekten -2 bayt. Üçüncü ve dördüncü bağlantıların bazı ortak unsurlarını ikinci bağlantıya ve ana bağlantıya taşımaktan -4 bayt. Bazı gereksiz zincir operatörleri kaldırmaktan -2 bayt. Numaratör bağlantısını yeniden düzenlemekten -2 bayt. Ḣ€İkinci bağlantının sonuna kadar hareket eden -1 bayt . Ana linkteki bir hata düzeltildi. Değiştirmesini -1 bayt Ṫ ... ,Ḣiçin Ḣ ... ṭ. - Payer bağlantısını ana linke taşımaktan -3 bayt.

Golf önerileri hoş geldiniz! Çevrimiçi deneyin!

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

açıklama

İlk önce, diğer bağlantıları çağıran ana linki açıklayacağım .

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

Sonra, rakamları alan ilk bağlantı .

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.

Şimdi, periyodik ve periyodik olmayan kısımları ve bir çok diğer ağır yükleri alan ikinci bağlantı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.

Üçüncü bağlantı yeni payda verir.

Ç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.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.