いくつかの周期的および非周期的部分を交換します


21

すべての有理数の10進表現にp/qは、次の形式で周期的なテール、非周期的なヘッド、および小数点の前のセクションがあります。

(before decimal point).(non-periodic)(periodic)

以下に例を示します。

1/70 = 0.0142857... = (0).(0)(142857)
10/7 = 1.428571... = (1).()(428571)            ## no non-periodic part
1/13 = 0.076923... = (0).()(076923)
3/40 = 0.075 = (0).(075)()                    ## no periodic part
-2/15 = -0.13... = -(0).(1)(3)                ## negative
75/38 = 1.9736842105263157894... = (1).(9)(736842105263157894)
                                              ## periodic part longer than float can handle
25/168 = 0.148809523... = (0).(148)(809523)
120/99 = 40/33 = 1.212121... = (1).()(21)
2/1 = 2 = (2).()()                            ## no periodic, no non-periodic
0/1 = 0 = (0).()()
0/2 = 0 = (0).()()
299/792 = 0.37752... = (0).(377)(52)
95/-14 = -6.7857142... = -(6).(7)(857142)
-95/-14 = 6.7857142... = (6).(7)(857142)

課題は、周期的な部分と非周期的な部分を入れ替えて、そのままbefore decimal pointにして新しい番号を作成することです。例えば:

25/168 = 0.148809523... = (0).(148)(809523)
       => (0).(809523)(148) = 0.809523148148... = 870397/1080000

数値に周期的な部分がない場合、0.25その数値を新しい周期的な数値に変換します。逆も同様です。

1/4 = 0.25 = (0).(25)() => (0).()(25) = 0.252525... = 25/99
4/9 = 0.444444... = (0).()(4) => (0).(4)() = 0.4 = 2/5
5/1 = 5 = (5).()() => (5).()() = 5 = 5/1

チャレンジ

  • x入力として文字列、2つの入力、有理数、または言語に適した任意の方法として、分数を取ります。
  • の10進表現の周期的部分と非周期的部分を入れ替えx、新しい数値を作成し、小数部分のみを残します。非周期部分ができるだけ短くなるように、周期部分は常にできるだけ早く開始されます。以下に例を示します。
  • 交換された数値を新しい分数として返します。出力は減少するはずですが、入力は必ずしも減少しません。入力形式は出力形式と異なることが許可されています。
  • 分子pのは、x絶対百万以下の値と分母を有する整数であろうqxとなり、非ゼロ百万以下の絶対値を有する整数です。
  • 結果の分子rと分母sは、100万未満であるとは限りません。これらの数値の周期部分の長さを考えると、フロートへの直接変換を避けることをお勧めします。
  • これはコードゴルフです。バイト単位の最短回答が優先されます。

1/70 = (0).(0)(142857)     => (0).(142857)(0) = (0).(142857)() = 0.142857 = 142857/1000000
10/7 = (1).()(428571)      => (1).(428571)() = 1.428571 = 1428571/1000000
1/13 = (0).()(076923)      => (0).(076923)() = 0.076293 = 76923/1000000
3/40 = (0).(075)()         => (0).()(075) = 0.075075... = 75/999 = 25/333
-2/15 = -(0).(1)(3)        => -(0).(3)(1) = -0.311111... = -28/90 = -14/45
75/38 = (1).(9)(736842105263157894)
      => (1).(736842105263157894)(9) = (1).(736842105263157895)()  ## since 0.999... = 1
      = 1.736842105263157895 = 1736842105263157895/1000000000000000000
      = 347368421052631579/200000000000000000
25/168 = (0).(148)(809523) => (0).(809523)(148) = 0.809523148148... = 870397/1080000
120/99 = (1).()(21)        => (1).(21)() = 1.21 = 121/100
2/1 = (2).()()             => (2).()() = 2 = 2/1
0/1 = (0).()()             => (0).()() = 0 = 0/1
0/2 = (0).()()             => (0).()() = 0 = 0/1
299/792 = (0).(377)(52)    => (0).(52)(377) = 0.52377377... = 2093/3996
95/-14 = -(6).(7)(857142)  => -(6).(857142)(7) = -6.857142777... = -12342857/1800000
-95/-14 = (6).(7)(857142)  => (6).(857142)(7) = 6.857142777... = 12342857/1800000

0テストケース2(10/7)の最後に欠落があり1428571/100000ます1428571/1000000
ジョンファンミン

1
前述のように、特定の入力に対して一意の答えはありません。1/7表すことができ(0).()(142857) 、または(0).(1)(428571)1として表すことができ(1).()()(0).()(9)(0).()(99)(0).(9)(9)、等
ngenisis

@ngenisisこれは例では暗黙的でしたが、明示的にしました。フィードバックをありがとう:)
Sherlock9

@ R.Kap私は、ここでフロートの使用を避けることが最善であるという課題ですでに述べました。floatに変換せずに数値の10進数を見つける方法があります。私は:)これは、あなたの質問に答える願っています
Sherlock9

pとqの両方を負にすることはできますか?
edc65 16

回答:


5

Python 2、292バイト

def x(n,d):
 L=len;s=cmp(n*d,0);n*=s;b=p=`n/d`;a={};n%=d
 while not n in a:
  a[n]=p;q=n/d;n=n%d
  if q==0:n*=10;p+=' '
  p=p[:-1]+`q`
 p=p[L(a[n]):];a=a[n][L(b):]
 if n==0:p=''
 n=int(b+p+a);d=10**L(p+a)
 if a!='':n-=int(b+p);d-=10**L(p)
 import fractions as f;g=f.gcd(n,d);return(n/g*s,d/g)

Ungolfedバージョンは、Python 2と3の両方で動作します。10進数表現も出力します。

def x(n,d):
# sign handling
 s=n*d>0-n*d<0
 n*=s
# b, a, p: BEFORE decimal, AFTER decimal, PERIODIC part
 b=p=str(n//d)
 a={}
 n%=d
# long division
 while not n in a:
  a[n]=p
  q=n//d
  n=n%d
  if q==0:
   n*=10
   p+=' '
  p=p[:-1]+str(q)
# a/p still contain b/ba as prefixes, remove them
 p=p[len(a[n]):]
 a=a[n][len(b):]
 if n==0: p=''
# print decimal representation
 print("(" + b + ").(" + a + ")(" + p + ")")
# reassemble fraction (with a and p exchanged)
 n=int(b+p+a)
 d=10**len(p+a)
 if a!='':
  n-=int(b+p)
  d-=10**len(p)
# reduce output
 from fractions import gcd
 g=gcd(n,d)
 return(n//g*s,d//g)

試してくださいd=10**len(p+a)
Sherlock9

1
簡単なテストのためのTIOリンクを次に示します。オンラインで試してみてください!
Kritixi Lithos

あなたの答えでよくやった:D。さらなるゴルフのヒント:可能な限りセミコロンを使用し、行のスペースを取り除き、の代わりになどif n==0: p=''、使用``するすべての場所で使用し、関数の先頭でwith に名前を変更します。str`n/d`str(n/d)lenLL=len;
Sherlock9

@ Sherlock9バックティックについても知りませんでした。すべてのアドバイスをありがとう。
レイナーP.

問題ない。ここにもう少しあります:Dセミコロンの2つの場所:n=int(b+p+a);d=10**L(p+a)import fractions as f;g=f.gcd(n,d);return(n/g*s,d/g)。また、現在の編集で295バイトを取得します。除外するのを忘れている余分な改行はありますか?
Sherlock9

2

ゼリー102 101 89 87 83 81 79 78 77 74バイト

これは、あまりにも長い間、デバッグに、書き込みに長いへの道を取って、間違いなくゴルフの多く(必要8つの7 6 5 4つのリンク、聖なる牛)が、それは私の知る限り、正しいです。特に最初の2つのリンクについては、デニスの支援に感謝します。Rainer P.にも感謝します。私はPythonの答えで多くのアルゴリズムを借りることになりました。

ゴルフの編集: Xanderhallのおかげで-1バイト。正しい論理NOTビルトインを使用しないことによるバグ修正。分子リンクのゴルフから-13バイト。dDennisのおかげで、ネガティブのバグ修正から+1バイト。分子生成がすべて1つのリンクになるように、リンクを再構築しました。-2番目と3番目のリンクの結合から2バイト。3番目と4番目のリンクのいくつかの共通要素を2番目のリンクとメインリンクに移動してから-4バイト。-2バイトで、余分なチェーン演算子が削除されます。分子リンクの再配置から-2バイト。-1バイトからḢ€2番目のリンクの終わりに移動。メインリンクのバグを修正しました。変更から-1バイトṪ ... ,ḢまでḢ ... ṭ。分子リンクをメインリンクに移動してから-3バイト。

ゴルフの提案を歓迎します!オンラインでお試しください!

2ị×⁵d⁴
ÇÐḶ,ÇÐĿḟ@\µḢḅÐfıṭµḢḊṭµḢ€€µF,ḢQ
ÇL€⁵*
×Ṡ©⁸×%µ³,⁴A:/;Ѐ2ĿḌ×®,Ç_/€µ:g/

説明

最初に、他のリンクを呼び出すメインリンクについて説明します。

×Ṡ©⁸×%µ³,⁴A:/;Ѐ2ĿḌ×®,Ç_/€µ:g/  Main link. Left argument: n (int), right argument: d (int)
                                Split into three chains.
×Ṡ©⁸×%  First chain
×       Multiply n by d.
 Ṡ©     Yield sign(n*d) and save it to the register.
   ⁸×   Multiply by n.
     %  Yield n*sgn(n*d) modulo d.

µ³,⁴A:/;Ѐ2ĿḌ×®,Ç_/€  Second chain
                        What follows is the formula for the numerator.
                        (+) means combining the digits of two numbers into one number.
                        ( `integer (+) periodic (+) non-periodic` - `integer (+) periodic` )
µ                     Start a new monadic chain with n*sgn(n*d)%d.
 ³,⁴                  Pair the original two arguments as a nilad.
    A                 Get their absolute values.
     :/               Integer divide to get the integer part of abs(n)/abs(d).
          2Ŀ          Yield the results of the second link.
       ;Ѐ            Append the integer part to each item in the right argument.
                        This appends to both lists from the second link.
            Ḍ         Convert each list from decimal to integer.
             ×®       Multiply by sign(n*d) retrieved from the register.
               ;Ç     Concatenate with the result of the third link (our new denominator).
                 _/€  Reduced subtract over each list.
                        Yields the proper numerator and denominator.

µ:g/  Third chain
µ     Start a new monadic chain with [numerator, denominator].
  g/  Yield gcd(numerator, denominator).
 :    Divide [numerator, denominator] by the gcd.
      Return this as our new fraction.

次に、数字を取得する最初のリンク

2ị×⁵d⁴  First link: Gets the decimal digits one at a time in the format:
          [digit, remainder to use in the next iteration]
2ị      Gets the second index (the remainder).
  ×⁵    Multiply by 10.
    d⁴  Divmod with d.

さて、の周期的部分と非周期的部分を取得する2番目のリンクn/d、および他の多くの重いリフティング。

ÇÐḶ,ÇÐĿḟ@\µḢḅÐfıṭµḢḊṭµḢ€€µF,ḢQ  Second link: Loops the first link,
                                  separates the periodic digits and non-periodic digits,
                                  removes the extras to get only the decimal digits,
                                  and prepares for the third and fourth links.
                                Split into five chains.
ÇÐḶ,ÇÐĿḟ@\  First chain
ÇÐḶ         Loop and collect the intermediate results **in the loop**.
    ÇÐĿ     Loop and collect **all** of the intermediate results.
   ,        Pair into one list.
       ḟ@\  Filter the loop results out the list of all results,
              leaving only [[periodic part], [non-periodic part]].

µḢḅÐfıṭµḢḊṭ  Second and third chains
µ            Start a new monadic chain.
 Ḣ           Get the head [periodic part].
   Ðf        Filter out any [0, 0] lists from a non-periodic number,
  ḅ  ı        by converting to a complex number before filtering.
               Only removes 0+0j. This removes extra zeroes at the end.
      ṭ      Tack the result onto the left argument again.
       µ     Start a new monadic chain.
        Ḣ    Get the head [non-periodic and extra baggage].
         Ḋ   Dequeue the extra baggage.
          ṭ  Tack the result onto the left argument again.

µḢ€€µF,ḢQ  Fourth and fifth chains
µ          Start a new monadic chain with the processed periodic and non-periodic parts.
 Ḣ€€       Get the head of each list (the digits)
            in both the periodic and non-periodic parts.
    µ      Start a new monadic chain with these lists of digits.
     F     Left argument flattened.
       Ḣ   Head of the left argument.
      ,    Pair the flattened list and the head into one list.
        Q  Uniquify this list. (Only removes if non-periodic part is empty)
             Removes any duplicates resulting from a purely periodic n/d.

第3のリンク私たちの新しい分母が得られ、。

ÇL€⁵*  Third link: Generate the denominator.
         What follows is the formula for the denominator.
         ( 10**(num_digits) - ( 10**(num_periodic_digits) if len(non-periodic) else 0 ) )
Ç      Yield the results of the second link.
 L€    Get the length of each item in the list.
         The number of digits in total and the number of digits in the periodic part.
   ⁵*  10 to the power of each number of digits.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.