Supprimer le premier chiffre périodique

17

Nous savons tous que chaque fois qu'un nombre rationnel est écrit en décimal, le résultat est soit final soit (éventuellement) périodique. Par exemple, lorsque 41/42 est écrit en décimal, le résultat est

0.9 761904 761904 761904 761904 761904 761904 761904 ...

avec une séquence initiale de chiffres 0.9suivie de la séquence 761904répétée encore et encore. (Une notation pratique pour cela est l' 0.9(761904)endroit où les parenthèses entourent le bloc de chiffres répétitifs.)

Votre objectif dans ce défi est de prendre un nombre rationnel positif, de supprimer le premier chiffre faisant partie de la séquence répétée et de renvoyer le nombre rationnel résultant. Par exemple, si nous faisons cela au 41/42, nous obtenons

0.9  61904 761904 761904 761904 761904 761904 761904 ...

ou 0.9(619047)pour faire court, qui est 101/105.

Si le nombre rationnel a une expansion décimale terminale, comme 1/4 = le 0.25fait, rien ne devrait se produire. Vous pouvez penser à 1/4 comme 0.250000000...ou comme 0.249999999...mais dans les deux cas, la suppression du premier chiffre de la partie répétitive laisse le nombre inchangé.

Détails

  • L'entrée est un nombre rationnel positif, soit sous la forme d'une paire d'entiers positifs représentant le numérateur et le dénominateur, ou (si votre langue de choix le permet et si vous le souhaitez) comme une sorte d'objet de nombre rationnel.
  • La sortie est également un nombre rationnel, également sous l'une ou l'autre forme. Si le résultat est un entier, vous pouvez renvoyer l'entier au lieu d'un nombre rationnel.
  • Si vous prenez une paire de nombres en entrée, vous pouvez supposer qu'ils sont relativement premiers; si vous produisez une paire de nombres en sortie, vous devez les rendre relativement premiers.
  • Veillez à trouver le premier chiffre qui commence un bloc répétitif. Par exemple, on pourrait écrire 41/42 comme 0.97(619047)mais cela ne fait pas de 2041/2100 (avec l'expansion décimale 0.97(190476)) une réponse valide.
  • Vous pouvez supposer que dans l'entrée que vous obtenez, le premier chiffre périodique est après le point décimal, ce qui 120/11= 10.909090909...entrée non valide: (son premier chiffre périodique pourrait être considéré comme le 0dans 10). Vous pouvez faire tout ce que vous voulez sur une telle entrée.
  • C'est le : la solution la plus courte l'emporte.

Cas de test

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
Misha Lavrov
la source
Pouvons-nous revenir 2017au lieu de 2017/1?
JungHwan Min
Oui, si vous faites la chose du nombre rationnel. (Si vous faites la chose paire de nombres entiers, alors je ne sais pas quoi d'autre vous retourneriez sauf la paire (2017,1).)
Misha Lavrov
L'entrée peut-elle être réductible (pas entièrement simplifiée)? Par exemple, peut 2/4se produire dans l'entrée?
user202729
1
Si la saisie est 120/11la bonne réponse 111/11ou 210/11?
kasperd
2
@kasperd Huh, c'est un cas auquel je n'avais pas pensé ... Je voudrais dire 111/11sauf que la réponse la plus votée du moment revient 210/11, donc je vous laisse choisir pour éviter d'invalider les réponses existantes.
Misha Lavrov

Réponses:

13

Wolfram Language (Mathematica) , 59 octets

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

Essayez-le en ligne!

Explication

RealDigits@#

Trouvez les chiffres décimaux de l'entrée.

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

S'il y a des chiffres qui se répètent, RotateLefteux. ( List@@#empêche le code de tenter de faire pivoter le dernier chiffre décimal si le nombre rationnel se termine).

FromDigits@

Convertissez en rationnel.

JungHwan Min
la source
Très intelligent en effet!
DavidC
6

Gelée , 36 32 31 30 octets

-1 octet merci à Erik l'Outgolfer !

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

Essayez-le en ligne!

Doit être correct. L'imprécision en virgule flottante ajoute 3 octets pour +.Ḟ.

Dépend de l'entrée irréductible.


Explication

Cela repose sur:

  • Que le numérateur soit n/ddans sa forme la plus simple. Ensuite, le lien ọ2,5Ṁappliqué ddonnera le nombre de chiffres non périodiques après le point de radix.

ọ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
user202729
la source
30 octets
Erik the Outgolfer
@EriktheOutgolfer Merci!
user202729
5

Python 2 , 237 235 214 octets

-21 octets grâce à M. 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])))

Essayez-le en ligne!

L'entrée se fait comme un tuple (numerator, denominator); la sortie est un fractions.Fractionobjet.

Cela utilise une méthode de style à longue division pour obtenir les chiffres de début et de répétition de la réponse, puis déplace le premier chiffre de répétition à la fin et utilise la manipulation de chaînes et fraction.Fractionpour la reconvertir en un rapport.

Version non golfée:

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
la source
5

Python 3 , 177 173 169 169 octets

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)

Essayez-le en ligne!

Leaky Nun
la source
@ Mr.Xcoder édité
Leaky Nun
1

Perl 6 , 102 octets

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

Essayez-le

Prend un nombre Rational et renvoie un nombre Rational ou Int .

Étendu:

{  # 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
    )
}

Remarque gérera les dénominateurs jusqu'à uint64.Range.maxgérer les dénominateurs plus grands. Utilisez FatRat(9 x$1.chars) Try it .

Brad Gilbert b2gills
la source