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

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.


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


@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))



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 .

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.