Exclua o primeiro dígito periódico

17

Todos sabemos que sempre que um número racional é escrito em decimal, o resultado é finalizado ou (eventualmente) periódico. Por exemplo, quando 41/42 é escrito em decimal, o resultado é

0.9 761904 761904 761904 761904 761904 761904 761904 ...

com uma sequência inicial de dígitos 0.9seguida pela sequência 761904repetida várias vezes. (Uma notação conveniente para isso é 0.9(761904)onde os parênteses cercam o bloco de dígitos repetidos.)

Seu objetivo neste desafio é pegar um número racional positivo, excluir o primeiro dígito que faz parte da sequência de repetição e retornar o número racional resultante. Por exemplo, se fizermos isso para 41/42, obtemos

0.9  61904 761904 761904 761904 761904 761904 761904 ...

ou 0.9(619047)abreviado, que é 101/105.

Se o número racional tiver uma expansão decimal final, como 1/4 = 0.25, nada deve acontecer. Você pode pensar em 1/4 como 0.250000000...ou como, 0.249999999...mas em ambos os casos, a exclusão do primeiro dígito da parte repetida deixa o número inalterado.

Detalhes

  • A entrada é um número racional positivo, como um par de números inteiros positivos, representando o numerador e o denominador, ou (se o seu idioma de escolha permitir e você desejar) como algum tipo de objeto de número racional.
  • A saída também é um número racional, também em qualquer forma. Se o resultado for um número inteiro, você poderá retornar o número inteiro em vez de um número racional.
  • Se você usar um par de números como entrada, pode assumir que eles são relativamente primos; se estiver produzindo um par de números como saída, você deve torná-los relativamente primos.
  • Cuidado para encontrar o primeiro dígito que inicia um bloco repetitivo. Por exemplo, alguém poderia escrever 41/42 como 0.97(619047)mas isso não torna 2041/2100 (com expansão decimal 0.97(190476)) uma resposta válida.
  • Você pode supor que, na entrada obtida, o primeiro dígito periódico esteja após o ponto decimal, tornando 120/11= 10.909090909...entrada inválida: (seu primeiro dígito periódico pode ser considerado 0como entrada 10). Você pode fazer o que quiser com essas informações.
  • Este é o : a solução mais curta vence.

Casos de teste

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
fonte
Podemos voltar em 2017vez de 2017/1?
JungHwan Min
Sim, se você estiver fazendo a coisa do número racional. (Se você está fazendo a coisa pair-of-inteiros, então eu não tenho certeza o que mais você ia voltar, exceto o par (2017,1).)
Misha Lavrov
A entrada pode ser redutível (não totalmente simplificada)? Por exemplo, pode 2/4acontecer na entrada?
user202729
1
Se entrada é 120/11a resposta correta 111/11ou 210/11?
kasperd
2
@kasperd Hein, esse é um caso em que eu não tinha pensado ... Gostaria de dizer, 111/11exceto que a resposta mais votada no momento retorna 210/11, então vou deixar você escolher para evitar a invalidação das respostas existentes.
Misha Lavrov

Respostas:

13

Wolfram Language (Mathematica) , 59 bytes

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

Experimente online!

Explicação

RealDigits@#

Encontre os dígitos decimais da entrada.

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

Se houver dígitos repetidos, RotateLefteles. ( List@@#impede que o código tente girar o último dígito decimal se o número racional estiver terminando).

FromDigits@

Converta para racional.

JungHwan Min
fonte
Muito esperto mesmo!
DavidC
6

Geléia , 36 32 31 30 bytes

-1 byte graças a Erik, o Outgolfer !

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

Experimente online!

Deve estar correto. Imprecisão de ponto flutuante adiciona 3 bytes para +.Ḟ.

Depende da entrada ser irredutível.


Explicação

Isso depende de:

  • Deixe o numerador n/dna sua forma mais simples. Em seguida, o link ọ2,5Ṁaplicado dfornecerá o número de dígitos não periódicos após o ponto de raiz.

ọ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
fonte
30 bytes
Erik the Outgolfer
@EriktheOutgolfer Thanks!
user202729
5

Python 2 , 237 235 214 bytes

-21 bytes graças ao 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])))

Experimente online!

A entrada é feita como uma tupla (numerator, denominator); output é um fractions.Fractionobjeto.

Ele usa um método no estilo de divisão longa para obter os dígitos inicial e repetitivo da resposta, depois move o primeiro dígito repetitivo para o final e usa a manipulação de strings e fraction.Fractionpara convertê-lo novamente em uma proporção.

Versão não destruída:

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

Experimente online!

Freira Furada
fonte
@ Mr.Xcoder editada
Leaky Nun
2

Wolfram Language (Mathematica) , 70 67 bytes

Graças a esta dica (agora excluída) por -3 bytes!

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

Experimente online!

Uma porta da minha resposta Jelly . Mais do que a resposta existente do Mathematica em 8 bytes ...

A função aceita 2 entradas [denominator, numerator], de modo que GCD[denominator, numerator] == 1.

user202729
fonte
1

Perl 6 , 102 bytes

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

Tente

Pega um número Rational e retorna um número Rational ou 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
    )
}

Nota manipulará denominadores até, uint64.Range.maxpara manipular denominadores maiores, use FatRat(9 x$1.chars) Experimente .

Brad Gilbert b2gills
fonte