Eliminar el primer dígito periódico

17

Todos sabemos que cada vez que se escribe un número racional en decimal, el resultado termina o es (eventualmente) periódico. Por ejemplo, cuando 41/42 se escribe en decimal, el resultado es

0.9 761904 761904 761904 761904 761904 761904 761904 ...

con una secuencia inicial de dígitos 0.9seguida por la secuencia 761904repetida una y otra vez. (Una notación conveniente para esto es 0.9(761904)donde los paréntesis rodean el bloque de dígitos repetidos).

Su objetivo en este desafío es tomar un número racional positivo, eliminar el primer dígito que forma parte de la secuencia repetitiva y devolver el número racional resultante. Por ejemplo, si hacemos esto a 41/42, obtenemos

0.9  61904 761904 761904 761904 761904 761904 761904 ...

o 0.9(619047)para abreviar, que es 101/105.

Si el número racional tiene una expansión decimal final, como 1/4 = lo 0.25hace, no debería pasar nada. Puede pensar en 1/4 como 0.250000000...o como, 0.249999999...pero en cualquier caso, eliminar el primer dígito de la parte que se repite deja el número sin cambios.

Detalles

  • La entrada es un número racional positivo, ya sea como un par de enteros positivos que representan el numerador y el denominador, o (si su lenguaje de elección lo permite y desea) como algún tipo de objeto de número racional.
  • La salida también es un número racional, también en cualquier forma. Si el resultado es un entero, puede devolver el entero en lugar de un número racional.
  • Si toma un par de números como entrada, puede suponer que son relativamente primos; si produce un par de números como salida, debe hacer que sean relativamente primos.
  • Tenga cuidado de encontrar el primer dígito que comienza un bloque repetitivo. Por ejemplo, uno podría escribir 41/42 como 0.97(619047)pero eso no hace que 2041/2100 (con la expansión decimal 0.97(190476)) sea una respuesta válida.
  • Puede suponer que en la entrada que obtiene, el primer dígito periódico va después del punto decimal, haciendo 120/11= 10.909090909...entrada no válida: (su primer dígito periódico podría considerarse el 0in 10). Puede hacer lo que quiera en dicha entrada.
  • Este es el : la solución más corta gana.

Casos de prueba

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
fuente
¿Podemos volver en 2017lugar de 2017/1?
JungHwan Min
Sí, si estás haciendo lo racional. (Si estás haciendo la cosa del par de enteros, entonces no estoy seguro de qué otra cosa volverías excepto el par (2017,1).)
Misha Lavrov
¿Puede la entrada ser reducible (no completamente simplificada)? Por ejemplo, ¿puede 2/4suceder en la entrada?
user202729
1
Si input es 120/11la respuesta correcta 111/11o 210/11?
kasperd
2
@kasperd Huh, ese es un caso en el que no había pensado ... Quisiera decir 111/11que la respuesta más altamente votada en este momento regresa 210/11, así que te dejaré elegir para evitar invalidar las respuestas existentes.
Misha Lavrov

Respuestas:

13

Wolfram Language (Mathematica) , 59 bytes

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

Pruébalo en línea!

Explicación

RealDigits@#

Encuentra los dígitos decimales de la entrada.

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

Si hay dígitos repetidos, RotateLeftellos. ( List@@#evita que el código intente rotar el último dígito decimal si el número racional está terminando).

FromDigits@

Convierte a racional.

JungHwan Min
fuente
Muy inteligente de hecho!
DavidC
6

Gelatina , 36 32 31 30 bytes

-1 byte gracias a Erik the Outgolfer !

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

Pruébalo en línea!

Debe ser correcto La imprecisión de coma flotante agrega 3 bytes para +.Ḟ.

Se basa en que la entrada sea irreducible.


Explicación

Esto se basa en:

  • Deje que el numerador esté n/den su forma más simple. Luego, el enlace ọ2,5Ṁaplicado ddará el número de dígitos no periódicos después del punto de la raíz.

ọ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
usuario202729
fuente
30 bytes
Erik the Outgolfer
@EriktheOutgolfer ¡Gracias!
user202729
5

Python 2 , 237 235 214 bytes

-21 bytes gracias al Sr. 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])))

Pruébalo en línea!

La entrada se realiza como una tupla (numerator, denominator); La salida es un fractions.Fractionobjeto.

Esto usa un método de estilo de división larga para obtener los dígitos iniciales y repetitivos de la respuesta, luego mueve el primer dígito repetitivo al final y usa la manipulación de cadenas y la fraction.Fractionconvierte nuevamente a una proporción.

Versión sin golf:

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))
Fruta Esolanging
fuente
5

Python 3 , 177 173 169 bytes

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)

Pruébalo en línea!

Monja permeable
fuente
@ Mr.Xcoder editado
Leaky Nun
2

Wolfram Language (Mathematica) , 70 67 bytes

¡Gracias a este consejo (ahora eliminado) por -3 byte!

(x=10^Max@IntegerExponent[#,{2,5}];(Floor@#+Mod[10#,1])/x&[x#2/#])&

Pruébalo en línea!

Un puerto de mi respuesta Jelly . Más largo que la respuesta existente de Mathematica en 8 bytes ...

La función toma 2 entradas [denominator, numerator], de modo que GCD[denominator, numerator] == 1.

usuario202729
fuente
1

Perl 6 , 102 bytes

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

Intentalo

Toma un número racional y devuelve un número racional o int .

Expandido:

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

Note manejará denominadores hasta uint64.Range.maxpara manejar denominadores más grandes . FatRat(9 x$1.chars) Pruébalo .

Brad Gilbert b2gills
fuente