정확한 소수로 분수


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.