주기적 및 비 주기적 부품 교체


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만 소수 이전 부분을 떠나, 새로운 번호를 생성 할 수 있습니다. 주기적 부분은 항상 가능한 빨리 시작하여 비 주기적 부분이 가능한 한 짧습니다. 예는 다음과 같습니다.
  • 교환 된 숫자를 새로운 분수로 반환합니다. 출력을 줄여야하지만 입력이 반드시 줄어들지는 않습니다. 입력 형식이 출력 형식과 다를 수 있습니다.
  • 분자 p의이 x절대 백만 이하의 값 및 분모와 정수 것이다 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

@ R.Kap 나는 이미 float를 사용하지 않는 것이 가장 좋습니다. 부동 소수점으로 변환하지 않고 숫자의 십진수를 찾는 방법이 있습니다. 나는 이것이 귀하의 질문에 답변되기를 바랍니다 :)
Sherlock9

p와 q가 모두 음수 일 수 있습니까?
edc65

답변:


5

파이썬 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='', 사용 ``하면 사용하는 모든 장소에서 str같은, `n/d`대신 str(n/d), 및 이름 변경 lenLL=len;함수의 시작 부분에.
Sherlock9

@ Sherlock9 나는 백틱에 대해서도 몰랐다. 모든 조언에 감사드립니다.
Rainer P.

문제가 아니다. 세미콜론을위한 두 곳 : 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 개의 링크, 거룩한 암소)가 필요하지만, 그것은 내가 아는 한, 정확합니다. 데니스에게 도움을 주신 데 대해 특히 감사합니다. 특히 처음 두 개의 링크가 있습니다. Rainer P에 감사드립니다. 파이썬 응답에 많은 알고리즘을 빌려 왔습니다.

골프 편집 : Xanderhall 덕분에 -1 바이트. 올바른 논리 NOT 기본 제공을 사용하지 않는 버그 수정. 분자 링크 골프에서 -13 바이트. dDennis 덕분에 버그를 수정하여 +1 바이트를 기록했습니다 . 분자 생성이 모두 하나의 링크에 있도록 링크를 재구성했습니다. 두 번째와 세 번째 링크를 결합하여 -2 바이트. 세 번째 및 네 번째 링크의 일부 공통 요소를 두 번째 링크 및 기본 링크로 이동하는 -4 바이트 불필요한 체인 연산자를 제거하여 -2 바이트 분자 링크 재 배열에서 -2 바이트 Ḣ€두 번째 링크의 끝에서 끝까지 -1 바이트 . 메인 링크의 버그를 수정했습니다. 변경 -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.

이제 두 번째 링크 는의주기적인 부분과 비주기적인 부분 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.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.