最初の定期的な数字を削除する


17

有理数が10進数で書かれているときはいつでも、結果は終了するか(最終的に)周期的であることを知っています。たとえば、41/42が10進数で記述されている場合、結果は次のようになります。

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 =のように、有理数の末尾に10進数の展開がある場合0.25、何も起こりません。あなたはどちらかと1/4の考えることができる0.250000000...かのように0.249999999...番号が変わらず、繰り返し部分の葉の最初の数字を削除するが、いずれの場合も。

詳細

  • 入力は、分子と分母を表す正の整数のペアとして、または(選択する言語で許可され、必要な場合)何らかの種類の有理数オブジェクトとしての正の有理数です。
  • 出力も有理数であり、どちらの形式でもあります。結果が整数の場合、有理数の代わりに整数を返します。
  • 入力として数値のペアを使用する場合、それらは比較的素数であると想定できます。出力として数値のペアを生成する場合、それらを比較的素数にする必要があります。
  • 繰り返しブロックを開始する最初の数字を見つけることに注意してください。たとえば、41/42と書くこともできます0.97(619047)が、これは2041/2100(10進数展開0.97(190476))を有効な答えにしません。
  • あなたは、あなたが得る入力で、第1の周期の数字であると仮定してもよいの後になって、小数点120/11= 10.909090909...(その最初の定期的な数字が考えられる:無効な入力010)。あなたはそのような入力であなたが好きなことをするかもしれません。
  • これがです。最短のソリューションが勝ちです。

テストケース

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か?
ジョンファンミン

はい、有理数のことをやっているなら。(もしあなたが整数のペアの事をしているなら、私はあなたがペア以外に何を返すだろうか分からない(2017,1)。)
ミシャ・ラヴロフ

入力を削減できる可能性があります(完全に簡略化されていない)。たとえば2/4、入力で発生する可能性がありますか?
user202729

1
入力が120/11正解である111/11場合、または210/11
カスペルド

2
@kasperd Huh、それは私が考えていなかったケースです...私は111/11、現時点で最も高く投票された答えが返されることを除いて言いたい210/11ので、既存の答えを無効にしないように選択させていただきます。
ミシャラヴロフ

回答:


13

Wolfram言語(Mathematica)、59バイト

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

オンラインでお試しください!

説明

RealDigits@#

入力の10進数を見つけます。

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

繰り返し数字がある場合、RotateLeftそれら。(List@@#有理数が終了している場合、コードが最後の10進数を回転させないようにします)。

FromDigits@

有理数に変換します。


本当に賢い!
DavidC

6

ゼリー36 32 31 30バイト

Erik the Outgolferのおかげで-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


@EriktheOutgolferありがとう!
user202729

5

Pythonの2237の 235 214バイト

Xcoder氏のおかげで-21バイト

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



1

Perl 6、102バイト

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

それを試してみてください

取り合理番号を返しますし、合理的のInt番号を。

拡張:

{  # 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は、uint64.Range.maxより大きな分母を使用するまで、分母を処理しますFatRat(9 x$1.chars) Try itを使用ます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.