Hapus digit periodik pertama

17

Kita semua tahu bahwa setiap kali angka rasional ditulis dalam desimal, hasilnya adalah penghentian atau (akhirnya) periodik. Misalnya, ketika 41/42 ditulis dalam desimal, hasilnya adalah

0.9 761904 761904 761904 761904 761904 761904 761904 ...

dengan urutan awal digit 0.9diikuti oleh urutan 761904berulang-ulang. (A notasi nyaman untuk ini adalah 0.9(761904)di mana kurung mengelilingi blok mengulangi digit.)

Tujuan Anda dalam tantangan ini adalah untuk mengambil angka rasional positif, menghapus angka pertama yang merupakan bagian dari urutan berulang, dan mengembalikan nomor rasional yang dihasilkan. Misalnya, jika kita melakukan ini pada 41/42, kita dapatkan

0.9  61904 761904 761904 761904 761904 761904 761904 ...

atau 0.9(619047)singkatnya, yaitu 101/105.

Jika bilangan rasional memiliki penghentian ekspansi desimal, seperti 1/4 = 0.25tidak, tidak ada yang terjadi. Anda dapat menganggap 1/4 sebagai 0.250000000...atau sebagai 0.249999999...tetapi dalam kedua kasus tersebut, menghapus digit pertama dari bagian berulang membuat angka tidak berubah.

Detail

  • Masukan adalah bilangan rasional positif, baik sebagai pasangan bilangan bulat positif yang mewakili pembilang dan penyebut, atau (jika bahasa pilihan Anda memungkinkannya dan Anda ingin) sebagai semacam objek bilangan rasional.
  • Outputnya juga bilangan rasional, juga dalam bentuk apa pun. Jika hasilnya bilangan bulat, Anda dapat mengembalikan bilangan bulat bukan angka rasional.
  • Jika menggunakan sepasang angka sebagai input, Anda dapat menganggapnya relatif prima; jika menghasilkan sepasang angka sebagai output, Anda harus membuatnya menjadi prima.
  • Berhati-hatilah agar Anda menemukan digit pertama yang memulai blok berulang. Sebagai contoh, seseorang dapat menulis 41/42 sebagai 0.97(619047)tetapi itu tidak membuat 2041/2100 (dengan ekspansi desimal0.97(190476) ) jawaban yang valid.
  • Anda dapat mengasumsikan bahwa dalam input yang Anda dapatkan, digit periodik pertama adalah setelah titik desimal, menjadikan 120/11= 10.909090909...input tidak valid: (digit periodik pertamanya dapat dianggap sebagai 0dalam10 ). Anda dapat melakukan apapun yang Anda suka pada input tersebut.
  • Ini adalah : solusi terpendek menang.

Uji kasus

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
sumber
Bisakah kita kembali 2017bukan 2017/1?
JungHwan Min
Ya, jika Anda melakukan hal angka rasional. (Jika Anda melakukan hal pair-of-integer, maka saya tidak yakin apa lagi yang akan Anda kembalikan kecuali pasangan tersebut (2017,1).)
Misha Lavrov
Apakah input dapat direduksi (tidak sepenuhnya disederhanakan)? Misalnya, dapatkah 2/4terjadi pada input?
user202729
1
Jika input adalah 120/11jawaban yang benar 111/11atau 210/11?
kasperd
2
@kasperd Huh, itu adalah kasus yang saya tidak pikirkan ... Saya ingin mengatakan 111/11kecuali bahwa jawaban yang paling tinggi saat ini kembali 210/11, jadi saya akan membiarkan Anda memilih untuk menghindari membatalkan jawaban yang ada.
Misha Lavrov

Jawaban:

13

Bahasa Wolfram (Mathematica) , 59 byte

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

Cobalah online!

Penjelasan

RealDigits@#

Temukan digit desimal input.

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

Jika ada angka berulang, RotateLeftmereka. ( List@@#mencegah kode dari upaya untuk memutar digit desimal terakhir jika nomor rasional diakhiri).

FromDigits@

Konversikan ke rasional.

JungHwan Min
sumber
Sangat pintar!
DavidC
6

Jelly , 36 32 31 30 byte

-1 byte terima kasih kepada Erik the Outgolfer !

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

Cobalah online!

Seharusnya benar. Ketidaktepatan titik apung tambahkan 3 byte untuk +.Ḟ.

Bergantung pada input yang tidak dapat direduksi.


Penjelasan

Ini bergantung pada:

  • Biarkan pembilang n/ddalam bentuk yang paling sederhana. Kemudian tautan yang ọ2,5Ṁditerapkan dakan memberikan angka digit non-periodik setelah titik 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
pengguna202729
sumber
30 byte
Erik the Outgolfer
@EriktheOutgolfer Terima kasih!
user202729
5

Python 2 , 237 235 214 byte

-21 byte terima kasih kepada Tn. 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])))

Cobalah online!

Input dilakukan sebagai tuple (numerator, denominator); output adalah fractions.Fractionobjek.

Ini menggunakan metode gaya pembagian panjang untuk mendapatkan digit awal dan berulang jawaban, kemudian memindahkan digit berulang pertama ke akhir dan menggunakan manipulasi string dan fraction.Fractionmengubahnya kembali menjadi rasio.

Versi tidak disatukan:

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))
Buah Esolanging
sumber
5

Python 3 , 177 173 169 byte

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)

Cobalah online!

Biarawati Bocor
sumber
@ Mr.Xcoder diedit
Leaky Nun
2

Bahasa Wolfram (Mathematica) , 70 67 byte

Berkat tip ini (sekarang dihapus) untuk -3 byte!

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

Cobalah online!

Port jawaban Jelly saya . Lebih lama dari jawaban Mathematica yang ada sebesar 8 byte ...

Fungsi mengambil 2 input [denominator, numerator], sehingga GCD[denominator, numerator] == 1.

pengguna202729
sumber
1

Perl 6 , 102 byte

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

Cobalah

Mengambil nomor Rasional dan mengembalikan nomor Rasional atau Int .

Diperluas:

{  # 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 akan menangani penyebut hingga uint64.Range.maxmenangani penyebut yang lebih besar gunakan FatRat(9 x$1.chars) Cobalah .

Brad Gilbert b2gills
sumber