Keyfi Hassas Tam Sayı Bölümü


16

Biz keyfi olarak büyük tamsayılar için bölüm uygulayacağız.

Bu .

Görev, üzerlerine rastgele hassas tamsayılar ve Bölme uygulayan bir program veya işlev yazmaktır.

Bunu çok kolaylaştırabilecek birçok şeye izin verilmediğini unutmayın, lütfen teknik özellikleri okuduğunuzdan emin olun .

Giriş

Size girdi olarak 2 şey verilecek:

  1. 10 basamaklı bir dize diyelim n.
  2. 10 basamaklı başka bir dize diyelim m

n>m>0Asla sıfıra bölmeniz istenmeyeceği anlamına gelir .

Çıktı

İki sayı çıkarırsınız Qve Rburada m * Q + R = n ve 0 <= R <m

Özellikler

  • Gönderiminiz keyfi olarak büyük tamsayılar için kullanılabilir olmalıdır (kullanılabilir bellekle sınırlıdır).

  • Sen olmayabilir dış kütüphane kullanmak. G / Ç için harici bir kütüphaneye ihtiyacınız varsa, bunu yerleşik olarak kabul edebilirsiniz. (iostream vb. şeylere bakmak).

  • Dilinizde bunu önemsizleştiren bir yerleşik varsa , onu kullanamayabilirsiniz. Bu, rastgele hassas tamsayıları işleyebilen yerleşik türleri içerir (ancak bunlarla sınırlı değildir).

  • Herhangi bir nedenden ötürü bir dil varsayılan olarak rastgele duyarlık tamsayıları kullanıyorsa, bu işlev genellikle 64 bitte saklanamayan tam sayıları temsil etmek için kullanılamaz.

  • Giriş ve çıkış taban 10 olmalıdır ZORUNLU . Sayıları bellekte nasıl sakladığınız ya da aritmetik işlemi nasıl yaptığınız önemli değildir, ancak G / Ç temel 10 olacaktır.

  • Sonuç almak için 15 saniyeniz var . Bu yinelenen çıkartmayı yasaklamak içindir.

  • Buradaki amaç, aslında keyfi hassas tamsayıları uygulamaktır. Herhangi bir nedenle meydan okuma özelliklerine uymayı ve bunları uygulamadan başarılı bir şekilde yapmayı başarabiliyorsanız, sanırım sizin için iyi, geçerli geliyor.

Test Durumları

  1. Bu durumda, girişler 39! ve 30!

Giriş

n = 20397882081197443358640281739902897356800000000 
m = 265252859812191058636308480000000

Çıktı

Q = 76899763100160
R = 0
  1. n50'ye kadar olan tüm faktörlerin toplamıdır, artı 1. m20'ye kadar sıralı sayılardır.

giriş

n = 31035053229546199656252032972759319953190362094566672920420940313
m = 1234567891011121314151617181920

çıktı

q = 25138393324103249083146424239449429
r = 62459510197626865203087816633
  1. n205! + 200 !. mPeterTaylor'un sanal alana gönderdiğim şeyleri parçalayarak beni döken kaç gözyaşı.

Giriş

n = 271841734957981007420619769446411009306983931324177095509044302452019682761900886307931759877838550251114468516268739270368160832305944024022562873534438165159941045492295721222833276717171713647977188671055774220331117951120982666270758190446133158400369433755555593913760141099290463039666313245735358982466993720002701605636609796997120000000000000000000000000000000000000000000000000
m = 247

Çıktı

q = 1100573825740813795225181252819477770473619155158611722708681386445423816849801159141424129060075102231232666057768175183676764503262931271346408394876267875141461722640873365274628650676808557279259873162169126398101692109801549256156915750794061370041981513180387019893765753438422927286098434193260562682052606153857091520795991080960000000000000000000000000000000000000000000000000
r = 0;

Muhtemelen bir noktada daha fazla test örneği ekleyeceğim.

İlişkili

Kulağa hoş geliyor, ama gerçekten değil


ES kütüphaneleri harici kütüphaneler olarak sayılır mı?
Johnson Steward

@JohnsonSteward Bununla ne demek istediğinden emin değilim? Ben varsayılan olarak "evet" olurdu, ama açıklığa kavuşturabilir misiniz?
Liam

@JohnsonSteward iyi Sanırım ne olduğuna bağlıyım? Kod mu / kod kütüphanesi mi?
Ashwin Gupta

1
Negatif sayılara izin veriliyor mu?
TheConstructor

2
@TheConstructor: kurallardan: "n> m> 0 olduğunu varsayın", yani hayır, negatif sayılara izin verilmez.
nimi

Yanıtlar:


4

Python 2, 427 bayt

b=S=lambda l:sorted(l)[::-1]
A=lambda a,b,o=0:A(a^b,{n+1for n in[b&a,b-a][o]},o)if b else a
M=lambda a,*b:reduce(A,({n+m for n in a}for m in b))
def D(a,b):
 q=a-a
 while b<=S(a):n=max(a)-b[0];n-=S(M(b,n))>S(a);q|={n};a=A(a,M(b,n),1)
 return q,a
exec"a=b;b=[]\nfor d in raw_input():b=A(M(b,3,1),{i for i in range(4)if int(d)>>i&1})\n"*2
for n in D(a,S(b)):
 s=''
 while n:n,d=D(n,[3,1]);s=`sum(2**i for i in d)`+s
 print s or 0

Girişi her biri ayrı bir satırdaki STDIN üzerinden okur ve sonucu STDOUT'a yazdırır.

açıklama

Tam sayıları basamak dizisi olarak göstermek yerine, her tamsayıyı ikili gösterimindeki "on" bitleri kümesi olarak temsil ederiz. Yani, bir tam sayıdır , n ikili gösterimi olarak 1'e eşit bit indisleri kümesi olarak temsil edilir , n . Örneğin, ikili sayıdaki 10, 1010 sayısı {1, 3} kümesi olarak temsil edilir. Bu temsil, Python'un set işlemlerini kullanarak aritmetik işlemlerin bazılarını oldukça kısa bir şekilde ifade etmemizi sağlar.

İki küme eklemek için, simetrik farklarının toplamını ve kesişme noktalarına ulaşan tam sayı kümesini (kolektif taşımaya karşılık gelen ve dolayısıyla sonunda nihai kümeye sahip olduğumuz boş küme oluruz) Benzer şekilde, iki seti çıkarmak için, simetrik farklarının (özyinelemeli olarak) farkını alırız ve sonraki tamsayılar kümesini (küme) farklarına (kolektif borçlanmaya karşılık gelir ve böylece sonunda boş küme olur) son noktaya sahibiz.) Bu iki işlemin benzerliği, bunları tek bir işlev ( A) olarak uygulamamıza izin verir .

Çarpma ( M) basitçe dağıtılmış toplamadır: iki A ve B seti verildiğinde , yukarıda tanımlandığı gibi tüm setlerin toplamını alırız { A + b | bB } (burada A + b { a + b | aA } kümesidir ).

Tamsayı karşılaştırması iki kümenin azalan düzende sıralanmış sözlükbilimsel karşılaştırması haline gelir.

Dİki kümeyi ( A ve B ) bölmek için , boş küme bölüm olarak başlar ve tekrar tekrar en büyük n tamsayısını buluruz , öyle ki B + n A'dan küçük veya ona eşittir (sadece maxima arasındaki farktır) ve A ve B , muhtemelen eksi-1), ekleme , n bölüm için bir eleman olarak ve çıkarma B + n, A , yukarıda tarif edildiği gibi kadar, bir daha az hale gelir B , yani, geri kalan olana kadar.

Tabii ki ücretsiz öğle yemeği yok. Vergi, ondalık ve ondalık sayıları dönüştürmek zorunda kalıyoruz. Aslında, ondalık sayıya dönüştürme çalışma süresinin çoğunu alır. Biz sıradan aritmetik yerine sadece yukarıdaki işlemleri kullanarak, "olağan yol" dönüşümünü yapıyoruz.


Sadece meraktan: s=`sum(2**i for i in d)`+sdönüşüm sırasında yerleşik keyfi hassas aritmetik kullanmıyor mu?
Yapımcı

1
Konstrüktör No. dtek bir ondalık basamaktır, yani i0 ile 3 arasındadır ve toplamın tamamı 0 ile 9 arasındadır.
Ell

4

Java 8, 485 bayt

Sınıf tanımı sayılmazsa , işlevi dyerine başka bir 5 bayt divideveya başka 16 bayt azaltılabilir .

public class G{int l(String a){return a.length();}String s(String n,String m){while(l(n)>l(m))m=0+m;String a="";for(int c=1,i=l(n);i>0;c=c/10){c=n.charAt(--i)+c-m.charAt(i)+9;a=c%10+a;}return e(a);}String e(String a){return a.replaceAll("^0+(?=[0-9])","");}String divide(String n,String m){String q="",p=q,y;for(int b=0,i=0;b<=l(n);i--){y=n.substring(0,b);if(l(y)==l(p)&&p.compareTo(y)<=0||l(y)>l(p)){y=s(y,p);n=y+n.substring(b);q+=i;b=l(y)+1;i=10;p=m+0;}p=s(p,m);}return e(q)+","+n;}}

Bu şekilde kullanılabilir:

public static void main(String[] args) {
    G devision = new G();
    System.out.println(devision.divide("20397882081197443358640281739902897356800000000",
            "265252859812191058636308480000000"));
    System.out.println(devision.divide("31035053229546199656252032972759319953190362094566672920420940313",
            "1234567891011121314151617181920"));
    System.out.println(devision.divide(
            "271841734957981007420619769446411009306983931324177095509044302452019682761900886307931759877838550251114468516268739270368160832305944024022562873534438165159941045492295721222833276717171713647977188671055774220331117951120982666270758190446133158400369433755555593913760141099290463039666313245735358982466993720002701605636609796997120000000000000000000000000000000000000000000000000",
            "247"));
}

verimli

76899763100160,0
25138393324103249083146424239449429,62459510197626865203087816633
1100573825740813795225181252819477770473619155158611722708681386445423816849801159141424129060075102231232666057768175183676764503262931271346408394876267875141461722640873365274628650676808557279259873162169126398101692109801549256156915750794061370041981513180387019893765753438422927286098434193260562682052606153857091520795991080960000000000000000000000000000000000000000000000000,0

Ungolfed:

public class ArbitraryPrecisionDivision {

    /**
     * Length of String
     */
    int l(String a) {
        return a.length();
    }

    /**
     * substract m of n; n >= m
     */
    String s(String n, String m) {
        while (l(n) > l(m))
            m = 0 + m;
        String a = "";
        for (int c = 1, i = l(n); i > 0; c = c / 10) {
            c = n.charAt(--i) + c - m.charAt(i) + 9;
            a = c % 10 + a;
        }
        return e(a);
    }

    /**
     * trim all leading 0s
     */
    String e(String a) {
        return a.replaceAll("^0+(?=[0-9])", "");
    }

    /**
     * divide n by m returning n/m,n%m; m may not start with a 0!
     */
    String divide(String n, String m) {
        // q stores the quotient, p stores m*i, y are the b leading digits of n
        String q = "", p = q, y;
        for (int b = 0, i = 0; b <= l(n); i--) {
            y = n.substring(0, b);
            if (l(y) == l(p) && p.compareTo(y) <= 0 || l(y) > l(p)) {
                y = s(y, p);
                n = y + n.substring(b);
                q += i;
                b = l(y) + 1;
                i = 10;
                p = m + 0;
            }
            p = s(p, m);
        }
        return e(q) + "," + n;
    }

    public static void main(String[] args) {
        ArbitraryPrecisionDivision division = new ArbitraryPrecisionDivision();
        System.out.println(division.divide("20397882081197443358640281739902897356800000000",
                "265252859812191058636308480000000"));
        System.out.println(division.divide("31035053229546199656252032972759319953190362094566672920420940313",
                "1234567891011121314151617181920"));
        System.out.println(division.divide(
                "271841734957981007420619769446411009306983931324177095509044302452019682761900886307931759877838550251114468516268739270368160832305944024022562873534438165159941045492295721222833276717171713647977188671055774220331117951120982666270758190446133158400369433755555593913760141099290463039666313245735358982466993720002701605636609796997120000000000000000000000000000000000000000000000000",
                "247"));
    }
}

m1'den 9'a kadar olan bir diziyi önceden hesaplayarak ve b=0bunun yerine başlayarak biraz hız feda ettim b=l(m), ama bunu yaparak çok sayıda bayt kaydettim. İsteğe bağlı hassas ekleme ile ilgileniyorsanız önceki sürüme bakın .

Sanırım bu en kısa çözüm olmayacak, ama belki de iyi bir başlangıç ​​olabilir.


Bunun için toplama, çarpma ve çıkarma uygularsanız, bunun için 500 tekrar ödül kazanacağım. : DI, Stringy hassasiyet fikrini seviyorum.
Addison Crump

@VoteToClose bunu yarın görecek. Sanırım en zor kısım bitti.
Yapımcı

1

Mathematica, 251 bayt

r=Reverse;f=FoldPairList;s={0}~Join~#&;
p[a_,b_]:={First@#,#[[2,1,-1,2]]}/.{Longest[0..],x__}:>{x}&@Reap@f[Sow@{Length@#-1,Last@#}&@NestWhileList[r@f[{#~Mod~10,⌊#/10⌋}&[#+Subtract@@#2]&,0,r@Thread@{#,s@b}]&,Rest@#~Join~{#2},Order[#,s@b]<=0&]&,0s@b,s@a]

açıklama

Ondalık sayılar üzerine aritmetik kolayca uygulanabilir FoldPairList. Örneğin,

times[lint_,m_]:=Reverse@FoldPairList[{#~Mod~10,⌊#/10⌋}&[m #2+#]&,0,Reverse@lint]

elle çarpma işlemini taklit eder.

times[{1,2,3,4,5},8]
(* {9,8,7,6,0} *)

Test durumu

p[{1,2,3,4,5,6,7,8,9},{5,4,3,2,1}] 
(* {{2,2,7,2},{3,9,4,7,7}} *)

anlamına gelir 123456789 / 54321= 2272...39477.

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.