Usuń pierwszą cyfrę okresową

17

Wszyscy wiemy, że ilekroć liczba wymierna jest zapisywana dziesiętnie, wynik kończy się albo (ewentualnie) jest okresowy. Na przykład, gdy liczba 41/42 jest zapisywana dziesiętnie, wynikiem jest

0.9 761904 761904 761904 761904 761904 761904 761904 ...

z początkową sekwencją cyfr, 0.9a następnie sekwencją 761904powtarzaną w kółko. (Wygodnym zapisem jest 0.9(761904)to, gdy nawiasy otaczają blok powtarzających się cyfr).

Twoim celem w tym wyzwaniu jest pobranie dodatniej liczby wymiernej, usunięcie pierwszej cyfry wchodzącej w skład powtarzalnej sekwencji i zwrócenie wynikowej liczby wymiernej. Na przykład, jeśli zrobimy to do 41/42, otrzymamy

0.9  61904 761904 761904 761904 761904 761904 761904 ...

lub 0.9(619047)w skrócie, czyli 101/105.

Jeśli liczba wymierna ma końcowe rozszerzenie dziesiętne, tak jak 1/4 = 0.25, nic nie powinno się wydarzyć. Możesz myśleć o 1/4 zarówno jako, jak 0.250000000...i tak, 0.249999999...ale w każdym przypadku usunięcie pierwszej cyfry powtarzającej się części pozostawia liczbę bez zmian.

Detale

  • Dane wejściowe to dodatnia liczba wymierna, albo jako para dodatnich liczb całkowitych reprezentujących licznik i mianownik, lub (jeśli twój język na to pozwala i chcesz) jako jakiś obiekt liczby wymiernej.
  • Wynik jest również liczbą wymierną, również w dowolnej formie. Jeśli wynikiem jest liczba całkowita, możesz zwrócić liczbę całkowitą zamiast liczby wymiernej.
  • Jeśli weźmiesz parę liczb jako dane wejściowe, możesz założyć, że są względnie pierwsze; jeśli tworzysz parę liczb jako wynik, musisz uczynić je względnie pierwszymi.
  • Uważaj, aby znaleźć pierwszą cyfrę rozpoczynającą powtarzający się blok. Na przykład można napisać 41/42 jako, 0.97(619047)ale to nie czyni 0.97(190476)poprawnej odpowiedzi 2041/2100 (z rozszerzeniem dziesiętnym ).
  • Możesz założyć, że na otrzymywanym wejściu pierwsza cyfra okresowa znajduje się po przecinku, co oznacza 120/11= 10.909090909...nieprawidłowe wejście: (jej pierwszą cyfrą okresową może być 0in 10). Na podstawie takich danych możesz zrobić co chcesz.
  • To jest : wygrywa najkrótsze rozwiązanie.

Przypadki testowe

41/42 => 101/105
101/105 => 193/210
193/210 => 104/105
104/105 => 19/21
1/3 => 1/3
1/4 => 1/4
2017/1 => 2017/1
1/7 => 3/7
1/26 => 11/130
1234/9999 => 2341/9999
Misza Ławrow
źródło
Czy możemy wrócić 2017zamiast 2017/1?
JungHwan Min.
Tak, jeśli robisz liczbę wymierną. (Jeśli robisz parę liczb całkowitych, to nie jestem pewien, co jeszcze byś zwrócił oprócz pary (2017,1).)
Misha Lavrov,
Czy dane wejściowe mogą być redukowalne (nie w pełni uproszczone)? Na przykład może się 2/4zdarzyć na wejściu?
user202729,
1
Jeśli dane wejściowe są 120/11poprawną odpowiedzią 111/11lub 210/11?
kasperd
2
@ Kasperd Huh, to przypadek, o którym nie myślałem ... Chciałbym powiedzieć, 111/11z wyjątkiem tego, że w tej chwili powraca najbardziej pozytywna odpowiedź 210/11, więc pozwolę ci wybrać, aby uniknąć unieważnienia istniejących odpowiedzi.
Misza Ławrow,

Odpowiedzi:

13

Wolfram Language (Mathematica) , 59 bajtów

FromDigits@MapAt[RotateLeft@*List@@#&,RealDigits@#,{1,-1}]&

Wypróbuj online!

Wyjaśnienie

RealDigits@#

Znajdź cyfry dziesiętne wejścia.

MapAt[RotateLeft@*List@@#&, ..., {1,-1}]

Jeśli występują powtarzające się cyfry, to RotateLeftone. ( List@@#uniemożliwia kodowi obrócenie ostatniej cyfry dziesiętnej, jeśli liczba wymierna się kończy).

FromDigits@

Konwertuj na wymierne.

JungHwan Min
źródło
Rzeczywiście bardzo sprytny!
DavidC
6

Galaretka , 36 32 31 30 bajtów

-1 bajt dzięki Erik the Outgolfer !

ọ2,5Ṁ⁵*©×Ɠ÷µ×⁵_Ḟ$+Ḟ,®×³+.Ḟ÷g/$

Wypróbuj online!

Powinno być poprawne Niedokładność zmiennoprzecinkowa dodaje 3 bajty dla +.Ḟ.

Polega na tym, że dane wejściowe są nieredukowalne.


Wyjaśnienie

Zależy to od:

  • Niech licznik będzie n/dw najprostszej formie. Następnie ọ2,5Ṁzastosowane łącze dpoda liczbę nieokresowych cyfr po punkcie podstawy.

ọ2,5Ṁ⁵*©×Ɠ÷µ×⁵_Ḟ$+Ḟ,®×³+.Ḟ÷g/$     Main link (monad take d as input)

    Ṁ                              Maximum
ọ                                  order of
 2,5                               2 or 5 on d
     ⁵*                            10 power
       ©                           Store value to register ®.
        ×Ɠ                         Multiply by eval(input()) (n)
          ÷                        Divide by first argument (d).
                                   Now the current value is n÷d×®.
           µ                       With that value,
            ×⁵                     Multiply by ⁵ = 10
              _Ḟ$                  subtract floor of self
                 +Ḟ                add floor or value (above)
                                   Given 123.45678, will get 123.5678
                                   (this remove first digit after `.`)
                   ,®              Pair with ®.
                     ׳            Scale
                       +.Ḟ         Round to integer
                          ÷g/$     Simplify fraction
użytkownik202729
źródło
30 bajtów
Erik the Outgolfer,
@EriktheOutgolfer Thanks!
user202729,
5

Python 2 , 237 235 214 bajtów

-21 bajtów dzięki Mr. Xcoder

from fractions import*
F=Fraction
n,d=input()
i=n/d
n%=d
R=[]
D=[]
while~-(n in R):R+=n,;n*=10;g=n/d;n%=d;D+=g,
x=R.index(n)
r=D[x+1:]+[D[x]]
print i+F(`r`[1::3])/F('9'*len(r))/10**x+F("0."+"".join(map(str,D[:x])))

Wypróbuj online!

Dane wejściowe są wykonywane jako krotka (numerator, denominator); wynik jest fractions.Fractionobiektem.

Wykorzystuje metodę w stylu dzielenia długiego, aby uzyskać początkowe i powtarzające się cyfry odpowiedzi, a następnie przesuwa pierwszą powtarzającą się cyfrę do końca, używa manipulacji ciągiem i fraction.Fractionprzekształca ją z powrotem na współczynnik.

Wersja bez golfa:

import fractions

num, denom = input()
integer_part, num = divmod(num, denom)

remainders = []
digits = []
current_remainder = num
while current_remainder not in remainders:
    remainders.append(current_remainder)
    current_remainder *= 10
    digit, current_remainder = divmod(current_remainder, denom)
    digits.append(digit)

remainder_index = remainders.index(current_remainder)
start_digits = digits[:remainder_index]
repeated_digits = digits[remainder_index:]

repeated_digits.append(repeated_digits.pop(0))

start_digits_str = "".join(map(str, start_digits))
repeated_digits_str = "".join(map(str, repeated_digits))

print(integer_part+int(repeated_digits_str)/fractions.Fraction('9'*(len(repeated_digits_str)))/10**len(start_digits_str)+fractions.Fraction("0."+start_digits_str))
Esolanging Fruit
źródło
5

Python 3 , 177 173 169 bajtów

from fractions import*
def f(n,d):
 i=1;r=[]
 while~-(i%d in r):r+=[i%d];i*=10
 r=10**r.index(i%d);u=i-r;v=i//r-1;t=u//d*n
 return Fraction(t-t%v+t%v*10//v+t%v*10%-~v,u)

Wypróbuj online!

Leaky Nun
źródło
@ Mr.Xcoder edytowany
Leaky Nun
1

Perl 6 , 102 bajtów

{$/=.base-repeating;(+$0//$0~0)+([~]([$1.comb].rotate)/(9 x$1.chars)*.1**(($0~~/\.<(.*/).chars)if $1)}

Spróbuj

Pobiera liczbę wymierną i zwraca liczbę wymierną lub Int .

Rozszerzony:

{  # bare block lambda with implicit Rational parameter 「$_」

  $/ = .base-repeating; # store in 「$/」 the two strings '0.9' '761904'

    # handle the non-repeating part
    (
      +$0        # turn into a number
      // $0 ~ 0  # if that fails append 0 (handle cases like '0.')
    )

  +

    # handle the repeating part
    (
          [~]( [$1.comb].rotate ) # rotate the repeating part
        /
          ( 9 x $1.chars )        # use a divisor that will result in a repeating number

        *

         # offset it an appropriate amount

         .1 ** (
           ( $0 ~~ / \. <( .* / ).chars # count the characters after '.'
         )

      if $1  # only do the repeating part if there was a repeating part
    )
}

Uwaga będzie obsługiwać mianowniki aż do uint64.Range.maxobsługi większych mianowników. FatRat(9 x$1.chars) Wypróbuj .

Brad Gilbert b2gills
źródło