আপনি কত দ্রুত গুন করতে পারেন?


12

সাম্প্রতিক পাইথনকে ধাক্কা দিয়ে , পাইথনের শক্তি দেখানোর চেষ্টা এখানে। আপনার চ্যালেঞ্জটি হ'ল এমন একটি প্রোগ্রাম লিখুন যা n10 সেকেন্ডের মধ্যে যথাসম্ভব উচ্চতর সংখ্যার ফ্যাক্টরিয়াল গণনা করে ।

আপনার স্কোর হবে (highest n for your program on your machine)/(highest n for my program on your machine)

বিধি

  • আপনাকে অবশ্যই একটি সঠিক পূর্ণসংখ্যার সমাধান গণনা করতে হবে। যেহেতু fact৪ বিট স্বাক্ষরবিহীন পূর্ণসংখ্যায় ফিট করতে পারে তার চেয়ে অনেক বেশি কারণ, যদি আপনার ভাষা বড় সংখ্যাকে সমর্থন না করে আপনি স্ট্রিং ব্যবহার করতে পারেন
  • স্ট্যান্ডার্ড লুফোলগুলি নিষিদ্ধ। বিশেষত, আপনি কোনও বাহ্যিক সংস্থান ব্যবহার করতে পারবেন না।
  • কেবল গণনার অংশ (এতে স্ট্রিং ব্যবহার করে কোনও কাজের ক্ষেত্রের জন্য সময় অন্তর্ভুক্ত) মোট সময় যোগ করে যা গড়ে 10 সেকেন্ডের নীচে হওয়া উচিত।
  • একক থ্রেডেড প্রোগ্রামগুলি।
  • আপনাকে আউটপুটটি সহজেই মুদ্রণযোগ্য আকারে সংরক্ষণ করতে হবে (যেমন মুদ্রণের সময় লাগে) (আমার প্রোগ্রামটি নীচে দেখুন), স্ট্রিং, ভেরিয়েবল, অক্ষর অ্যারে ইত্যাদি store

সম্পাদনা করুন:

  • আপনার প্রোগ্রামটি অবশ্যই সবার জন্য সঠিক ফলাফল প্রদান করবে n:1 <= n <= (your highest n)

EDIT2:

  • আমি স্পষ্টভাবে এটি বলতে অপছন্দ করি তবে আপনার ভাষার অন্তর্নির্মিত ফ্যাক্টরিয়াল ফাংশনগুলি ব্যবহার করা স্ট্যান্ডার্ড লুফোলের আওতায় পড়ে http://meta.codegolf.stackexchange.com/a/1078/8766 দুঃখিত গণিত এবং aষি

আমার প্রোগ্রাম

from __future__ import print_function
import time


def factorial( n ):
    return reduce( ( lambda x , y : x * y ) , xrange( 1 , n + 1 ) , 1 )

start = time.clock()
answer = factorial( 90000 )
end = time.clock()

print ( answer )
print ( "Time:" , end - start , "sec" )

সর্বোচ্চ স্কোর জয়। রেকর্ডের জন্য, আমার কোড পেন্টিয়াম 4 3.0 গিগাহার্টজ n = 90000প্রায় 9.89সেকেন্ডে পরিচালনা করতে পারে


সম্পাদনা: সবাই দয়া করে কেবল সর্বোচ্চ এন এর চেয়ে স্কোর যুক্ত করতে পারেন ? এটি আপনার হার্ডওয়ারের উপর নির্ভর করে কেবল সর্বোচ্চের নিজের দ্বারা কোনও অর্থ নেই। অন্যথায় উদ্দেশ্যমূলক বিজয়ী মানদণ্ড পাওয়া অসম্ভব। ali0sha এর অ্যাওয়ার সঠিকভাবে এটি করে।n


আমরা একটি বিজয়ী আছে। Http://meta.codegolf.stackexchange.com/a/1080/8766 এর কাছাকাছি স্কার্টের মতো হিসাবে আমি জাভা উত্তরটি /codegolf//a/26974/8766 হিসাবে গ্রহণ করি নি


1
আপনি operator.mul
ল্যাম্বদা

1
বিট এই কাজগুলিকে অবাক করে দিয়েছিল, তবে ধরে নিলাম আমি নিয়মগুলি সঠিকভাবে পড়েছি এই ম্যাটল্যাব সমাধানটি দুর্দান্ত হবে:, এক সেকেন্ডের ভগ্নাংশে factorial(Inf)ফিরে আসে Inf
ডেনিস জহেরুদ্দিন

1
@ ডুরকনব যা স্ট্যান্ডার্ড লুফোলগুলিতে ফিট করে।
জাস্টিন

1
@ ডেনিসজাহেরউদ্দিন, "ইনফ" কে "সঠিক সংখ্যার সমাধান" হিসাবে উল্লেখ করা কিছুটা প্রসারিত বিষয়।
tobyink

1
@ কুইনকুনস না, যে কোনও ভাষা অনুমোদিত।
ব্যবহারকারী 80551

উত্তর:


7

জিএমপি সহ সি ++, স্কোর = 55.55 (10,000,000 / 180,000)

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <vector>
#include <iostream>
#include <queue>
#include <gmpxx.h>

int main(int argc, char *argv[]) {
  uint64_t n = atoi(argv[1]);

  // Iterate through 1..n.  Strip off powers of 2.  Multiply
  // remainders together into <= 64 bit chunks.
  uint64_t twos = 0;
  std::vector<uint64_t> terms;
  uint64_t m = 1;
  for(uint64_t i = 1; i <= n; i++) {
    uint64_t j = __builtin_ctzll(i);
    twos += j;
    uint64_t k = i >> j;
    if(__builtin_clzll(m) + __builtin_clzll(k) >= 64) {
      m *= k;
    } else {
      terms.push_back(m);
      m = k;
    }
  }
  if(m != 1) terms.push_back(m);

  // convert to gmp
  // why isn't there a 64-bit constructor?
  std::queue<mpz_class> gmpterms;
  for(int i = 0; i < terms.size(); i++) {
    mpz_class x = (uint32_t)(terms[i] >> 32);
    x <<= 32;
    x += (uint32_t)terms[i];
    gmpterms.push(x);
  }

  // pop two from the bottom, multiply them, push on the end.
  while(gmpterms.size() > 1) {
    mpz_class a = gmpterms.front();
    gmpterms.pop();
    mpz_class b = gmpterms.front();
    gmpterms.pop();
    gmpterms.push(a * b);
  }

  mpz_class r = gmpterms.front();
  r <<= twos;
  //std::cout << r << std::endl;
}

8

পাইথন 2.7

42.575 = (6,812,000 / 160,000) প্রায়


কোড:

import gmpy2

def fac1(n):
    m=lambda(L):([]if len(L)%2==0 else[L.pop()])+map(lambda(l):l[0]*l[1],zip(L[1::2],L[-2::-2]))
    L=map(gmpy2.mpz,xrange(1,n+1))
    Number = (len(L)-1).bit_length()
    while Number:Number-=1;L=m(L)
    return L[0]

def fac2(n):
    global E; E=0
    def f(i):
        global E; E+=i//2
        return[]if i==1 else f(i//2)+range(3,i,2)+[[1,i][i%2]]
    m=lambda(L):([]if len(L)%2==0 else[L.pop()])+map(lambda(l):l[0]*l[1],zip(L[1::2],L[-2::-2]))
    L=map(gmpy2.mpz,f(n))
    N=(len(L)-1).bit_length()
    while N: N-=1;L=m(L)
    return L[0]<<E

টেস্ট:

import time

start = time.time()
baseline(160000)
print time.time()-start

start = time.time()
fac1(6811000)
print time.time()-start

start = time.time()
fac2(6812000)
print time.time()-start

start = time.time()
gmpy2.fac(26000000)
print time.time()-start

আউটপুট:

10.0069999695
10.0729999542
10.0360000134
9.98699998856

কিভাবে এটা কাজ করে:

বড় গুণগুলি আরও সময় নেয়, সুতরাং আমরা যতটা সম্ভব ছোট ছোট গুণগুলি করতে চাই। এটি পাইথনের ক্ষেত্রে বিশেষভাবে সত্য যেখানে সংখ্যার তুলনায় 2^64আমরা হার্ডওয়ার পাটিগণিত ব্যবহার করি না এবং তারপরে আমরা সফ্টওয়্যার ব্যবহার করি। সুতরাং, মধ্যে m(L), আমরা একটি তালিকা দিয়ে শুরু L; যদি এটির দৈর্ঘ্যের দৈর্ঘ্য হয় তবে আমরা এটিকে আবারও তৈরি করার জন্য বিবেচনা থেকে একটি সংখ্যা সরিয়ে ফেলি। তারপরে আমরা উপাদান 1দিয়ে উপাদান -2, উপাদান ইত্যাদির 3সাথে গুণ -4করি

m([1,2,3,4,5,6,7,8]) = [2*7, 4*5, 6*3, 8*1] = [14, 20, 18, 8]
m([10,12,6]) = [360,112]
m([120,6]) = [40320]

এই পদ্ধতিটি নিশ্চিত করে আমরা যতক্ষণ সম্ভব হার্ডওয়্যার পাটিগণিত ব্যবহার করছি, এরপরে আমরা দক্ষ জিএমসি পাটিগণিত লাইব্রেরিতে স্যুইচ করি।

ইন fac2, আমরা আরও ক্লাসিক বিভাজন নিয়েছি এবং পাশাপাশি বিজয়ী পদ্ধতির দিকেও চলেছি, যেখানে আমরা 2 এর প্রতিটি বহুগুলি বিভক্ত করি এবং একটি তুচ্ছ কর্মক্ষমতা বৃদ্ধির জন্য শেষে তাদের বিটশিফ্ট করি। আমি এখানে অন্তর্ভুক্ত করেছেন এটি সাধারণত প্রায় 0.5% তুলনায় আরো দ্রুত কারণ fac1

গল্ফযুক্ত সংস্করণ fac1(কারণ আমি পারি), 220 বি

import gmpy2
def f(n):
    m=lambda(L):([]if len(L)%2==0 else[L.pop()])+map(lambda(l):l[0]*l[1],zip(L[1::2],L[-2::-2]))
    L=map(gmpy2.mpz,xrange(1,n+1));N=(len(L)-1).bit_length()
    while N:N-=1;L=m(L)
return L[0]

1
জিএমপি ব্যাকএন্ডে যদি একটি বিটশিফ্ট ফাংশন অন্তর্ভুক্ত থাকে তবে আপনি তালিকার প্রতিটি সংখ্যা 2 টি ভাগ করে না হওয়া পর্যন্ত সংখ্যাকে আরও ছোট রাখতে পারবেন এবং তারপরে শেষে একক শিফট করে doing
পিটার টেলর

কোথা থেকে পেলেন gmpy2? $ পাইথন পাইথন ২.7.৩ (ডিফল্ট, ফেব্রুয়ারী ২ 2014 2014, 19:58:35) [জিসিসি 4.6.3] লিনাক্স 2 এ আরও তথ্যের জন্য "সহায়তা", "কপিরাইট", "ক্রেডিট" বা "লাইসেন্স" টাইপ করুন। >>> gmpy2 আমদানি এমপিজেড থেকে ট্রেসব্যাক (সর্বশেষতম কল): ফাইল "<stdin>", লাইন 1, <মডুল> আমদানি ত্রুটি: gmpy2 নামে কোনও মডিউল >>>
ব্যবহারকারী 80551

@ ব্যবহারকারী 80551: কোড. google.com/p/gmpy (শীর্ষস্থানীয় গুগল অনুসন্ধান ফলাফল) এর অনেকগুলি বিভিন্ন প্ল্যাটফর্মের জন্য ইনস্টলার রয়েছে।
আলেকজান্ডার-ব্রেট

গল্ফযুক্ত সংস্করণের জন্য, আপনি কি এর while len(L): ...পরিবর্তে না করতে পারেন while len(L)>1: ...?
ব্যবহারকারী 80551

না: সেই লুপের ভিতরে ফাংশনটি কখনই দৈর্ঘ্য 1 এর নীচে তালিকাটি নেবে না এবং যেভাবেই আমাদের প্রথম উপাদানটির প্রয়োজন!
আলেকজান্ডার-ব্রেট

2

জাভা - 125.15 (21,400,000 / 171,000)

এছাড়াও নির্লজ্জভাবে পিটার লুশনির গিথুব রেপো থেকে কপি করেছেন (ধন্যবাদ @ অর্ধ-বহির্মুখী) এবং এমআইটি লাইসেন্সের আওতায় লাইসেন্সযুক্ত, এটি আলবার্ট শানহেজ এট আল দ্বারা প্রস্তাবিত "প্রাইম ফ্যাক্টেরাইজেশন নেস্টড স্কোয়ারিং" অ্যালগরিদম ব্যবহার করে। (লুশ্নির কল্পিত অ্যালগরিদমের বিবরণ পৃষ্ঠা অনুসারে )।

আমি জাভাটির বিগইন্টিজারটি ব্যবহার করতে এবং এন <20 এর জন্য কোনও সন্ধানের টেবিলটি ব্যবহার না করার জন্য অ্যালগোরিদমটি সামান্যভাবে গ্রহণ করেছি।

জিসিজে দিয়ে সংকলিত, যা এর বিগইন্টিজার বাস্তবায়নের জন্য জিএমপি ব্যবহার করে এবং লিনাক্স ৩.১২.৪ (জেন্টু), ২.৪০ গিগাহার্টজে কোর আই 47 4700 এমকিউতে ছুটেছিল

import java.math.BigInteger;

public class PrimeSieveFactorialSchoenhage {

    private static int[] primeList, multiList;

    public static BigInteger factorial(int n) {
        int log2n = 31 - Integer.numberOfLeadingZeros(n);
        int piN = log2n < 2 ? 1 : 2 + (15 * n) / (8 * (log2n - 1));

        primeList = new int[piN];
        multiList = new int[piN];

        int len = primeFactors(n);
        return nestedSquare(len).shiftLeft(n - Integer.bitCount(n));
    }

    private static BigInteger nestedSquare(int len) {
        if (len == 0) {
            return BigInteger.ONE;
        }

        int i = 0, mult = multiList[0];

        while (mult > 1) {
            if ((mult & 1) == 1) { // is mult odd ?
                primeList[len++] = primeList[i];
            }

            multiList[i++] = mult / 2;
            mult = multiList[i];
        }
        BigInteger ns = nestedSquare(i);
        if (len <= i) {
            return ns.multiply(ns);
        }

        return product(primeList, i, len - i).multiply(ns.multiply(ns));
    }

    private static BigInteger product(int[] a, int start, int length) {
        if (length == 0) {
            return BigInteger.ONE;
        }

        int len = (length + 1) / 2;
        long[] b = new long[len];

        int i, j, k;

        for (k = 0, i = start, j = start + length - 1; i < j; i++, k++, j--) {
            b[k] = a[i] * (long) a[j];
        }

        if (i == j) {
            b[k++] = a[j];
        }

        return recProduct(b, 0, k - 1);
    }

    private static BigInteger recProduct(long[] s, int n, int m) {
        if (n > m) {
            return BigInteger.ONE;
        }
        if (n == m) {
            return BigInteger.valueOf(s[n]);
        }
        int k = (n + m) >> 1;
        return recProduct(s, n, k).multiply(recProduct(s, k + 1, m));
    }

    private static int primeFactors(int n) {
        int[] primes = new int[n < 17 ? 6 : (int) Math.floor(n / (Math.log(n) - 1.5))];
        int numPrimes = makePrimeList(n, primes);

        int maxBound = n / 2, count = 0;

        int start = indexOf(primes, 2, 0, numPrimes - 1);
        int end = indexOf(primes, n, start, numPrimes);

        for (int i = start; i < end; i++) {
            int prime = primes[i];
            int m = prime > maxBound ? 1 : 0;

            if (prime <= maxBound) {
                int q = n;
                while (q >= prime) {
                    m += q /= prime;
                }
            }

            primeList[count] = prime;
            multiList[count++] = m;
        }
        return count;
    }

    private static int indexOf(final int[] data, int value, int low, int high) {
        while (low < high) {
            int mid = (low + high) >>> 1;

            if (data[mid] < value) {
                low = mid + 1;
            } else {
                high = mid;
            }
        }

        if (low >= data.length) {
            return low;
        }

        if (data[low] == value) {
            low++;
        }

        return low;
    }

    private static int makePrimeList(int n, int[] prime) {
        boolean[] composite = new boolean[n / 3];

        sieveOfEratosthenes(composite);

        boolean toggle = false;
        int p = 5, i = 0, j = 2;

        prime[0] = 2;
        prime[1] = 3;

        while (p <= n) {
            if (!composite[i++]) {
                prime[j++] = p;
            }
            // -- never mind, it's ok.
            p += (toggle = !toggle) ? 2 : 4;
        }

        return j; // number of primes
    }

    private static void sieveOfEratosthenes(final boolean[] composite) {
        int d1 = 8;
        int d2 = 8;
        int p1 = 3;
        int p2 = 7;
        int s1 = 7;
        int s2 = 3;
        int n = 0;
        int len = composite.length;
        boolean toggle = false;

        while (s1 < len) { // -- scan sieve
            if (!composite[n++]) { // -- if a prime is found, cancel its multiples
                int inc = p1 + p2;

                for (int k = s1; k < len; k += inc) {
                    composite[k] = true;
                }

                for (int k = s1 + s2; k < len; k += inc) {
                    composite[k] = true;
                }
            }

            if (toggle = !toggle) { // Never mind, it's ok.
                s1 += d2;
                d1 += 16;
                p1 += 2;
                p2 += 2;
                s2 = p2;
            } else {
                s1 += d1;
                d2 += 8;
                p1 += 2;
                p2 += 6;
                s2 = p1;
            }
        }
    }

    public static void main(String[] args) {
        int n = Integer.parseInt(args[0]);
        long nanos = System.nanoTime();
        BigInteger fact = factorial(n);
        nanos = System.nanoTime() - nanos;
        // Commented out because it takes ages to print
        //System.out.println(fact);
        System.out.println(nanos / 1e9);
    }
}

সংকলিতgcj -O3 --main=PrimeSieveFactorialSchoenhage PrimeSieveFactorialSchoenhage.java -o pf_nest_square_fact
14mRh4X0r

1

পাইথন 3, এন = 100000

একটি সাধারণ অ্যালগরিদম পরিবর্তন যা ছিল 10000 দ্বারা স্যাম্পল কোডটি ফাটিয়ে দেওয়া দরকার ছিল।

import time

def factorial(n):
    result = 1
    while n > 0:
        result *= n
        n = n - 1
    return result

start = time.clock()
answer = factorial(100000)
end = time.clock()

print(answer)
print("Time:", end - start, "sec")

স্পষ্টতই সর্বাধিক সৃজনশীল উত্তর নয়, তবে একটি ফ্যাক্টরিয়াল করার সত্যিই কেবল একটি উপায় আছে ....


স্কোর দিন, আমার সম্পাদনা দেখুন। আচমকা সম্ভবত হবে কারণ আপনার মেশিনে খনি চেয়ে ভাল।
ব্যবহারকারী 80551

1

পার্ল + সি, এন = প্রায় 3 মিলিয়ন

এখানে আমি সিপিএএন- তে ম্যাথ :: বিগিয়ান্ট :: জিএমপি গ্রন্থাগারটি ব্যবহার করছি , যা পার্লের কোর ম্যাথ :: বিগআইএন্ট অবজেক্টের জন্য একটি বিশাল গতি বাড়িয়ে তোলে।

use v5.14;
use Time::HiRes 'time';
use Math::BigInt only => 'GMP';

sub factorial { Math::BigInt::->new(@_)->bfac }

my $start  = time;
my $answer = factorial( 3_000_000 );
my $end    = time;

say $answer;
say "Time: ", $end - $start, " sec";

মনে রাখবেন যে আমার কম্পিউটারটি সম্ভবত আপনার চেয়ে কিছুটা ধীর। আপনার মূল পাইথন স্ক্রিপ্ট ব্যবহার করে, আমি কেবল factorial(40000)10 সেকেন্ডের মধ্যে গণনা করতে পারি ; factorial(90000)অনেক বেশি সময় নেয়। (আমি এক মিনিটের পরে Ctrl + C চাপলাম hit) আপনার হার্ডওয়্যারে, ম্যাথ :: বিগইন্ট :: জিএমপি ব্যবহার করে, আপনি 10 সেকেন্ডের মধ্যে 5 মিলিয়ন বা তারও বেশি সংখ্যক এর ফ্যাক্টরিয়ালটি গণনা করতে সক্ষম হতে পারেন ।

একটি জিনিস আপনি লক্ষ্য করতে পারেন যে কল্পিতটি অবিশ্বাস্যভাবে দ্রুত গণনা করা হলেও ফলাফলটি মুদ্রণ করা খুব ধীর, মূল গণনার চেয়ে প্রায় তিনগুণ বেশি সময় নেয়। এটি কারণ GMP অভ্যন্তরীণ দশমিক প্রতিনিধিত্বের চেয়ে বাইনারি ব্যবহার করে এবং এটি মুদ্রণের জন্য বাইনারি থেকে দশমিক রূপান্তর প্রয়োজন।


1
আমি মনে করি জিএমপি একটি বাহ্যিক সংস্থান হিসাবে গণ্য। (এটা অবশ্যই কিছু অনেক হইছে বাস্তবায়নের চেয়ে সহজ করে তোলে যদিও উত্তর দিবেন এবং Schönhage-Strassen গুণ গোড়া থেকে।)
r3mainer


স্ক্যোয়ামিশ: লাইব্রেরিগুলি সাধারণত বিরক্তিকর লফোলস বিধিটির আওতায় আসে এমন কোনও ফাংশন না থাকলে বাহ্যিক সংস্থান হিসাবে গণ্য হয় না।
আলেকজান্দার-ব্রেট

1
টবিঙ্ক: আপনার প্রোগ্রামটি কী ব্যাখ্যা করতে পারে? দেখে মনে হচ্ছে আপনি কেবল একটি বিল্ট-ইন ফাংশন (বিফ্যাক?) ব্যবহার করছেন
আলেকজান্দার-ব্রেট

হা. এই উত্তরটি অবৈধ, যেহেতু এটিMath::BigInt
14mRh4X0r

1

পাইথন 2.7
5.94 = 1'200'000 / 202'000

def fast_fac(n):
    def prod(start, fin):
            if fin - start <= 50:
                    return reduce(lambda x,y: x*y, xrange(start, fin+1), 1)
            else:
                    mid = (start+fin) / 2
                    return prod(start, mid) * prod(mid+1, fin)
    return prod(1, n)

বিপুল সংখ্যক জড়িত বৃহত সংখ্যার সাথে তুলনা করে ছোট সংখ্যার অনেকগুলি গোষ্ঠীর গুণিতকরণের তুলনায় আপেক্ষিক স্বাচ্ছন্দ্যের ব্যবহার করে এবং তারপরে এগুলি গুণ করে।


1

সি #: 0,48 (77,000 / 160,000)

আমি এতে খুশি নই।

সি # কি ধীর?

তবে এখানে যাইহোক আমার প্রবেশ।

static void Main(string[] args)
    {
        Console.WriteLine("Enter N for fatorial:");
        int n = Convert.ToInt32(Console.ReadLine());

        Stopwatch s = Stopwatch.StartNew();


        BigInteger result = 1;
        while (0 <-- n) result *= n;

        s.Stop();

        Console.WriteLine("Output: {0} ", result);

        Console.WriteLine("Completed in {0}", s.Elapsed);

    }

যখন n = 77000 00:00:09:8708952গণনা করতে লাগে ।

আমি রিলিজ মোডে চলছি, ভিজ্যুয়াল স্টুডিওর বাইরে, একটি কোর i3-2330M @ 2.2GHz ব্যবহার করে।

সম্পাদনা: যেহেতু আমি বুদ্ধিমান কিছু করছি না, তাই আমি সেই ফলাফলটি গ্রহণ করি। হতে পারে। নেট ফ্রেমওয়ার্ক 4.5 কিছু ওভারহেড অ্যাডইন্ড হয় (বা বিগইন্টিজার তত দ্রুত নয়)।


স্কোর দিন এবং নাn
ব্যবহারকারী 80551

1
আপনি zero approached byএটিকে সুন্দর করার জন্য অপারেটরটি ব্যবহার করতে পারেন (যেমন করুন তার সাথে শুরু n = ... + 1করুন while (0 <-- n) result *= n;)
চতুহুলু

1
.NET- র জন্য বিগইন্টিজার সম্ভবত করাতসুবা বা টুম -3 এর মতো বৃহত সংখ্যার গুণনের জন্য অ্যালগরিদমগুলি প্রয়োগ করেনি। যদি তা হয় তবে পাইথন কীভাবে দ্রুত হয় তার এটি একটি উত্তম উদাহরণ।
kernigh

1

বিসি, স্কোর = 0.19

হ্যাক কী, এখানে "আপনি আস্তে আস্তে কত গুণ করতে পারেন?"

বিসি হ'ল "একটি নির্বিচারে নির্ভুলতা ক্যালকুলেটর ভাষা", তবে দুর্ভাগ্যক্রমে বরং ধীর:

n=read()
for(f=i=1;i<=n;i++)f*=i
f
quit

আমার মধ্যবর্তী ২০১২ ম্যাকবুক প্রো (২.৩ গিগাহার্টজ ইন্টেল কোর আই)) প্রায় 10 সেকেন্ডে রেফারেন্স পাইথন উত্তরটি 122000 গণনা করতে পারে !, তবে এই বিসি স্ক্রিপ্টটি কেবল 23600 গণনা করতে পারে !.

বিপরীতে 10000! পাইথন রেফারেন্স স্ক্রিপ্টের সাথে 1.5s লাগে, তবে বিসি স্ক্রিপ্টটি 50s লাগে।

ওহে প্রিয়।


1
ওপেনবিএসডি বিসি (1) দ্রুততর। আপনার প্রোগ্রামের স্কোর 0.29 = 28000/98000। নেই read(), তাই দৌড়ে গেলাম time sed 's/read()/28000/' factorial.bc | bc
কর্নি

1

বাশ: স্কোর = 0.001206 (181/150000)

আমি রোজটাকোড থেকে গণিতের ফাংশনগুলি চুরি করেছি - দীর্ঘ গুণটি আমি বিশ্লেষণ করিনি বা অনুকূলকরণের চেষ্টাও করিনি।
আপনি অ্যালগরিদম পরিবর্তন করতে বা একটি ভিন্ন স্ট্রিং বিভক্ত পদ্ধতি চেষ্টা করতে মুক্ত।

#!/bin/bash


add() { # arbitrary-precision addition
  if (( ${#1} < ${#2} )); then
    local a="$2" b="$1" sum= carry=0
  else
    local a="$1" b="$2" sum= carry=0
  fi

  while (( ${#a} )); do
    local -i d1="${a##${a%?}}" d2="10#0${b##${b%?}}" s=carry+d1+d2
    sum="${s##${s%?}}$sum"
    carry="10#0${s%?}"
    a="${a%?}" b="${b%?}"
  done
  echo "$sum"
}

multiply() { # arbitrary-precision multiplication
  if (( ${#1} < ${#2} )); then
    local a="$2" b="$1" product=0
  else
    local a="$1" b="$2" product=0
  fi

  local zeroes=
  while (( ${#b} )); do
    local m1="$a"
    local m2="${b##${b%?}}"
    local partial=$zeroes 
    local -i carry=0
    while (( ${#m1} )); do 
      local -i d="${m1##${m1%?}}"
      m1="${m1%?}"
      local -i p=d*m2+carry
      partial="${p##${p%?}}$partial"
      carry="10#0${p%?}"
    done
    partial="${carry#0}$partial"
    product="$(add "$product" "$partial")"
    zeroes=0$zeroes
    b="${b%?}"
  done
  echo "$product"
}

# 'timerun' function
trap 'echo $((i -1)) $f; exit'  USR1  
(sleep 9.9; kill -USR1 $$)&

declare -i i 
f=1
for ((i=1; i< 10000 ; i++ ))   # 10000 is verry optimistic
do
    f=$(multiply $f $i)
done 

1
স্কোর যুক্ত করুন এবং সর্বাধিক এন
ব্যবহারকারী 80551

@ ব্যবহারকারী 80551 এটি হয়ে গেছে
এমমানুয়েল

1

পাইথন 3, পিটার লুশনি দ্বারা উন্নত আলগো: 8.25x (1 280 000/155 000)

নির্লজ্জভাবে পিটার Luschny থেকে কপি করা
http://www.luschny.de/math/factorial/FastFactorialFunctions.htm ,
যারা "ক্রিয়েটিভ কমন্স এট্রিবিউশন-শেয়ারএলাইক 3.0" লাইসেন্সের অধীনে এই কোড প্রদান করে।

এটি "সুইং ফ্যাক্টরিয়াল" নামে পরিচিত কিছু এবং প্রাইমসের একটি তালিকা ব্যবহার করে এটি বেশ উন্নত অ্যালগরিদম। আমি সন্দেহ করি এটি অন্যান্য উত্তরগুলির মতো করে এবং 32 বিট সংখ্যার সাথে বেশিরভাগ গুণগুলি সম্পাদন করলে এটি আরও দ্রুততর হতে পারে।

#! /usr/bin/python3
import time
import bisect 

def Primes(n) : 
  primes = [2, 3] 
  lim, tog = n // 3, False 
  composite = [False for i in range(lim)] 

  d1 = 8; d2 = 8; p1 = 3; p2 = 7; s = 7; s2 = 3; m = -1 

  while s < lim :             # --  scan the sieve 
      m += 1                  # --  if a prime is found 
      if not composite[m] :   # --  cancel its multiples 
          inc = p1 + p2 
          for k in range(s,      lim, inc) : composite[k] = True 
          for k in range(s + s2, lim, inc) : composite[k] = True 

          tog = not tog 
          if tog: s += d2; d1 += 16; p1 += 2; p2 += 2; s2 = p2 
          else:   s += d1; d2 +=  8; p1 += 2; p2 += 6; s2 = p1 

  k, p, tog = 0, 5, False 
  while p <= n : 
      if not composite[k] : primes.append(p) 
      k += 1; 
      tog = not tog 
      p += 2 if tog else 4 

  return primes 

def isqrt(x): 
  ''' 
  Writing your own square root function
  ''' 
  if x < 0: raise ValueError('square root not defined for negative numbers') 
  n = int(x) 
  if n == 0: return 0 
  a, b = divmod(n.bit_length(), 2) 
  x = 2**(a + b) 
  while True: 
      y = (x + n // x) // 2 
      if y >= x: return x 
      x = y 

def product(s, n, m): 
  if n > m: return 1 
  if n == m: return s[n] 
  k = (n + m) // 2 
  return product(s, n, k) * product(s, k + 1, m) 

def factorialPS(n): 

  small_swing = [1,1,1,3,3,15,5,35,35,315,63,693,231,3003,429,6435,6435, 
          109395,12155,230945,46189,969969,88179,2028117,676039,16900975, 
          1300075,35102025,5014575,145422675,9694845,300540195,300540195] 

  def swing(m, primes): 
      if m < 33: return small_swing[m] 

      s = bisect.bisect_left(primes, 1 + isqrt(m)) 
      d = bisect.bisect_left(primes, 1 + m // 3) 
      e = bisect.bisect_left(primes, 1 + m // 2) 
      g = bisect.bisect_left(primes, 1 + m) 

      factors = primes[e:g] 
      factors += filter(lambda x: (m // x) & 1 == 1, primes[s:d]) 
      for prime in primes[1:s]:   
          p, q = 1, m 
          while True: 
              q //= prime 
              if q == 0: break 
              if q & 1 == 1: 
                  p *= prime 
          if p > 1: factors.append(p) 

      return product(factors, 0, len(factors) - 1) 

  def odd_factorial(n, primes): 
      if n < 2: return 1 
      return (odd_factorial(n // 2, primes)**2) * swing(n, primes) 

  def eval(n): 
      if n < 0: 
          raise ValueError('factorial not defined for negative numbers') 

      if n == 0: return 1 
      if n < 20: return product(range(2, n + 1), 0, n-2) 

      N, bits = n, n 
      while N != 0: 
          bits -= N & 1 
          N >>= 1 

      primes = Primes(n) 
      return odd_factorial(n, primes) * 2**bits 

  return eval(n)

start = time.time()
answer = factorialPS(1280000) 
print(time.time()-start)

1

জাভা - 10.9

n = 885000

Mergesort-Y।

import java.math.BigInteger;

public class Factorials {

    public static BigInteger fac;

    public static BigInteger two = BigInteger.valueOf(2);

    static BigInteger mul(BigInteger start, BigInteger end) {
        if(start.equals(end)) {
            return start;
        } else {
            BigInteger mid = start.add(end.subtract(start).divide(Factorials.two));
            return Factorials.mul(start, mid).multiply(Factorials.mul(mid.add(BigInteger.ONE), end));
        }
    }

    public static void main(String[] args) {
        Factorials.fac = BigInteger.valueOf(Integer.parseInt(args[0]));
        long t = System.nanoTime();
        BigInteger result = mul(BigInteger.ONE, fac);
        t = System.nanoTime() - t;
        System.out.print(String.valueOf(((float) t) / 1000000000)); //result.toString()+" @ "+
    }
}

BigIntegers ধীর।

স্বেচ্ছাসেবী-নির্ভুলতা উচ্চ গতির জাভা সংখ্যার লাইব্রেরিগুলির জন্য প্রস্তাবনাগুলি? : P: P


আমি কি আপনার কোডটিকে বহুগঠিত করার জন্য চুরি করতে পারি?
সাইমন কুয়াং

সিমনকুয়াং : পি মাল্টি-থ্রেডযুক্ত এন্ট্রিগুলি এখানে অনুমোদিত নয়। এছাড়াও, আপনি আরও দক্ষ বিগইন্টেইজার বাস্তবায়ন ব্যবহার করতে চাইতে পারেন।
সিজেফুরে

Mergesort-y এটিকে বিভাজন এবং বিজয় বলে।
johnchen902

1

সি ++ (x86_64- নির্দিষ্ট) - 3.0 (390000/130000)

(সহজেই x86-32 তে পোর্টেবল, অন্যান্য আর্কিটেকচারে পোর্টিং একটি উল্লেখযোগ্য গতির ক্ষতি বোঝায়)

এখানে লম্বা গণিতের নিজস্ব মাইক্রো-বাস্তবায়ন।
গণনা নিজেই 10 সেকেন্ড সময় নেয় এবং আউটপুট সহজেই মুদ্রণযোগ্য আকারে ( operator<<ওভারলোড দেখুন) এটি মুদ্রণ করতে আরও কিছুটা সময় নেয়।

#include <vector>
#include <iostream>
#include <stdint.h>
#include <ctime>

typedef uint64_t digit;
typedef std::vector<digit> number;

std::ostream &operator<<(std::ostream &s, const number &x)
{
    std::vector<char> o;
    size_t size = x.size() * 21;
    o.resize(size);
    size_t lud = 0;
    for(number::const_reverse_iterator i = x.rbegin(), end = x.rend(); i != end; i++)
    {
        digit carry = 0;
        int j;
        for(j = 0; j <= lud || carry; j++)
        {
            digit r = o[j] * (1LL << 32) + carry;
            o[j] = r % 10;
            carry = r / 10;
        }
        lud = j;
        carry = 0;
        for(j = 0; j <= lud || carry; j++)
        {
            digit r = o[j] * (1LL << 32) + carry;
            o[j] = r % 10;
            carry = r / 10;
        }
        lud = j;
        carry = *i;
        for(j = 0; carry; j++)
        {
            digit r = o[j] + (carry % 10);
            carry /= 10;
            carry += r / 10;
            o[j] = r % 10;
        }
        if(j > lud)
            lud = j;
    }
    for(int j = lud; j--;)
        s.put(o[j] + '0');
    return s;
}

inline uint64_t dmul(uint64_t x, uint64_t y, uint64_t &carry)
{
    asm("mulq %2" : "+a"(x), "=d"(carry) : "r"(y));
    return x;
}
inline digit dadd(digit x, digit y, digit &carry)
{
    asm("movq $0, %1; addq %2, %0; adcq %1, %1" : "+r"(x), "=r"(carry), "+r"(y));
    return x;
}

void multiply(number &x, digit y)
{
    x.resize(x.size() + 2);
    digit carry = 0;
    for(number::iterator i = x.begin(), end = x.end(); i != end; i++)
    {
        digit nc, res = dmul(*i, y, nc);
        *i = dadd(res, carry, carry);
        carry += nc;
    }
    size_t sz = x.size();
    for(number::const_reverse_iterator i = x.rbegin(), end = x.rend(); i != end; i++)
    {
        if(*i)
            break;
        sz--;
    }
    x.resize(sz);
}

int main()
{
    const int r = 390000;
    clock_t start = clock();
    number n;
    digit mult = 1;
    n.push_back(1);
    for(digit a = 2; a <= r; a++)
    {
        digit carry, m = dmul(mult, a, carry);
        if(carry)
        {
            multiply(n, mult);
            mult = a;
        }
        else
            mult = m;
    }
    multiply(n, mult);
    std::cout << "Took: " << (clock() - start)/((double)CLOCKS_PER_SEC) << std::endl;
    std::cout << n << std::endl;
}

আপনার স্কোর পরীক্ষা করুন। আপনার কম্পিউটারে প্রশ্নের পাইথন ২.7 প্রোগ্রামটি চালানো দরকার। আমার কম্পিউটারে জন্য, আমি সঙ্গে আপনার প্রোগ্রাম কম্পাইল g++ -O2 factorial.cc -o factorialএবং এটি স্কোর 3.90 = 382000 / 98000.
kernigh

অদ্ভুত, আমি 3.9 পেয়েছি এবং আপনি এই প্রোগ্রামের জন্য 3.0 পেয়েছেন। আমার ধারণা আপনার দ্রুত কম্পিউটারটি একটি পেনাল্টি। সম্ভবত আপনার প্রোগ্রামটি পাইথনের চেয়ে rবাড়ার সাথে সাথে এর সুবিধাটি হারাবে । যদি তা হয়, এবং আপনি r10 সেকেন্ডের মধ্যে আরও উচ্চতর করতে পারেন , তবে আপনার স্কোর হ্রাস পাবে।
kernigh

0

পাইথন 3: 280000/168000

আপনার প্রোগ্রাম চালানোর সময়: এর মধ্যে 9.87585953253এবং 10.3046453994। আমার প্রোগ্রাম চলমান সময়: প্রায় 10.35296977897559

import time

def factorial(n):
    f = 1
    while n > 1:
        hn = n >> 1
        f = f * 2**hn * double_factorial(n) #dfl[hn + (n & 1) - 1]
        n = hn
    return f
def double_factorial(n):
    #dfl = [1]
    p = 1
    l = 3
    mh = n
    while l <= n:
        p *= l
        l += 2
        #dfl.append(p)
    return p

start = time.clock()
factorial(280000)
end = time.clock()

print(end - start)

আমি এই উত্তরটি সিএসই তে পড়েছি এবং পাইথনে এটি প্রয়োগের চেষ্টা করার সিদ্ধান্ত নিয়েছি। যাইহোক, আমি ঘটনাক্রমে আবিষ্কার করেন যে n! = (⌊n / 2⌋)! * 2**(⌊n / 2⌋) * n!!(দ্রষ্টব্য: !!হয় দ্বৈত গৌণিক )। সুতরাং আমি এটিকে একটি পুনরাবৃত্ত আকারে রূপান্তরিত করেছি।

মন্তব্যগুলি ডাবল ফ্যাক্টরিয়ালটির পুনর্নির্মাণ এড়াতে আমার প্রয়াস দেখায়, কিন্তু আমি আবিষ্কার করেছি যে প্রতিটি মান সংরক্ষণ করা খুব বেশি স্মৃতি-ব্যয়বহুল যা আমার কম্পিউটারকে আরও ধীর করে চালিয়েছে। আমি কেবল যা প্রয়োজন তা সঞ্চয় করে এটিকে উন্নত করতে পারি।

আশ্চর্যের বিষয় হল, আমি পাইথন 3 এ সরল গুটি গুটি প্রয়োগ করেছি এবং এটি আপনার প্রোগ্রামের চেয়ে n = 16900010 গুণ সেকেন্ডে আরও ভাল করেছে:

def factorial(n):
    p=1
    for i in range(n):
        p*=i+1
    return p

0

রুবি 2.1

স্কোর = 1.80 = 176_000 / 98_000

সম্পাদনা: 1.35 = 132_000 / 98_000 থেকে উন্নত

আমি জিএমপি ফ্যাকটোরিয়াল অ্যালগরিদম থেকে ধারণা নিয়েছি । এই প্রোগ্রামটি প্রাথমিক সংখ্যা উত্পন্ন করতে মানক গ্রন্থাগার ব্যবহার করে। রুবি একটি খারাপ পছন্দ কারণ পাইথনের তুলনায় রুবিতে গুণটি ধীর বলে মনে হচ্ছে।

  1. রুবি ২.১ এ আমার প্রোগ্রাম: স্কোর = 1.80 = 176_000 / 98_000
  2. পাইথন ২.7 এ তুচ্ছ আলগোরিদিম: স্কোর = 1 = 98_000 / 98_000
  3. রুবি ২.১ এ তুচ্ছ আলগোরিদম: স্কোর = 0.878 = 86_000 / 98_000

হ্যাঁ, ruby 2.1.0p0 (2013-12-25 revision 44422) [x86_64-openbsd]জিএমপির বিরুদ্ধে আমার বাইনারি লিঙ্কগুলি। রুবি ২.১ বৃহত গুণনের জন্য জিএমপি ব্যবহার করতে একটি বৈশিষ্ট্য যুক্ত করেছে, তবে এটি পাইথন ২.7 এর চেয়ে ধীর বলে মনে হচ্ছে।

require 'benchmark'
require 'optparse'
require 'prime'

def factorial(n)
  # calculate primes up to n, drop the 2
  @odd_primes = Prime.each(n).drop(1)

  # count prime factors of factorial(n)
  @factors = Hash.new(0)
  factorial_recurse(n)

  shift = @factors.delete(2) || 0
  @factors.inject(1) {|product, (base, exp)|
    product * base**exp
  } << shift
end

def factorial_recurse(n)
  return if n < 2

  # collect prime factors of 2 * 4 * 6 * .. * n
  #  = (2 * 2 * 2 * .. * 2) * (1 * 2 * 3 * .. * exp)
  #  = 2**exp * factorial(exp) where exp = floor(n/2)
  exp = n >> 1
  factorial_recurse(exp)
  @factors[2] += exp

  # collect prime factors 3 * 5 * 7 * ... * n
  for prime in @odd_primes
    break if prime > n
    exp = 0
    # count occurences of prime, prime**2, prime**3, .. n
    prime_power = prime
    until prime_power > n
      # floor(n / prime_power) occurences in 1 * 2 * .. * n,
      # but only ceil(count / 2) occurences in 3 * 5 * .. * n
      @factors[prime] += (n / prime_power + 1) >> 1
      prime_power *= prime
    end
  end
end

# usage: factorial.rb [-ct] [number]
cflag = tflag = false
OptionParser.new {|opts|
  opts.on('-c', 'Check for bugs') { cflag = true }
  opts.on('-t', 'Use trivial algorithm') { tflag = true }
  opts.parse!
}
$*[1] and fail 'too many arguments'
n = Integer($*[0] || 176_000)

if cflag
  factorial(n) == (1..n).reduce(1, :*) or
    fail "bad program: factorial(#{n}) is wrong"
  puts "ok"
  exit
end

# measure processor time to calculate factorial
f = nil
if tflag
  time = Benchmark.measure { f = (1..n).reduce(1, :*) }
else
  time = Benchmark.measure { f = factorial(n) }
end
puts f
puts "Time #{time.total} sec"

0

জুলিয়া - স্কোর = 15.194

রেফারেন্স প্রোগ্রামের মতো ঠিক একই পদ্ধতির ব্যবহার করা হচ্ছে ... এটি হ'ল

f(n)=reduce(*,1:big(n))

সুতরাং এটি হ্রাস, মৌলিক বাইনারি গুণিত অপারেশন এবং একটি পরিসীমা (এই ক্ষেত্রে, বড় (এন) ব্যবহার করে গণনাটি ইন্টার -64 এর চেয়ে বিগইন্টে করতে বাধ্য করতে ব্যবহৃত হয়) ব্যবহার করে। এই থেকে, আমি পেতে

julia> @time K=f(2340000);
elapsed time: 9.991324093 seconds (814552840 bytes allocated)

আমার কম্পিউটারে, 154000 ইনপুট নিয়ে রেফারেন্স প্রোগ্রাম সহ, আমি Time: 10.041181 secআউটপুট পাই (ব্যবহার করে চালান python ./test.py, যেখানে টেস্ট.পি রেফারেন্স কোডযুক্ত ফাইলটির নাম)


0

tcl, 13757

আমার উত্তর টিসিএল এর সীমা পরীক্ষা করা হয়।

প্রথম লাইনটি কেবলমাত্র একটি ইনপুট প্যারামিটার সেট করতে হয়:

set n 13757

অন্যরা হ'ল নিজেই অ্যালগরিদম:

set r 2
for {set i 3} {$i <= $n} {incr i} {set r [expr {$r*$i}]}   
puts $r

আমি http://rextester.com/live/WEL36956 এ আমার কোড পরীক্ষা করেছি ; আমি যদি আরও বড় করে তুলি তবে আমি একটি সিগ্কিল পাব; স্থানীয় এনসিএল দোভাষীর কাছে এন বড় হতে পারে যা আমার কাছে নেই।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.