Zamień niektóre okresowe i nieokresowe części


21

W dziesiętnej reprezentacji każdej liczby wymiernej p/qmasz okresowy ogon, nieokresową głowę i sekcję przed przecinkiem w następującym formacie:

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

Niektóre przykłady obejmują:

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)

Wyzwanie polega na zamianie części okresowych i nieokresowych, pozostawiając w before decimal pointspokoju, aby utworzyć nową liczbę. Na przykład:

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

Jeśli liczba nie ma części okresowej, takiej jak 0.25zamień ją na nową liczbę okresową i odwrotnie.

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

Wyzwanie

  • Weź ułamek xjako dane wejściowe, ciąg znaków, dwa dane wejściowe, liczbę wymierną lub dowolną metodę odpowiednią dla twojego języka.
  • Zamień okresowe i nieokresowe części reprezentacji dziesiętnej na, xaby utworzyć nową liczbę, pozostawiając tę ​​część przed samą dziesiętną. Część okresowa rozpoczyna się zawsze tak szybko, jak to możliwe, aby część nieokresowa była jak najkrótsza. Przykłady są poniżej.
  • Zwraca zamienioną liczbę jako nową część. Wejście niekoniecznie jest zmniejszone, chociaż wyjście powinno być. Format wejściowy może różnić się od formatu wyjściowego.
  • Licznik pstanowi xbędzie liczbą całkowitą o wartości bezwzględnej milion lub mniej i mianownika qdo xbędzie niezerowy całkowitą o wartości bezwzględnej milion lub mniej.
  • Licznik ri mianownik swyniku nie jest gwarantowany na mniej niż milion. Biorąc pod uwagę długość okresowych części tych liczb, zaleca się unikanie bezpośredniej konwersji na liczby zmiennoprzecinkowe.
  • To jest kod golfowy. Najkrótsza odpowiedź w bajtach wygrywa.

Przykłady

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

Na 0końcu przypadku testowego 2 ( 10/7) brakuje : 1428571/100000powinno być 1428571/1000000.
JungHwan Min.

1
Jak wspomniano, nie będzie jednoznacznej odpowiedzi na dane wejście. 1/7może być reprezentowane (0).()(142857) lub (0).(1)(428571), 1mogą być reprezentowane (1).()(), (0).()(9), (0).()(99), (0).(9)(9), itd.
ngenisis

@ngenisis Było to ukryte w przykładach, ale wyraziłem to jasno. Dzięki za opinie :)
Sherlock9

@ R.Kap Stwierdziłem już w wyzwaniu, że najlepiej unikać tutaj pływaków. Istnieją sposoby na znalezienie cyfr dziesiętnych liczby bez konwersji na liczbę zmiennoprzecinkową. Mam nadzieję, że to odpowiada na twoje pytanie :)
Sherlock9

czy zarówno p, jak i q mogą być ujemne?
edc65

Odpowiedzi:


5

Python 2, 292 bajty

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)

Wersja bez golfa, działa zarówno w Pythonie 2, jak i 3. Drukuje również reprezentację dziesiętną.

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)

Spróbujd=10**len(p+a)
Sherlock9,

1
Oto link TIO do łatwego testowania: Wypróbuj online!
Kritixi Lithos,

Dobra robota z twojej odpowiedzi: D. Dodatkowe wskazówki golfa: używać więcej średniki o ile to możliwe, pozbyć przestrzeni w linii if n==0: p='', wykorzystania ``w każdym miejscu, którego używasz str, jak `n/d`zamiast str(n/d)i zmiany nazwy lenna Lz L=len;na początku funkcji.
Sherlock9

@ Sherlock9 Nawet nie wiedziałem o backticks. Dziękuję za wszystkie porady.
Rainer P.,

Żaden problem. Oto kilka innych: D Dwa miejsca na średniki: n=int(b+p+a);d=10**L(p+a)i import fractions as f;g=f.gcd(n,d);return(n/g*s,d/g). Dostaję również 295 bajtów na bieżącą edycję. Czy jest jakaś nowa linia, o której zapominasz pominąć?
Sherlock9

2

Galaretka , 102 101 89 87 83 81 79 78 77 74 bajtów

Trwało to zbyt długo, aby pisać, zdecydowanie zbyt długo, aby debugować, i zdecydowanie wymaga dużo gry w golfa ( osiem siedem sześć pięć czterech linków, święta krowa), ale zgodnie z moją najlepszą wiedzą jest poprawne. Bardzo, bardzo dziękuję Dennisowi za jego pomoc tutaj, szczególnie z pierwszymi dwoma linkami. Ogromne podziękowania dla Rainera P., ponieważ ostatecznie pożyczyłem dużo algorytmu w odpowiedzi na Python.

Edycja gry w golfa: -1 bajt dzięki Xanderhall. Naprawiono błąd związany z niepoprawnym użyciem wbudowanego logicznego NIE. -13 bajtów od gry w golfa w łączach licznika. +1 bajt od naprawienia błędu za negatywny ddzięki Dennisowi. Zrestrukturyzowano łącza, tak aby generowanie licznika odbywało się w jednym łączu. -2 bajty z połączenia drugiego i trzeciego łącza. -4 bajty od przeniesienia niektórych wspólnych elementów trzeciego i czwartego łącza do drugiego i głównego łącza. -2 bajty z usunięcia niektórych niepotrzebnych operatorów łańcuchowych. -2 bajty od zmiany układu łącza licznika. -1 bajt od przejścia Ḣ€do końca drugiego łącza. Naprawiono błąd w głównym linku. -1 bajt ze zmiany Ṫ ... ,Ḣna Ḣ ... ṭ. -3 bajty od przeniesienia łącza licznika do łącza głównego.

Zapraszamy do gry w golfa! Wypróbuj online!

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

Wyjaśnienie

Najpierw wyjaśnię główny link , który wywołuje inne linki.

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

Następnie pierwszy link, który pobiera cyfry.

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.

Teraz drugi link, który pobiera okresowe i nieokresowe części n/doraz wiele innych ciężkich ładunków.

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

Trzecie ogniwo , które daje nasz nowy mianownik.

Ç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.
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.