交换一些周期性和非周期性的部分


21

在每个有理数的十进制表示形式中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作为输入,字符串,两个输入,一个有理数或任何适合您的语言的方法。
  • 交换的十进制表示形式的周期性和非周期性部分x以创建新的数字,仅保留小数点之前的部分。周期性部分总是尽可能早地开始,以使非周期性部分尽可能短。示例如下。
  • 返回交换后的数字作为新分数。尽管输出应该减少,但不一定减少输入。输入格式允许与输出格式不同。
  • 分子px将是与一个万以下的绝对值和分母的整数qx将是一个非零的整数与一个万以下的绝对值。
  • 结果的分子r和分母s不能保证小于一百万。给定这些数字的周期部分的长度,建议您避免直接转换为浮点数。
  • 这是代码高尔夫。以字节为单位的最短答案将获胜。

例子

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
JungHwan Min

1
如前所述,对于给定的输入,不会有唯一的答案。1/7可以表示为(0).()(142857) (0).(1)(428571)1可以表示为(1).()()(0).()(9)(0).()(99)(0).(9)(9),等等
ngenisis

@ngenisis在示例中这是隐式的,但是我已经明确了。感谢您的反馈:)
Sherlock9'9

@ R.Kap我已经在挑战中指出,最好避免在此处使用浮点数。有一些方法可以查找数字的小数位数而不转换为浮点数。我希望这能回答您的问题:)
Sherlock9'2013/

p和q都可以为负吗?
edc65

Answers:


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中使用。还打印十进制表示形式。

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='',利用``在每次使用的地方str,如`n/d`替代的str(n/d)和重命名len,以LL=len;在函数的开始。
Sherlock16年

@ Sherlock9我什至不知道反引号。感谢所有的建议。
Rainer P.

没问题 这里还有更多:D分号的两个地方: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个字节。您还有多余的换行符吗?
Sherlock16年

2

果冻102 101 89 87 83 81 79 78 77 74字节

这花的方式来长写的,太长时间的调试,肯定需要大量的高尔夫球场(8个七六 5四个环节,圣牛),但它是,在我所知的,正确的。非常感谢Dennis在这里的帮助,尤其是前两个链接。我也非常感谢Rainer P.,因为我最终在他们的Python答案中借用了很多算法。

高尔夫编辑:感谢Xanderhall,-1个字节。通过不使用正确的逻辑“非”内置错误修复。打高尔夫球分子链接的-13个字节。d丹尼斯(Dennis)的帮助,修复了一个否定错误的+1字节。重组了链接,以便分子生成全部在一个链接中。第二个和第三个链接的组合产生-2个字节。从第三和第四链接的一些公共元素移动到第二链接和主链接的-4字节。删除一些多余的链运算符后的-2个字节。重新排列分子链接的-2个字节。-1字节,从移动Ḣ€到第二个链接的末尾。修复了主链接中的错误。-1个字节,从更改Ṫ ... ,ḢḢ ... ṭ。将分子链接移动到主链接中的-3个字节。

欢迎打高尔夫球!在线尝试!

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

说明

首先,我将解释main链接,该链接称为其他链接。

×Ṡ©⁸×%µ³,⁴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.

现在,第二个链接获取的周期性和非周期性部分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.

第三个环节,这将产生我们新的分母。

Ç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.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.