Kesin ondalık basamağa


23

A, b iki tamsayı verilen bir program veya fonksiyon yazın , tam olarak a / b kesimini temsil eden bir ondalık sayı içeren bir dize çıktılar .

Eğer a / b tamsayı ise, değeri basit, ondalık bir nokta veya baştaki sıfırlar olmadan verin:

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

Eğer a / b tamsayı değilse de, üs 10'da sonlu bir gösterime sahipse, değeri öncü veya sondaki sıfırlar olmadan (noktadan önce tek bir sıfır hariç) verin:

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

Son olarak, eğer ( eğer hayırsa 0.999...) a / b tamsayı değilse ve sonlu bir gösterimi yoksa, sonlu kısmı parantez içinde tekrarlayan kısmı izler. Tekrarlayan kısım mümkün olduğunca küçük olmalı ve mümkün olduğunca erken başlamalıdır.

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

Programınız, yukarıdaki örneklerin tümü için, modern bir masaüstü PC'de 10 saniyeden kısa sürede çalışmalıdır. Bayt cinsinden en küçük program kazanır.


@DestructibleWatermelon Turing tarpits dahil hemen hemen her dilde mümkündür. (Bunlar olsa da zaman sınırı ile mücadele edebilir.)
Dennis,

@DestructibleWatermelon Çoğu dilin tamamının tamamlandığı izlenimini edindim.
orlp

Kesirin şöyle bir şey olmayacağını güvenle söyleyebilir miyiz: 0.33333333333336333 ...?
brianush1

2
Bu PE26 için çözümler istemenin uzun soluklu bir yolu gibi gözüküyor ;)
Conor O'Brien

1
Bu sorunun genelleştirilmesi ; ayrıca ilgili .
Peter Taylor

Yanıtlar:


3

Perl 6 ,  63 58  50 bayt

{->$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}

Dene

Yalnızca 64 bit tam sayıya uyan paydalarla çalışması umrunda değilse, yalnızca 43 bayta kısaltılabilir:

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

Expanded:

{
  # 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
}

Cevabınızı biçimlendirme şekliniz kafa karıştırıcı. Eski programlarınızı kaldırmalısınız çünkü şu anda çok hatlı bir program gibi görünüyor.
mbomb007

@ mbomb007 Golf ilanı göndermemdeki temel sebep, pazarlama ve Perl 6 eğitimi. Bu yüzden daha fazla dil göstermek için eski sürümleri bırakıyorum. Bu yüzden, orada bir çeşit açıklama yapana kadar nadiren gönderiyorum. Farklı örnekleri farklı kod bloklarında olacak şekilde değiştirdim.
Brad Gilbert b2gills'de

Eski sürümler, gönderinin düzenleme geçmişinde her zaman görünür.
mbomb007

@ mbomb007 Yazmak için birkaç farklı yolu denedikten sonra göndermeyi beklersem olmaz.
Brad Gilbert b2gills

Sonra her 5 dakikada bir düzenleyin.
mbomb007

8

Python 2, 174 bayt

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

Bu cevabın geçerliliği konusunda tam olarak ikna olmadım, ancak yukarıdaki test vakalarında ve attığım diğer test vakalarında işe yaradı. Olsa da, doğru bir karışıklık gibi görünüyor, bu yüzden golf için bol bol yer var eminim.

İlk kurulum, negatif olmayan sayılarla uğraşmamızı sağlamak için her iki argümanın mutlak değerlerini alır (daha sonra işaret hesaplamasını kaydeder) ve sonucun bölüm kısmını Python'un rasgele kesinlik aritmetiğine devreder. Kesirli kısım, geri kalanı tekrar edinceye kadar ilkokul bölümü algoritmasıyla yapılır. Daha sonra, bu tekrarı en son ne zaman gördüğümüze bakarız ve zamanı bulmak için dizgiyi oluştururuz.

Algoritmanın O (n) inişlemi nedeniyle oldukça yavaş olduğuna dikkat edin , ancak örnekler için yeterince hızlı.


5

Toplu iş, 349 344 bayt

@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%

Düzenleme: Gereksiz karakterleri kaldırarak 5 bayt kaydedildi. "Ungolfed":

@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
Bunların hiçbirinin nasıl çalıştığını bilmiyorum ama toplu iş lmao'da yaptığınız için sizi takdir ediyorum
Alexander - Reinstate Monica

Yeteneklerinden etkilendim set /a.
Joe,

2

Java, 625 605

Golf kodu:

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;}

Not: Statik içe aktarımı, golf amacıyla bu fonksiyonun bir parçası olarak sayıyorum.

Bu fonksiyon bölme sonucunu alarak başlar. Gerekirse ayrılmaz kısmı ve işareti ekler. O zaman bir geri kalan varsa, 10 tabanını uzunluğuyla birleştirir. Her adımda, bölümü gerçekleştirin. Hesaplanan basamağı ve kalanı iki listede saklayın. Aynı rakam ve kalanıyla tekrar karşılaşırsak, tekrarlanan bir bölüm var ve hangi endekste başladığını biliyoruz. Kod, ya rakamları (tekrar yok) ya da tekrar öncesi rakamları, ardından parantez içine alınmış tekrarlanan rakamları ekler.

Bu çoğunlukla nedeniyle biraz büyük BigInteger. Girişler bile bir taşma olmasaydı long, biraz daha kısa olabilirdi. Yine de, bu girişi iyileştirmenin yolları olduğunu bekliyorum.

Test için ana yöntemle kodlanmamış kod:

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
}

Program çıktısı:

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)

Güzel! Bunu bir dize döndüren bir işlev yaparak ve içindeki bir boşluğu kaldırarak birkaç bayttan tasarruf edebileceğinizi düşünüyorum a, BigInteger. Ben de takma yapabileceğini düşünüyorum BigInteger.TENve BigInteger.ZERO.
FryAmTheEggman

@FryAmTheEggman teşekkürler, daha ayrıntılı referanslar üzerinde statik ithalat tasarruf alanı fark etmedim. Öyle. Ayrıca, while (true)-> gibi for (;;), forbaşlatıcıya bir şeyler koymamı ve başka bir baytı kurtarmamı sağlayan -> gibi kaçtığım birkaç şey daha buldum .

İlk olarak, BigInteger'ı genişletmeye ne dersiniz? İkincisi, tekrarlanan bir geri kalanın tekrar ettiğini göstermek için yeterlidir; eğer girişi int ile sınırlandırırsanız, geri kalanı indeks olarak indeksi ve endeksi değer olarak indisi kullanabilirsiniz, eğer mantıklıysa.
JollyJoker,

@JollyJoker, BigInteger'ı genişletmek için yer kazanmayı denemek için bütün bir sınıf yazmayı gerektirir ve tradeoff'un işe yarayacağından şüpheliyim. Artı, ben yapamam girişi kısıtlar. Her neyse, kodumda metnin sekiz örneği var BigIntegerve bunları tek bir karakter sınıfı adına küçültmek için nasıl daha fazla kod eklemenin işe yarayacağını anlamıyorum. Ve kesinlikle başa çıkmak için kod int[]eklemelisiniz (ki BigInteger zaten dahili olarak yapıyor) sadece cevabımı patlatacak.

@JollyJoker , alt sınıfın bir örneğini döndürmek için çağırdığım her BigInteger yöntemi geçersiz kılmadığım sürece, kodu daha da şişiren birkaç yayın eklemek zorunda kalacağımdan bahsetmeye değer . Bir alt sınıfın ek yükü için boşa harcanan baytların üstünde, bu kesinlikle kod boyutunu artıracaktır.

1

PHP, 277 Bayt

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

Mathematica 198 bayt

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}}}

UnGolfed

(* 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}}}

Testler

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)"}

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.