Удалить первую периодическую цифру

17

Все мы знаем, что всякий раз, когда рациональное число записывается в десятичном виде, результат либо завершается, либо (в конечном итоге) периодический. Например, когда 41/42 записано в десятичном виде, результат

0.9 761904 761904 761904 761904 761904 761904 761904 ...

с начальной последовательностью цифр, 0.9за которой следует последовательность, 761904повторяемая снова и снова. (Удобное обозначение для этого - то, 0.9(761904)где круглые скобки окружают блок повторяющихся цифр.)

Ваша задача в этой задаче - взять положительное рациональное число, удалить первую цифру, являющуюся частью повторяющейся последовательности, и вернуть полученное рациональное число. Например, если мы сделаем это до 41/42, мы получим

0.9  61904 761904 761904 761904 761904 761904 761904 ...

или 0.9(619047)для краткости 101/105.

Если рациональное число имеет конечное десятичное разложение, как у 1/4 = 0.25, ничего не должно происходить. Вы можете думать о 1/4 либо как, 0.250000000...либо как, 0.249999999...но в любом случае удаление первой цифры повторяющейся части оставляет число без изменений.

Детали

  • Входные данные представляют собой положительное рациональное число, либо в виде пары натуральных чисел, представляющих числитель и знаменатель, либо (если ваш язык выбора позволяет это сделать, и вы хотите) в качестве объекта рационального числа.
  • Выход также является рациональным числом, также в любой форме. Если результатом является целое число, вы можете вернуть целое число вместо рационального числа.
  • Если в качестве входных данных взять пару чисел, вы можете предположить, что они относительно простые; если вы выводите пару чисел в качестве выходных данных, вы должны сделать их относительно простыми.
  • Будьте осторожны, чтобы найти первую цифру, которая начинает повторяющийся блок. Например, можно написать 41/42 как, 0.97(619047)но это не делает 2041/2100 (с десятичным расширением 0.97(190476)) действительным ответом.
  • Можно предположить , что на входе вы получаете, то первый периодический цифра после десятичной точки, что делает 120/11= 10.909090909...неверный ввод: (его первый периодический разряд можно считать 0в 10). Вы можете делать все, что вам нравится на таком входе.
  • Это : выигрывает самое короткое решение.

Контрольные примеры

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
Миша лавров
источник
Можем ли мы вернуться 2017вместо 2017/1?
JungHwan Мин
Да, если вы делаете рациональное число. (Если вы занимаетесь парой целых чисел, то я не уверен, что бы вы вернули, кроме пары (2017,1).)
Миша Лавров
Может ли ввод быть сводимым (не полностью упрощенным)? Например, может 2/4случиться на входе?
user202729
1
Если ввод является 120/11правильным ответом 111/11или 210/11?
kasperd
2
@kasperd Да, это тот случай, о котором я не задумывался ... Я хотел бы сказать, 111/11за исключением того, что возвращается наиболее высоко голосованный ответ 210/11, поэтому я позволю вам выбрать, чтобы избежать аннулирования существующих ответов.
Миша Лавров

Ответы:

13

Wolfram Language (Mathematica) , 59 байт

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

Попробуйте онлайн!

объяснение

RealDigits@#

Найти десятичные цифры ввода.

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

Если есть повторяющиеся цифры, RotateLeftих. ( List@@#препятствует тому, чтобы код попытался повернуть последнюю десятичную цифру, если рациональное число заканчивается).

FromDigits@

Преобразовать в рациональное.

Юнг Хван Мин
источник
Очень умный действительно!
DavidC
6

Желе , 36 32 31 30 байт

-1 байт благодаря Эрику Аутгольферу !

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

Попробуйте онлайн!

Должно быть правильно. Неточность с плавающей точкой добавить 3 байта для +.Ḟ.

Полагается на то, что ввод является неприводимым.


объяснение

Это зависит от:

  • Пусть числитель будет n/dв самом простом виде. Затем ссылка, ọ2,5Ṁк которой dбудет применяться , даст число непериодических цифр после точки радиуса.

ọ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
источник
30 байтов
Эрик Outgolfer
@EriktheOutgolfer Спасибо!
user202729
5

Python 2 , 237 235 214 байт

-21 байт благодаря мистеру 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])))

Попробуйте онлайн!

Ввод выполняется в виде кортежа (numerator, denominator); вывод является fractions.Fractionобъектом.

При этом используется метод в стиле длинного деления для получения начальных и повторяющихся цифр ответа, затем перемещение первой повторяющейся цифры в конец и использование манипуляции со строками и fraction.Fractionдля преобразования ее обратно в отношение.

Безголовая версия:

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
источник
5

Python 3 , 177 173 169 байт

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)

Попробуйте онлайн!

Пропитанная монахиня
источник
@ Mr.Xcoder отредактировано
Leaky Nun
2

Wolfram Language (Mathematica) , 70 67 байт

Благодаря этому совету (теперь удален) за -3 байта!

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

Попробуйте онлайн!

Порт моего желе ответа . Дольше, чем существующий ответ Mathematica на 8 байт ...

Функция принимает 2 входа [denominator, numerator], так что GCD[denominator, numerator] == 1.

user202729
источник
1

Perl 6 , 102 байта

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

Попытайся

Принимает Rational number и возвращает Rational или Int .

Expanded:

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

Примечание будет обрабатывать знаменатели вплоть uint64.Range.maxдо обработки больших знаменателей использовать FatRat(9 x$1.chars) Попробуйте .

Брэд Гилберт b2gills
источник