정확한 소수로 분수


23

두 개의 정수 a 를 부여한 프로그램이나 함수를 작성하십시오 . b 는 분수 a / b를 정확하게 나타내는 10 진수를 포함하는 문자열을 출력합니다 .

경우 A / B는 소수의 도트 또는 선행 0없는 정수, 단순히 출력 값이다 :

123562375921304812375087183597 / 2777 -> 44494913907563850333124661
81 / 3 -> 27
-6 / 2 -> -3

경우 A / B는 정수가 아니라 출력을,베이스 (10)에 선행 또는 (도트 전에 단일 제로 제외) 제로 후행없는 값이 유한 한 표현을 가진다 :

1 / 2 -> 0.5
3289323463 / -250000000 -> -13.157293852

마지막으로, 만약 오직 경우 (그래서 0.999...) A / B는 정수 아니고 한정된 표현이없는 출력이 유한 부분 괄호 안의 부분 반복 하였다 없다. 반복 부분은 가능한 작아야하고 가능한 빨리 시작해야합니다.

-1 / 3 -> -0.(3)
235 / 14 -> 16.7(857142)
123 / 321 -> 0.(38317757009345794392523364485981308411214953271028037)
355 / 113 -> 3.(1415929203539823008849557522123893805309734513274336283185840707964601769911504424778761061946902654867256637168)

프로그램은 최신 데스크탑 PC에서 10 초 이내에 위의 모든 예제에서 작동해야합니다. 바이트 단위의 가장 작은 프로그램이 이깁니다.


@DestructibleWatermelon 이것은 Turing tarpits를 포함한 거의 모든 언어로 가능합니다 . (하지만 시간 제한으로 어려움을 겪을 수 있습니다.)
Dennis

@DestructibleWatermelon 나는 대부분의 언어가 튜링 완료되었다는 인상을 받았다.
orlp

분수가 0.33333333333336333 ...과 같지 않을 것이라고 안전하게 가정 할 수 있습니까?
brianush1

2
이것은 PE26에 대한 해결책을 요구하는 긴 바람처럼 보입니다 .;)
Conor O'Brien

답변:


3

펄 6 ,  63 58  50 바이트

{->$a,$b {$a~"($b)"x?$b}(|($^a.FatRat/$^b).base-repeating(10))}
{->\a,$b {a~"($b)"x?$b}(|($^a.FatRat/$^b).base-repeating)}
{$/=($^a.FatRat/$^b).base-repeating;$0~"($1)"x?$1}

그것을 테스트

64 비트 정수에 맞는 분모에서만 작동하는지 걱정하지 않으면 43 바이트로 단축 할 수 있습니다.

{$/=($^a/$^b).base-repeating;$0~"($1)"x?$1}

넓히는:

{
  # store in match variable so that we can
  # use 「$0」 and 「$1」
  $/ = (

    # turn the first value into a FatRat so that
    # it will continue to work for all Int inputs
    $^a.FatRat / $^b

  ).base-repeating;

  # 「$0」 is short for 「$/[0]」 which is the non-repeating part
  $0

  # string concatenated with
  ~

  # string repeat once if $1 is truthy (the repeating part)
  # otherwise it will be an empty Str
  "($1)" x ?$1
}

답을 형식화하는 방법은 혼란 스럽습니다. 이전 프로그램은 여러 줄 프로그램처럼 보이기 때문에 이전 프로그램을 제거해야합니다.
mbomb007

@ mbomb007 골프를 게시해야하는 주된 이유는 마케팅 및 Perl 6 교육 때문입니다. 따라서 더 많은 언어를 표시하기 위해 이전 버전을 그대로 둡니다. 그렇기 때문에 설명이있을 때까지 거의 게시하지 않는 이유도 있습니다. 다른 예제가 다른 코드 블록에 있도록 변경했습니다.
브래드 길버트 b2gills

이전 버전은 게시물의 편집 기록에 항상 표시됩니다.
mbomb007

@ mbomb007 여러 가지 다른 방법으로 글을 쓸 때까지 게시 대기하는 경우에는 아닙니다.
브래드 길버트 b2gills

그런 다음 5 분마다 하나씩 편집하십시오.
mbomb007

8

파이썬 2, 174 바이트

x,y=input()
a=abs(x)
b=abs(y)
r=a%b*10
L=[]
M=''
while~-(r in L):L+=r,;M+=str(r/b);r=r%b*10
i=L.index(r)
t=M[:i]+"(%s)"%M[i:]*(M[i:]>'0')
print"-%d."[x*y>=0:(t>'')+3]%(a/b)+t

이 답변의 유효성에 대해서는 확신이 없지만 위의 테스트 사례 및 내가 던진 다른 테스트 사례에서 작동했습니다. 그래도 엉망인 것처럼 보이므로 골프를위한 충분한 공간이 있다고 확신합니다.

초기 설정은 음수가 아닌 숫자를 처리하고 (나중에 부호 계산을 저장하는) 두 인수의 절대 값을 취하고 결과의 몫 부분을 파이썬의 임의 정밀도 산술에 위임합니다. 소수 부분은 우리가 나머지 부분에서 반복 될 때까지 학년 분할 알고리즘으로 수행됩니다. 그런 다음 마침표를 얻기 위해이 반복을 마지막으로 본 시점을 찾아 그에 따라 문자열을 구성합니다.

알고리즘은 실제로 O (n) in연산 으로 인해 상당히 느리지 만 예제에는 충분히 빠릅니다.


5

배치, 349344 바이트

@echo off
set/ad=%2,i=%1/d,r=%1%%d
if not %r%==0 set i=%i%.&if %r% leq 0 set/ar=-r&if %i%==0 set i=-0.
set d=%d:-=%
set/ae=d
:g
if %r%==0 echo %i%&exit/b
set/ag=-~!(e%%2)*(!(e%%5)*4+1)
if not %g%==1 set/ae/=g&call:d&goto g
set/as=r
set i=%i%(
:r
call:d
if %r%==%s% echo %i%)&exit/b
goto r
:d
set/ar*=10,n=r/d,r%%=d
set i=%i%%n%

편집 : 불필요한 문자를 제거하여 5 바이트를 절약했습니다. "골프 해제":

@echo off
set /a d = %2
set /a i = %1 / d
set /a r = %1 % d
if not %r%==0 (
    set i=%i%.                  Decimal point is required
    if %r% leq 0 (
        set /a r = -r           Get absolute value of remainder
        if %i%==0 set i=-0.     Fix edge case (-1/3 = 0 remainder -1)
    )
)
set d = %d:-=%                  Get absolute value of divisor
set /a e = d
:g
if %r%==0 echo %i% & exit /b    Finished if there's no remainder
set /a g = gcd(e, 10)           Loop through nonrecurring decimals
if not %g%==1 (
    set /a e /= g
    call :d
    goto g
)
set /a s = r                    Save remainder to know when loop ends
set i=%i%(
:r
call :d
if %r%==%s% echo %i%)&exit/b
goto r
:d                              Add the next decimal place
set /a r *= 10
set /a n = r / d
set /a r %= d
set i=%i%%n%

2
나는 이것이 어떻게 작동하는지 전혀 모른다. 그러나 나는 배치 lmao에서 그것을 해준 것에 대해 당신을 칭찬한다
Alexander-Reinstate Monica

의 기능에 깊은 인상을 받았습니다 set /a.
Joe

2

자바, 625 (605)

골프 코드 :

import static java.math.BigInteger.*;
String f(BigInteger a, BigInteger b){BigInteger[]r=a.divideAndRemainder(b);String s=r[0].toString();if(r[1].signum()<0)s="-"+s;if(!ZERO.equals(r[1])){s+='.';List<BigInteger>x=new ArrayList();List<BigInteger>y=new ArrayList();for(BigInteger d=TEN.multiply(r[1].abs());;){BigInteger[]z=d.divideAndRemainder(b.abs());int i=y.indexOf(z[1]);if(i>-1&&i==x.indexOf(z[0])){for(int j=0;j<i;++j)s+=x.get(j);s+='(';for(int j=i;j<x.size();++j)s+=x.get(j);s+=')';break;}x.add(z[0]);y.add(z[1]);if(ZERO.equals(z[1])){for(BigInteger j:x)s+=j;break;}d=TEN.multiply(z[1]);}}return s;}

참고 : 정적 가져 오기는 골프 목적으로 함수의 일부로 계산합니다.

이 함수는 나눗셈 결과를 얻어서 시작합니다. 필요한 경우 적분 부분과 부호를 추가합니다. 그런 다음 나머지가 있으면 기본 10 긴 나누기를 수행합니다. 각 단계에서 나눗셈을 수행하십시오. 계산 된 숫자와 나머지를 두 목록에 저장하십시오. 우리가 같은 숫자를 만나고 다시 남는다면 반복되는 부분이 있고 어떤 인덱스가 시작되는지 알 수 있습니다. 코드는 숫자 (반복 없음) 또는 사전 반복 숫자를 추가 한 다음 반복 숫자를 괄호로 묶습니다.

이 때문에 주로 약간 큽니다 BigInteger. 입력이 넘치지 않으면 long조금 더 짧을 수 있습니다. 그래도이 항목을 개선 할 수있는 방법이있을 것으로 기대합니다.

테스트를위한 주요 방법이있는 언 골프 코드 :

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import static java.math.BigInteger.*;

public class FractionToExactDecimal {

  public static void main(String[] args) {
    // @formatter:off
    String[][] testData = new String[][] {
      { "123562375921304812375087183597", "2777", "44494913907563850333124661" },
      { "81", "3", "27" },
      { "-6", "2", "-3" },
      { "1", "2", "0.5" },
      { "3289323463", "-250000000", "-13.157293852" },
      { "-1", "3", "-0.(3)" },
      { "235", "14", "16.7(857142)" },
      { "123", "321", "0.(38317757009345794392523364485981308411214953271028037)" },
      { "355", "113", "3.(1415929203539823008849557522123893805309734513274336283185840707964601769911504424778761061946902654867256637168)" }
    };
    // @formatter:on

    for (String[] data : testData) {
      System.out.println(data[0] + " / " + data[1]);
      System.out.println("  Expected -> " + data[2]);
      System.out.print("    Actual -> ");
      System.out.println(new FractionToExactDecimal().f(new BigInteger(data[0]), new BigInteger(data[1])));
      System.out.println();
    }
  }

  // Begin golf
  String f(BigInteger a, BigInteger b) {
    BigInteger[] r = a.divideAndRemainder(b);
    String s = r[0].toString();
    if (r[1].signum() < 0) s = "-" + s;
    if (!ZERO.equals(r[1])) {
      s += '.';
      List<BigInteger> x = new ArrayList();
      List<BigInteger> y = new ArrayList();
      for (BigInteger d = TEN.multiply(r[1].abs());;) {
        BigInteger[] z = d.divideAndRemainder(b.abs());
        int i = y.indexOf(z[1]);
        if (i > -1 && i == x.indexOf(z[0])) {
          for (int j = 0; j < i; ++j)
            s += x.get(j);
          s += '(';
          for (int j = i; j < x.size(); ++j)
            s += x.get(j);
          s += ')';
          break;
        }
        x.add(z[0]);
        y.add(z[1]);
        if (ZERO.equals(z[1])) {
          for (BigInteger j : x)
            s += j;
          break;
        }
        d = TEN.multiply(z[1]);
      }
    }
    return s;
  }
  // End golf
}

프로그램 출력 :

123562375921304812375087183597 / 2777
  Expected -> 44494913907563850333124661
    Actual -> 44494913907563850333124661

81 / 3
  Expected -> 27
    Actual -> 27

-6 / 2
  Expected -> -3
    Actual -> -3

1 / 2
  Expected -> 0.5
    Actual -> 0.5

3289323463 / -250000000
  Expected -> -13.157293852
    Actual -> -13.157293852

-1 / 3
  Expected -> -0.(3)
    Actual -> -0.(3)

235 / 14
  Expected -> 16.7(857142)
    Actual -> 16.7(857142)

123 / 321
  Expected -> 0.(38317757009345794392523364485981308411214953271028037)
    Actual -> 0.(38317757009345794392523364485981308411214953271028037)

355 / 113
  Expected -> 3.(1415929203539823008849557522123893805309734513274336283185840707964601769911504424778761061946902654867256637168)
    Actual -> 3.(1415929203539823008849557522123893805309734513274336283185840707964601769911504424778761061946902654867256637168)

좋은! 이것을 문자열을 반환하는 함수로 만들고에서 하나의 공백을 제거하여 몇 바이트를 절약 할 수 있다고 생각합니다 a, BigInteger. 나는 또한 당신이 별칭을 수 생각 BigInteger.TEN하고 BigInteger.ZERO.
FryAmTheEggman

@FryAmTheEggman 덕분에 정적 가져 오기가 더 자세한 참조를 통해 공간을 절약 할 수 있다는 것을 알지 못했습니다. 그렇습니다. 또한 누락 된 다른 몇 가지를 발견했습니다. 예 : while (true)-> for (;;)또한 for초기화 프로그램 에 물건을 넣고 다른 바이트를 절약 할 수있었습니다 .

먼저 BigInteger를 확장하는 것은 어떻습니까? 둘째, 반복되는 나머지는 반복되는 것을 보여주기에 충분합니다. 입력을 int로 제한하면 나머지가 색인으로, 색인이 값으로 int []를 사용할 수 있습니다.
JollyJoker

BigInteger를 확장하는 @JollyJoker는 공간을 절약하기 위해 전체 클래스를 작성해야하며 트레이드 오프가 작동하는지 의심합니다. 또한 입력을 제한 할 수 없습니다 . 어쨌든 BigInteger내 코드 에는 8 개의 텍스트 인스턴스가 있으며 더 많은 코드를 추가하여 단일 문자 클래스 이름으로 축소하는 방법을 알지 못합니다. 그리고 int[]BigInteger가 이미 내부적 으로 처리하는 코드를 추가하면 내 대답이 부풀어 올 것입니다.

@JollyJoker 서브 클래스의 인스턴스를 반환하기 위해 호출하는 모든 BigInteger 메서드를 재정의하지 않으면 코드를 더 부 풀릴 수있는 캐스트를 추가해야한다고 언급 할 가치가 있습니다 . 서브 클래스의 오버 헤드로 인해 낭비되는 바이트 외에 코드 크기가 확실히 증가합니다.

1

PHP, 277 바이트

list(,$n,$d)=$argv;$a[]=$n;$n-=$d*$r[]=$n/$d^0;!$n?:$r[]=".";while($n&&!$t){$n*=10;$n-=$d*$r[]=$n/$d^0;$t=in_array($n%=$d,$a);$a[]=$n;}if($t){$l=count($a)-($p=array_search(end($a),$a));echo join(array_slice($r,0,2+$p))."(".join(array_slice($r,2+$p,$l)).")";}else echo join($r);

0

매스 매 티카 198 바이트

i=Integer;t=ToString;a_~h~b_:=f[a/b];f@q_i:= t@q;
f@q_:=""<>{t@IntegerPart[q],".",RealDigits[FractionalPart[q]][[1]]//.{{x___,{k__i}}:> {x,"("<>(t/@{k})<>")"},{x__i,j___String}:>""<> {""<>t/@{x},j}}}

언 골프

(* hand over quotient of a, b to function f *)
h[a_, b_] := f[a/b];

(* if the quotient is an integer, return it as a string *)
f[q_Integer] := ToString@q;

(* otherwise, return the integer part, followed by a decimal point ...*)
f[q_] := "" <> {ToString@IntegerPart[q], ".", 

   (* replacing the repeating part (if it exists) between parentheses *)
   RealDigits[FractionalPart[q]][[1]] //. {{x___, {i__Integer}} :> {x, "(" <>(ToString /@ {i}) <> ")"},

   (* and the non-repeating part (if it exists) without parentheses *)
   {x__Integer, i___String} :> "" <> {"" <> ToString /@ {x}, i}}}

테스트

h @@@ {{81, 3}, {-81, 3}, {1, 4}, {-13, 3}, {19, 7}, {3289323463, 25000}, {235, 14}, {1325, 14}}

{ "27", "-27", "0.25", "-4. (3)", "2. (714285)", "131572.93852", "16.7 (857142)", "94.6 (428571)"}

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.