কম্পিউটার: আপনি গণিত করেন


13

এই চ্যালেঞ্জটি আংশিকভাবে একটি অ্যালগরিদম চ্যালেঞ্জ, কিছু গণিত জড়িত এবং আংশিকভাবে কেবল একটি দ্রুততম কোড চ্যালেঞ্জ।

কিছু ধনাত্মক পূর্ণসংখ্যার জন্য n, 1s এবং 0s দৈর্ঘ্যের একটি অভিন্ন র্যান্ডম স্ট্রিং বিবেচনা করুন nএবং এটিকে কল করুন A। এখন দ্বিতীয় দ্বিতীয়টি হিসাবে বেছে নেওয়া এলোমেলো স্ট্রিংয়ের দৈর্ঘ্যের nমান বিবেচনা করুন -1, 0,বা 1এটি কল করুন B_pre। এখন দিন Bহতে B_pre+ + B_pre। এটি B_preনিজেই কনকনেটেড।

এখন ভেতরের পণ্য বিবেচনা Aএবং B[j,...,j+n-1]এবং এটি কল Z_jএবং সূচক থেকে 1

কার্য

আউটপুটটি n+1ভগ্নাংশের একটি তালিকা হওয়া উচিত । iআউটপুটে তম শব্দটি হওয়া উচিত সঠিক সম্ভাব্যতা যে সব প্রথম iপদ Z_jসঙ্গে j <= iসমান 0

স্কোর

সবচেয়ে বড় nযার জন্য আপনার কোডটি আমার মেশিনে 10 মিনিটের মধ্যে সঠিক আউটপুট দেয়।

টাইব্রেকার

দুটি উত্তরের যদি একই স্কোর থাকে তবে একটি জমা দেয় প্রথমে।

(খুব খুব) সম্ভাব্য ইভেন্টে যে কেউ সীমাহীন স্কোর পাওয়ার জন্য কোনও পদ্ধতি আবিষ্কার করে, এই জাতীয় সমাধানের প্রথম বৈধ প্রমাণ গ্রহণ করা হবে।

ইঙ্গিত

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

ভাষা ও গ্রন্থাগার

আপনি যে কোনও ভাষা নিখরচায় উপলব্ধ সংকলক / দোভাষী / ইত্যাদি ব্যবহার করতে পারেন। লিনাক্স এবং যে কোনও লাইব্রেরির জন্য লিনাক্সের জন্য নিখরচায় উপলব্ধ।

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


কিছু পরীক্ষার ফলাফল। প্রতিটি জন্য প্রথম আউটপুট বিবেচনা করুন n। যখন হয় i=1। জন্য n1 13 তারা হওয়া উচিত।

 1: 4/6
 2: 18/36
 3: 88/216
 4: 454/1296
 5: 2424/7776
 6: 13236/46656
 7: 73392/279936
 8: 411462/1679616
 9: 2325976/10077696
10: 13233628/60466176
11: 75682512/362797056
12: 434662684/2176782336
13: 2505229744/13060694016

আপনি http://oeis.org/A081671i=1 এ এর জন্য একটি সাধারণ সূত্রও খুঁজে পেতে পারেন ।

লিডারবোর্ড (ভাষা দ্বারা বিভক্ত)

  • n = 15. পাইকন + সমান্তরাল পাইথন + পাইপ 1 মেক 49 এ জাকুবে লিখেছেন
  • n = 17. কিথ র্যান্ডাল রচনা 3 মিমি 37 এ সি ++
  • n = 16. সি ++ 2 মিনিটের মধ্যে কুরোই নেকো দ্বারা

1
@ কীনার্ড আমি কীভাবে বলতে পারি না। আমি কীভাবে আপনার কোডটি লিনাক্সে চালাতে পারি তা চেষ্টা করার চেষ্টা করব তবে যে কোনও সহায়তা অনেক প্রশংসিত।

ঠিক আছে, মন্তব্য মুছে ফেলার জন্য দুঃখিত। যেটি পড়েনি, সবার জন্য এটি F # বা C # এর অনুমতি থাকলে :)
কেনার্ড

অন্য প্রশ্নটি আবার, আপনার কাছে বৈধ ইনপুট আউটপুট উদাহরণ থাকতে পারে?
কিনার্ড

আপনার গ্রাফিক কার্ড কি? দেখে মনে হচ্ছে কোনও জিপিইউর চাকরির মতো।
মাইকেল এম

1
@ কেনার্ড আমি পরিবর্তে প্রশ্নের সম্ভাবনার একটি সারণী যুক্ত করেছি। আমি এটা সহায়ক আশা করি।

উত্তর:


5

সি ++, এন = 18 8 থ্রেডে 9 মিনিটে

(এটি আপনার মেশিনে 10 মিনিটের মধ্যে তৈরি করে কিনা তা আমাকে জানান))

আমি বি অ্যারেতে বিভিন্ন ধরণের প্রতিসাম্য ব্যবহার করি। এগুলি হ'ল চক্রীয় (একটি অবস্থানের মাধ্যমে স্থানান্তরিত), বিপরীতমুখী (উপাদানগুলির ক্রম বিপরীত), এবং সাইন ইন (প্রতিটি উপাদানের নেতিবাচক গ্রহণ করুন)। প্রথমে আমি যে বিএস এর চেষ্টা করতে হবে তার তালিকা এবং তাদের ওজন গণনা করি। তারপরে এ বি এর সমস্ত 2 ^ n মানগুলির জন্য প্রতিটি বি একটি দ্রুত রুটিন (বিটকাউন্ট নির্দেশাবলী ব্যবহার করে) চালিত হয়

এখানে n == 18 এর ফলাফল রয়েছে:

> time ./a.out 18
 1: 16547996212044 / 101559956668416
 2:  3120508430672 / 101559956668416
 3:   620923097438 / 101559956668416
 4:   129930911672 / 101559956668416
 5:    28197139994 / 101559956668416
 6:     6609438092 / 101559956668416
 7:     1873841888 / 101559956668416
 8:      813806426 / 101559956668416
 9:      569051084 / 101559956668416
10:      510821156 / 101559956668416
11:      496652384 / 101559956668416
12:      493092812 / 101559956668416
13:      492186008 / 101559956668416
14:      491947940 / 101559956668416
15:      491889008 / 101559956668416
16:      449710584 / 101559956668416
17:      418254922 / 101559956668416
18:      409373626 / 101559956668416

real    8m55.854s
user    67m58.336s
sys 0m5.607s

সাথে নীচের প্রোগ্রামটি সংকলন করুন g++ --std=c++11 -O3 -mpopcnt dot.cc

#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <thread>
#include <mutex>
#include <chrono>

using namespace std;

typedef long long word;

word n;

void inner(word bpos, word bneg, word w, word *cnt) {
    word maxi = n-1;
    for(word a = (1<<n)-1; a >= 0; a--) {
        word m = a;
        for(word i = maxi; i >= 0; i--, m <<= 1) {
            if(__builtin_popcount(m&bpos) != __builtin_popcount(m&bneg))
                break;
            cnt[i]+=w;
        }
    }
}

word pow(word n, word e) {
    word r = 1;
    for(word i = 0; i < e; i++) r *= n;
    return r;
}

typedef struct {
    word b;
    word weight;
} Bentry;

mutex block;
Bentry *bqueue;
word bhead;
word btail;
word done = -1;

word maxb;

// compute -1*b
word bneg(word b) {
    word w = 1;
    for(word i = 0; i < n; i++, w *= 3) {
        word d = b / w % 3;
        if(d == 1)
            b += w;
        if(d == 2)
            b -= w;
    }
    return b;
}

// rotate b one position
word brot(word b) {
    b *= 3;
    b += b / maxb;
    b %= maxb;
    return b;
}

// reverse b
word brev(word b) {
    word r = 0;
    for(word i = 0; i < n; i++) {
        r *= 3;
        r += b % 3;
        b /= 3;
    }
    return r;
}

// individual thread's work routine
void work(word *cnt) {
    while(true) {
        // get a queue entry to work on
        block.lock();
        if(btail == done) {
            block.unlock();
            return;
        }
        if(bhead == btail) {
            block.unlock();
            this_thread::sleep_for(chrono::microseconds(10));
            continue;
        }
        word i = btail++;
        block.unlock();

        // thread now owns bqueue[i], work on it
        word b = bqueue[i].b;
        word w = 1;
        word bpos = 0;
        word bneg = 0;
        for(word j = 0; j < n; j++, b /= 3) {
            word d = b % 3;
            if(d == 1)
                bpos |= 1 << j;
            if(d == 2)
                bneg |= 1 << j;
        }
        bpos |= bpos << n;
        bneg |= bneg << n;
        inner(bpos, bneg, bqueue[i].weight, cnt);
    }
}

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

    // allocate work queue
    maxb = pow(3, n);
    bqueue = (Bentry*)(malloc(maxb*sizeof(Bentry)));

    // start worker threads
    word procs = thread::hardware_concurrency();
    vector<thread> threads;
    vector<word*> counts;
    for(word p = 0; p < procs; p++) {
        word *cnt = (word*)calloc(64+n*sizeof(word), 1);
        threads.push_back(thread(work, cnt));
        counts.push_back(cnt);
    }

    // figure out which Bs we actually want to test, and with which weights
    bool *bmark = (bool*)calloc(maxb, 1);
    for(word i = 0; i < maxb; i++) {
        if(bmark[i]) continue;
        word b = i;
        word w = 0;
        for(word j = 0; j < 2; j++) {
            for(word k = 0; k < 2; k++) {
                for(word l = 0; l < n; l++) {
                    if(!bmark[b]) {
                        bmark[b] = true;
                        w++;
                    }
                    b = brot(b);
                }
                b = bneg(b);
            }
            b = brev(b);
        }
        bqueue[bhead].b = i;
        bqueue[bhead].weight = w;
        block.lock();
        bhead++;
        block.unlock();
    }
    block.lock();
    done = bhead;
    block.unlock();

    // add up results from threads
    word *cnt = (word*)calloc(n,sizeof(word));
    for(word p = 0; p < procs; p++) {
        threads[p].join();
        for(int i = 0; i < n; i++) cnt[i] += counts[p][i];
    }
    for(word i = 0; i < n; i++)
        printf("%2lld: %14lld / %14lld\n", i+1, cnt[n-1-i], maxb<<n);
    return 0;
}

ভাল, এটি আমার নিজের পোষা

এর জন্য ধন্যবাদ. আপনার বর্তমান বিজয়ী প্রবেশ রয়েছে। আমাদের -pthreadআবার মনে রাখতে হবে । আমি n=17আমার মেশিনে উঠি

উফফ .. আপনার পুরো অনুগ্রহ করা উচিত ছিল। দুঃখিত আমি সময়সীমা মিস করেছি।

@ ল্যাম্বিক: কোনও সমস্যা নেই।
কিথ র্যান্ডাল

6

পাইপিয়ন এবং পিপি ব্যবহার করে পাইথন 2: 3 মিনিটের মধ্যে n = 15

এছাড়াও কেবল একটি সাধারণ উদ্দীপনা। দেখতে আকর্ষণীয়, আমি সি ++ এর সাথে কুরোই নেখোর প্রায় একই গতি পেয়েছি। আমার কোডটি n = 12প্রায় 5 মিনিটের মধ্যে পৌঁছতে পারে । এবং আমি কেবল এটি একটি ভার্চুয়াল কোর উপর চালানো।

সম্পাদনা করুন: এর একটি উপাদান দ্বারা অনুসন্ধানের স্থান হ্রাস করুন n

আমি লক্ষ্য করেছি, যে একটি আবর্তিত ভেক্টর A*এর Aসম্ভাব্যতা (একই নম্বর) হিসাবে একই সংখ্যার উৎপন্ন মূল বাহক হিসেবে Aযখন আমি বারবার উপর B। যেমন দ্য ভেক্টর (1, 1, 0, 1, 0, 0)একই সম্ভাব্যতা ভেক্টর প্রতিটি যেমন রয়েছে (1, 0, 1, 0, 0, 1), (0, 1, 0, 0, 1, 1), (1, 0, 0, 1, 1, 0), (0, 0, 1, 1, 0, 1)এবং (0, 1, 1, 0, 1, 0)যখন একটি র্যান্ডম নির্বাচন B। অতএব আমাকে এই 6 টি ভেক্টরের প্রত্যেকটির উপরে পুনরাবৃত্তি করতে হবে না, তবে কেবল 1 টি এবং এর সাথে প্রতিস্থাপন count[i] += 1করতে হবে count[i] += cycle_number

এই থেকে জটিলতা হ্রাস Theta(n) = 6^nকরার Theta(n) = 6^n / n। সুতরাং n = 13এটির জন্য আমার আগের সংস্করণ হিসাবে প্রায় 13 গুণ দ্রুত। এটি n = 13প্রায় 2 মিনিট 20 সেকেন্ডে গণনা করে। কারণ n = 14এটি এখনও কিছুটা ধীর। এটি প্রায় 13 মিনিট সময় নেয়।

সম্পাদনা 2: মাল্টি-কোর-প্রোগ্রামিং

পরবর্তী উন্নতিতে সত্যিই খুশি নয়। আমি একাধিক কোরগুলিতে আমার প্রোগ্রামটি চালানোর চেষ্টা করার সিদ্ধান্ত নিয়েছি। আমার 2 + 2 কোরগুলিতে আমি এখন n = 14প্রায় 7 মিনিটের মধ্যে গণনা করতে পারি । শুধুমাত্র 2 উন্নতির একটি ফ্যাক্টর।

কোডটির এই GitHub রেপো উপলব্ধ: লিংক । মাল্টি-কোর প্রোগ্রামিংগুলি কিছুটা কুৎসিত।

সম্পাদনা 3: Aভেক্টর এবং Bভেক্টরগুলির জন্য অনুসন্ধানের স্থান হ্রাস করা

আমি Aভেক্টরদের জন্য একই মিরর-প্রতিসাম্য লক্ষ্য করলাম যেমন কুরোই নেখো করেছে। এখনও নিশ্চিত নয়, কেন এটি কাজ করে (এবং যদি এটি প্রতিটিটির জন্য কাজ করে n)।

Bভেক্টরগুলির জন্য অনুসন্ধানের স্থান হ্রাস করা কিছুটা চালাক। আমি ভেক্টরগুলির প্রজন্মকে ( itertools.product) একটি নিজস্ব ফাংশন দিয়ে প্রতিস্থাপন করেছি । মূলত, আমি একটি খালি তালিকা দিয়ে শুরু করি এবং এটি স্ট্যাকের উপরে রাখি। স্ট্যাকটি খালি না হওয়া অবধি আমি একটি তালিকা সরিয়ে ফেলি, যদি এর মতো দৈর্ঘ্য না থাকে তবে nআমি 3 টি অন্যান্য তালিকা তৈরি করে (-1, 0, 1 যুক্ত করে) এবং স্ট্যাকের উপরে ঠেলা দিয়ে থাকি। আমার তালিকাটির সমান দৈর্ঘ্য রয়েছে n, আমি অঙ্কগুলি মূল্যায়ন করতে পারি।

এখন যেহেতু আমি নিজে ভেক্টর তৈরি করি, আমি যদি যোগফল = 0 বা না পৌঁছাতে পারি তার উপর নির্ভর করে আমি সেগুলি ফিল্টার করতে পারি। যেমন যদি আমার ভেক্টর Aহয় (1, 1, 1, 0, 0)এবং আমার ভেক্টরটি Bদেখে মনে হয় (1, 1, ?, ?, ?), আমি জানি যে আমি ?মানগুলি পূরণ করতে পারি না , তাই A*B = 0। সুতরাং আমি Bফর্মের সমস্ত 6 ভেক্টর পুনরাবৃত্তি করতে হবে না (1, 1, ?, ?, ?)

আমরা এটির উন্নতি করতে পারি, যদি আমরা 1 এর মানগুলিকে অগ্রাহ্য করি তবে প্রশ্নে উল্লিখিত হিসাবে মানগুলির জন্য i = 1ক্রম A081671 রয়েছে । সেগুলি গণনা করার অনেকগুলি উপায় রয়েছে। আমি সহজ পুনরাবৃত্তি নির্বাচন করুন: a(n) = (4*(2*n-1)*a(n-1) - 12*(n-1)*a(n-2)) / n। যেহেতু আমরা i = 1মূলত কোনও সময় গণনা করতে পারি না , আমরা এর জন্য আরও ভেক্টর ফিল্টার করতে পারি B। যেমন A = (0, 1, 0, 1, 1)এবং B = (1, -1, ?, ?, ?)। আমরা ভেক্টরগুলিকে অগ্রাহ্য করতে পারি, যেখানে প্রথম ? = 1, কারণ এই A * cycled(B) > 0সমস্ত ভেক্টরগুলির জন্য। আমি আপনাকে অনুসরণ করতে পারেন আশা করি। এটি সম্ভবত সেরা উদাহরণ নয়।

এটি দিয়ে আমি n = 156 মিনিটে গণনা করতে পারি ।

সম্পাদনা 4:

দ্রুত Kuroi Neko এর মহান ধারণা, যা, বলছেন যে বাস্তবায়িত Bএবং -Bএকই ফলাফল উৎপন্ন হয়। স্পিডআপ এক্স 2। বাস্তবায়ন শুধুমাত্র দ্রুত হ্যাক, যদিও। n = 153 মিনিটে

কোড:

সম্পূর্ণ কোডের জন্য গিথুব দেখুন । নিম্নলিখিত কোডটি কেবল প্রধান বৈশিষ্ট্যগুলির উপস্থাপনা। আমি আমদানি, মাল্টিকোর প্রোগ্রামিং, ফলাফল মুদ্রণ, ...

count = [0] * n
count[0] = oeis_A081671(n)

#generating all important vector A
visited = set(); todo = dict()
for A in product((0, 1), repeat=n):
    if A not in visited:
        # generate all vectors, which have the same probability
        # mirrored and cycled vectors
        same_probability_set = set()
        for i in range(n):
            tmp = [A[(i+j) % n] for j in range(n)]
            same_probability_set.add(tuple(tmp))
            same_probability_set.add(tuple(tmp[::-1]))
        visited.update(same_probability_set)
        todo[A] = len(same_probability_set)

# for each vector A, create all possible vectors B
stack = []
for A, cycled_count in dict_A.iteritems():
    ones = [sum(A[i:]) for i in range(n)] + [0]
    # + [0], so that later ones[n] doesn't throw a exception
    stack.append(([0] * n, 0, 0, 0, False))

    while stack:
        B, index, sum1, sum2, used_negative = stack.pop()
        if index < n:
            # fill vector B[index] in all possible ways,
            # so that it's still possible to reach 0.
            if used_negative:
                for v in (-1, 0, 1):
                    sum1_new = sum1 + v * A[index]
                    sum2_new = sum2 + v * A[index - 1 if index else n - 1]
                    if abs(sum1_new) <= ones[index+1]:
                        if abs(sum2_new) <= ones[index] - A[n-1]:
                            C = B[:]
                            C[index] = v
                            stack.append((C, index + 1, sum1_new, sum2_new, True))
            else:
                for v in (0, 1):
                    sum1_new = sum1 + v * A[index]
                    sum2_new = sum2 + v * A[index - 1 if index else n - 1]
                    if abs(sum1_new) <= ones[index+1]:
                        if abs(sum2_new) <= ones[index] - A[n-1]:
                            C = B[:]
                            C[index] = v
                            stack.append((C, index + 1, sum1_new, sum2_new, v == 1))
        else:
            # B is complete, calculate the sums
            count[1] += cycled_count  # we know that the sum = 0 for i = 1
            for i in range(2, n):
                sum_prod = 0
                for j in range(n-i):
                    sum_prod += A[j] * B[i+j]
                for j in range(i):
                    sum_prod += A[n-i+j] * B[j]
                if sum_prod:
                    break
                else:
                    if used_negative:
                        count[i] += 2*cycled_count
                    else:
                        count[i] += cycled_count

ব্যবহার:

আপনাকে পাইপি ইনস্টল করতে হবে (পাইথন 2 এর জন্য !!!)। সমান্তরাল পাইথন মডিউল পাইথন 3. জন্য বৈশিষ্ট্যসমূহ নিয়ে আসা হয় না তারপর আপনি সমান্তরাল পাইথন মডিউল ইনস্টল করতে হবে pp-1.6.4.zip । এটি cdফোল্ডারে প্রবেশ করুন এবং কল করুন pypy setup.py install

তারপরে আপনি আমার প্রোগ্রামটি সাথে কল করতে পারেন

pypy you-do-the-math.py 15

এটি স্বয়ংক্রিয়ভাবে সিপু'র সংখ্যা নির্ধারণ করবে। প্রোগ্রাম শেষ করার পরে কিছু ত্রুটি বার্তা থাকতে পারে, কেবল তাদের এড়িয়ে যান। n = 16আপনার মেশিনে সম্ভব হওয়া উচিত।

আউটপুট:

Calculation for n = 15 took 2:50 minutes

 1  83940771168 / 470184984576  17.85%
 2  17379109692 / 470184984576   3.70%
 3   3805906050 / 470184984576   0.81%
 4    887959110 / 470184984576   0.19%
 5    223260870 / 470184984576   0.05%
 6     67664580 / 470184984576   0.01%
 7     30019950 / 470184984576   0.01%
 8     20720730 / 470184984576   0.00%
 9     18352740 / 470184984576   0.00%
10     17730480 / 470184984576   0.00%
11     17566920 / 470184984576   0.00%
12     17521470 / 470184984576   0.00%
13     17510280 / 470184984576   0.00%
14     17507100 / 470184984576   0.00%
15     17506680 / 470184984576   0.00%

নোট এবং ধারণা:

  • আমার কাছে একটি আই 7-4600 মি প্রসেসর রয়েছে যার সাথে 2 টি কোর এবং 4 টি থ্রেড রয়েছে। আমি 2 বা 4 টি থ্রেড ব্যবহার করি না তবে কিছু যায় আসে না। সিপিইউ-ব্যবহার 2 টি থ্রেড সহ 50% এবং 4 টি থ্রেড সহ 100%, তবে এটি এখনও একই পরিমাণে সময় নেয়। কেন জানি না। আমি পরীক্ষা করে দেখেছি যে প্রতিটি থ্রেডের কেবলমাত্র অর্ধ পরিমাণ তথ্য থাকে, যখন 4 টি থ্রেড থাকে, ফলাফলগুলি পরীক্ষা করে, ...
  • আমি প্রচুর তালিকাগুলি ব্যবহার করি। পাইথন সংরক্ষণে বেশ দক্ষ নয়, আমাকে প্রচুর তালিকাগুলি অনুলিপি করতে হবে, ... সুতরাং আমি পরিবর্তে একটি পূর্ণসংখ্যা ব্যবহার করার কথা ভেবেছিলাম। আমি ভেক্টর এ-তে বিটস 00 (0 এর জন্য) এবং 11 (1 এর জন্য), এবং বিটস 10 (-1 এর জন্য), 00 (0) এবং 01 (1 এর জন্য) ভেক্টর বিতে ব্যবহার করতে পারি A এবং B এর, আমাকে কেবল A & B01 এবং 10 ব্লক গণনা করতে হবে এবং তা গণনা করতে হবে। সেক্টরটি ভেক্টর স্থানান্তর এবং মাস্কগুলি ব্যবহার করে করা যেতে পারে, ... আমি আসলে এগুলি বাস্তবায়ন করেছি, আপনি এটি গিথুব সম্পর্কে আমার কিছু পুরানো প্রতিশ্রুতিতে খুঁজে পেতে পারেন। তবে দেখা গেল তালিকার তুলনায় ধীর হতে হবে। আমার ধারণা, পাইপি সত্যিই তালিকার ক্রিয়াকলাপকে অনুকূল করে তোলে।

আমার পিসিতে এন = 12 রান 7:25 লাগে যখন আমার সি ++ জাঙ্কের টুকরোটি প্রায় 1:23 লাগে, যা এটি প্রায় 5 গুণ বেশি দ্রুত করে তোলে। মাত্র দুটি সত্য কোরের সাথে, আমার সিপিইউ মনো-থ্রেডযুক্ত অ্যাপ্লিকেশনটির তুলনায় 2.5 ফ্যাক্টরের মতো কিছু অর্জন করবে, সুতরাং সত্য 8 টি কোর সিপিইউ 3 গুণ দ্রুত চালানো উচিত, এবং এটি মৌলিক মনো-কোর গতির উন্নতির সাথে গণনা করছে না not আমার বার্ধক্য i3-2100। তাত্পর্যপূর্ণভাবে বর্ধমান গণনার সময়কে মোকাবেলা করার জন্য এই সমস্ত সি ++ হুপের মধ্য দিয়ে যাওয়া চেষ্টা করা সার্থক, যদিও তা বিতর্কযোগ্য।


মাল্টিথ্রেডিং সম্পর্কে, আপনি প্রতিটি থ্রেড লক করে আপনার 2 + 2 কোরের আরও কিছুটা বার করতে পারবেন। এক্স 2 লাভটি সিডিয়ুলে প্রতিবার ম্যাচস্টিকটি সরানোর সময়সূচীটি আপনার থ্রেডগুলির চারপাশে স্থানান্তরিত করার কারণে ঘটে। মূল লকিংয়ের সাথে, আপনি সম্ভবত পরিবর্তে একটি x2.5 লাভ পাবেন। যদিও পাইথন প্রসেসরের অ্যাফিনিটি সেট করতে দেয় কিনা ধারণা নেই।

ধন্যবাদ, আমি এটি খতিয়ে দেখব। তবে আমি মাল্টিথ্রেডিংয়ের ক্ষেত্রে বেশ নবাগত।
জাকুব

nbviewer.ipython.org/gist/minrk/5500077 এর সমান্তরালতার জন্য আলাদা একটি সরঞ্জাম ব্যবহার করেও এর কিছু উল্লেখ রয়েছে।

5

উলি বুলি - সি ++ - উপায় খুব ধীর

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

#include <cstdlib>
#include <cmath>
#include <vector>
#include <bitset>
#include <future>
#include <iostream>
#include <iomanip>

using namespace std;

/*
6^^n events will be generated, so the absolute max
that can be counted by a b bits integer is
E(b*log(2)/log(6)), i.e. n=24 for a 64 bits counter

To enumerate 3 possible values of a size n vector we need
E(n*log(3)/log(2))+1 bits, i.e. 39 bits
*/
typedef unsigned long long Counter; // counts up to 6^^24

typedef unsigned long long Benumerator; // 39 bits
typedef unsigned long      Aenumerator; // 24 bits

#define log2_over_log6 0.3869

#define A_LENGTH ((size_t)(8*sizeof(Counter)*log2_over_log6))
#define B_LENGTH (2*A_LENGTH)

typedef bitset<B_LENGTH> vectorB;

typedef vector<Counter> OccurenceCounters;

// -----------------------------------------------------------------
// multithreading junk for CPUs detection and allocation
// -----------------------------------------------------------------
int number_of_CPUs(void)
{
    int res = thread::hardware_concurrency();
    return res == 0 ? 8 : res;
}

#ifdef __linux__
#include <sched.h>
void lock_on_CPU(int cpu)
{
    cpu_set_t mask;
    CPU_ZERO(&mask);
    CPU_SET(cpu, &mask);
    sched_setaffinity(0, sizeof(mask), &mask);
}
#elif defined (_WIN32)
#include <Windows.h>
#define lock_on_CPU(cpu) SetThreadAffinityMask(GetCurrentThread(), 1 << cpu)
#else
// #warning is not really standard, so this might still cause compiler errors on some platforms. Sorry about that.
#warning "Thread processor affinity settings not supported. Performances might be improved by providing a suitable alternative for your platform"
#define lock_on_CPU(cpu)
#endif

// -----------------------------------------------------------------
// B values generator
// -----------------------------------------------------------------
struct Bvalue {
    vectorB p1;
    vectorB m1;
};

struct Bgenerator {
    int n;                 // A length
    Aenumerator stop;      // computation limit
    Aenumerator zeroes;    // current zeroes pattern
    Aenumerator plusminus; // current +1/-1 pattern
    Aenumerator pm_limit;  // upper bound of +1/-1 pattern

    Bgenerator(int n, Aenumerator start=0, Aenumerator stop=0) : n(n), stop(stop)
    {
        // initialize generator so that first call to next() will generate first value
        zeroes    = start - 1;
        plusminus = -1;
        pm_limit  = 0;
    }

    // compute current B value
    Bvalue value(void)
    {
        Bvalue res;
        Aenumerator pm = plusminus;
        Aenumerator position = 1;
        int i_pm = 0;
        for (int i = 0; i != n; i++)
        {
            if (zeroes & position)
            {
                if (i_pm == 0)  res.p1 |= position; // first non-zero value fixed to +1
                else         
                {
                    if (pm & 1) res.m1 |= position; // next non-zero values
                    else        res.p1 |= position;
                    pm >>= 1;
                }
                i_pm++;
            }
            position <<= 1;
        }
        res.p1 |= (res.p1 << n); // concatenate 2 Bpre instances
        res.m1 |= (res.m1 << n);
        return res;
    }

    // next value
    bool next(void)
    {
        if (++plusminus == pm_limit)
        {
            if (++zeroes == stop) return false;
            plusminus = 0;
            pm_limit = (1 << vectorB(zeroes).count()) >> 1;
        }
        return true;
    }

    // calibration: produces ranges that will yield the approximate same number of B values
    vector<Aenumerator> calibrate(int segments)
    {
        // setup generator for the whole B range
        zeroes = 0;
        stop = 1 << n;
        plusminus = -1;
        pm_limit = 0;

        // divide range into (nearly) equal chunks
        Aenumerator chunk_size = ((Aenumerator)pow (3,n)-1) / 2 / segments;

        // generate bounds for zeroes values
        vector<Aenumerator> res(segments + 1);
        int bound = 0;
        res[bound] = 1;
        Aenumerator count = 0;
        while (next()) if (++count % chunk_size == 0) res[++bound] = zeroes;
        res[bound] = stop;
        return res;
    }
};

// -----------------------------------------------------------------
// equiprobable A values merging
// -----------------------------------------------------------------
static char A_weight[1 << A_LENGTH];
struct Agroup {
    vectorB value;
    int     count;
    Agroup(Aenumerator a = 0, int length = 0) : value(a), count(length) {}
};
static vector<Agroup> A_groups;

Aenumerator reverse(Aenumerator n) // this works on N-1 bits for a N bits word
{
    Aenumerator res = 0;
    if (n != 0) // must have at least one bit set for the rest to work
    {
        // construct left-padded reverse value
        for (int i = 0; i != 8 * sizeof(n)-1; i++)
        {
            res |= (n & 1);
            res <<= 1;
            n >>= 1;
        }

        // shift right to elimitate trailing zeroes
        while (!(res & 1)) res >>= 1;
    }
    return res;
}

void generate_A_groups(int n)
{
    static bitset<1 << A_LENGTH> lookup(0);
    Aenumerator limit_A = (Aenumerator)pow(2, n);
    Aenumerator overflow = 1 << n;
    for (char & w : A_weight) w = 0;

    // gather rotation cycles
    for (Aenumerator a = 0; a != limit_A; a++)
    {
        Aenumerator rotated = a;
        int cycle_length = 0;
        for (int i = 0; i != n; i++)
        {
            // check for new cycles
            if (!lookup[rotated])
            {
                cycle_length++;
                lookup[rotated] = 1;
            }

            // rotate current value
            rotated <<= 1;
            if (rotated & overflow) rotated |= 1;
            rotated &= (overflow - 1);
        }

        // store new cycle
        if (cycle_length > 0) A_weight[a] = cycle_length;
    }

    // merge symetric groups
    for (Aenumerator a = 0; a != limit_A; a++)
    {
        // skip already grouped values
        if (A_weight[a] == 0) continue;

        // regroup a symetric pair
        Aenumerator r = reverse(a);
        if (r != a)
        {
            A_weight[a] += A_weight[r];
            A_weight[r] = 0;
        }  
    }

    // generate groups
    for (Aenumerator a = 0; a != limit_A; a++)
    {
        if (A_weight[a] != 0) A_groups.push_back(Agroup(a, A_weight[a]));
    }
}

// -----------------------------------------------------------------
// worker thread
// -----------------------------------------------------------------
OccurenceCounters solve(int n, int index, Aenumerator Bstart, Aenumerator Bstop)
{
    OccurenceCounters consecutive_zero_Z(n, 0);  // counts occurences of the first i terms of Z being 0

    // lock on assigned CPU
    lock_on_CPU(index);

    // enumerate B vectors
    Bgenerator Bgen(n, Bstart, Bstop);
    while (Bgen.next())
    {
        // get next B value
        Bvalue B = Bgen.value();

        // enumerate A vector groups
        for (const auto & group : A_groups)
        {
            // count consecutive occurences of inner product equal to zero
            vectorB sliding_A(group.value);
            for (int i = 0; i != n; i++)
            {
                if ((sliding_A & B.p1).count() != (sliding_A & B.m1).count()) break;
                consecutive_zero_Z[i] += group.count;
                sliding_A <<= 1;
            }
        }
    }
    return consecutive_zero_Z;
}

// -----------------------------------------------------------------
// main
// -----------------------------------------------------------------
#define die(msg) { cout << msg << endl; exit (-1); }

int main(int argc, char * argv[])
{
    int n = argc == 2 ? atoi(argv[1]) : 16; // arbitray value for debugging
    if (n < 1 || n > 24) die("vectors of lenght between 1 and 24 is all I can (try to) compute, guv");

    auto begin = time(NULL);

    // one worker thread per CPU
    int num_workers = number_of_CPUs();

    // regroup equiprobable A values
    generate_A_groups(n);

    // compute B generation ranges for proper load balancing
    vector<Aenumerator> ranges = Bgenerator(n).calibrate(num_workers);

    // set workers to work
    vector<future<OccurenceCounters>> workers(num_workers);
    for (int i = 0; i != num_workers; i++)
    {
        workers[i] = async(
            launch::async, // without this parameter, C++ will decide whether execution shall be sequential or asynchronous (isn't C++ fun?).
            solve, n, i, ranges[i], ranges[i+1]); 
    }

    // collect results
    OccurenceCounters result(n + 1, 0);
    for (auto& worker : workers)
    {
        OccurenceCounters partial = worker.get();
        for (size_t i = 0; i != partial.size(); i++) result[i] += partial[i]*2; // each result counts for a symetric B pair
    }
    for (Counter & res : result) res += (Counter)1 << n; // add null B vector contribution
    result[n] = result[n - 1];                           // the last two probabilities are equal by construction

    auto duration = time(NULL) - begin;

    // output
    cout << "done in " << duration / 60 << ":" << setw(2) << setfill('0') << duration % 60 << setfill(' ')
        << " by " << num_workers << " worker thread" << ((num_workers > 1) ? "s" : "") << endl;
    Counter events = (Counter)pow(6, n);
    int width = (int)log10(events) + 2;
    cout.precision(5);
    for (int i = 0; i <= n; i++) cout << setw(2) << i << setw(width) << result[i] << " / " << events << " " << fixed << (float)result[i] / events << endl;

    return 0;
}

এক্সিকিউটেবল বিল্ডিং

এটি একটি স্বতন্ত্র সি ++ 11 উত্স যা সতর্কতা ছাড়াই সংকলন করে এবং সহজেই চালিত হয়:

  • Win7 এবং MSVC2013
  • Win7 এবং MinGW - g ++ 4.7
  • উবুন্টু এবং জি ++ 4.8 (2 সিপিইউ বরাদ্দযুক্ত ভার্চুয়ালবক্স ভিএম এ)

যদি আপনি জি ++ দিয়ে সংকলন করেন তবে ব্যবহার করুন: g ++ -O3 -pthread -std = c ++ 11
ভুলে যাওয়া -pthreadএকটি দুর্দান্ত এবং বন্ধুত্বপূর্ণ কোর ডাম্প তৈরি করবে।

নিখুঁতকরণ

  1. শেষ জেড শব্দটি প্রথমটির সমান (উভয় ক্ষেত্রে বিপ্রে এক্স এ), সুতরাং সর্বশেষ দুটি ফলাফল সর্বদা সমান, যা সর্বশেষ জেড মান গণনার ক্ষেত্রে ব্যয় করে।
    লাভটি উপেক্ষণীয়, তবে কোডিংয়ের জন্য কোনও দাম নেই যাতে আপনি এটি ব্যবহার করতে পারেন।

  2. জাকুব আবিষ্কার হিসাবে, প্রদত্ত একটি ভেক্টরের সমস্ত চক্রীয় মান একই সম্ভাবনা তৈরি করে।
    আপনি এ এর ​​একক উদাহরণ দিয়ে এগুলি গণনা করতে পারেন এবং এর সম্ভাব্য ঘূর্ণনের সংখ্যা দ্বারা ফলাফলকে গুণ করতে পারেন। ঘূর্ণন গোষ্ঠীগুলি সহজেই একটি উপেক্ষিত পরিমাণে প্রাক-গণনা করা যায়, সুতরাং এটি বিশাল নেট গতির লাভ।
    যেহেতু একটি এন দৈর্ঘ্যের ভেক্টরের ক্রম সংখ্যা ন -1, তাই জটিলতা ও (6 এন ) থেকে ও (6 এন / (এন -1)) এ নেমে আসে , মূলত একই গণনার সময়টির জন্য আরও এক ধাপ এগিয়ে যায়।

  3. এটি প্রদর্শিত হয় সিমেট্রিক প্যাটার্নগুলির জোড়াও একই সম্ভাবনা তৈরি করে। উদাহরণস্বরূপ, ১০০১০১ এবং ১০০০০০১।
    আমার কাছে এর গাণিতিক প্রমাণ নেই, তবে স্বজ্ঞাতভাবে যখন সমস্ত সম্ভাব্য বি প্যাটার্ন উপস্থাপন করা হয়, তখন প্রতিটি সিমেট্রিক একই মান একই বৈশ্বিক ফলাফলের জন্য সংশ্লিষ্ট সিমেট্রিক বি মানের সাথে সংশ্লেষিত হবে।
    এটি একটি গ্রুপ সংখ্যার আনুমানিক 30% হ্রাসের জন্য আরও কিছু এ ভেক্টরগুলিকে পুনরায় গোষ্ঠী তৈরি করতে দেয়।

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

  5. ভেক্টর বি এবং-বি (বি সমস্ত উপাদানগুলির সাথে -1 দ্বারা গুণিত) একই সম্ভাবনা তৈরি করে।
    (উদাহরণস্বরূপ [1, 0, -1, 1] এবং [-1, 0, 1, -1])।
    নাল ভেক্টর ব্যতীত (সমস্ত উপাদান 0 এর সমান), বি এবং-বি স্বতন্ত্র ভেক্টরগুলির একটি জুড়ি তৈরি করে ।
    এটি প্রতিটি জোড়ার একটি মাত্র বিবেচনা করে এবং তার অবদানকে 2 দিয়ে বহুগুণে বি মানগুলির সংখ্যা অর্ধেকে কাটতে দেয়, প্রতিটি সম্ভাবনার ক্ষেত্রে নাল বিয়ের জ্ঞাত বৈশ্বিক অবদানকে একবার যুক্ত করে।

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

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

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

সামঞ্জস্যযোগ্য অংশগুলিতে পুনরায় গ্রুপিংয়ের জন্য একটি মানগুলি ভারি ফিল্টার করা হয়।
এটি প্রাক-কম্পিউটিং পর্যায়ে করা হয় যা ব্রুট-ফোর্স সমস্ত সম্ভাব্য মানগুলি পরীক্ষা করে।
এই অংশে একটি উপেক্ষণযোগ্য ও (2 এন ) কার্যকর করার সময় রয়েছে এবং এটি অনুকূলিতকরণের প্রয়োজন নেই (কোডটি ইতিমধ্যে যেমনটি অপঠনযোগ্য তেমন পর্যাপ্ত রয়েছে!)।

অভ্যন্তরীণ পণ্যটি মূল্যায়ন করতে (যা কেবল শূন্যের বিপরীতে পরীক্ষা করা প্রয়োজন), বি -1 এবং 1 উপাদান বাইনারি ভেক্টরগুলিতে পুনরায় গ্রুপ করা হয়।
অভ্যন্তরীণ পণ্যটি শূন্য নয় তবে (এবং কেবলমাত্র যদি) বি-মানগুলির সাথে বি মানগুলির মধ্যে সমান সংখ্যক +1 এবং -1 হয়।
এটি সাধারণ মাস্কিং এবং বিট কাউন্ট অপারেশনগুলির সাথে গণনা করা যেতে পারে, এটির সাহায্যে std::bitsetকুৎসিত স্বতন্ত্র নির্দেশাবলী অবলম্বন না করে যুক্তিসঙ্গতভাবে দক্ষ বিট কাউন্ট কোড তৈরি করবে।

কাজটি বাধ্যতামূলক সিপিইউ অ্যাফিনিটি (প্রতিটি সামান্য সাহায্য করে, বা তাই তারা বলে) সহ কোরগুলির মধ্যে সমানভাবে বিভক্ত।

উদাহরণ ফলাফল

C:\Dev\PHP\_StackOverflow\C++\VectorCrunch>release\VectorCrunch.exe 16
done in 8:19 by 4 worker threads
 0  487610895942 / 2821109907456 0.17284
 1   97652126058 / 2821109907456 0.03461
 2   20659337010 / 2821109907456 0.00732
 3    4631534490 / 2821109907456 0.00164
 4    1099762394 / 2821109907456 0.00039
 5     302001914 / 2821109907456 0.00011
 6     115084858 / 2821109907456 0.00004
 7      70235786 / 2821109907456 0.00002
 8      59121706 / 2821109907456 0.00002
 9      56384426 / 2821109907456 0.00002
10      55686922 / 2821109907456 0.00002
11      55508202 / 2821109907456 0.00002
12      55461994 / 2821109907456 0.00002
13      55451146 / 2821109907456 0.00002
14      55449098 / 2821109907456 0.00002
15      55449002 / 2821109907456 0.00002
16      55449002 / 2821109907456 0.00002

ক্রিয়াকাণ্ড

মাল্টিথ্রেডিং এটিতে নিখুঁতভাবে কাজ করা উচিত, যদিও কেবল "সত্য" কোর সম্পূর্ণরূপে গণনার গতিতে অবদান রাখবে। আমার সিপিইউতে 4 টি সিপিইউয়ের জন্য কেবল 2 টি কোর রয়েছে এবং একটি একক থ্রেডযুক্ত সংস্করণে লাভ "কেবল" প্রায় 3.5।

কম্পাইলার

মাল্টিথ্রেডিংয়ের সাথে প্রাথমিক সমস্যা আমাকে বিশ্বাস করতে পরিচালিত করেছিল যে জিএনইউ সংকলকরা মাইক্রোসফ্টের চেয়ে খারাপ পারফর্ম করছে।

আরও নিখুঁত পরীক্ষার পরে, এটি আবার +1 দিন আবার জিতেছে, আনুমানিক 30% দ্রুত কোড তৈরি করে (একই অনুপাতটি আমি অন্য দুটি গণনা-ভারী প্রকল্পে লক্ষ্য করেছি)।

উল্লেখযোগ্যভাবে, std::bitsetলাইব্রেরিটি g ++ 4.8 দ্বারা ডেডিকেটেড বিট গণনা নির্দেশাবলীর সাথে প্রয়োগ করা হয়েছে, যখন এমএসভিসি 2013 কেবলমাত্র প্রচলিত বিট শিফ্টের লুপ ব্যবহার করে।

যেমনটি আশা করা যায়, 32 বা 64 বিটের মধ্যে সংকলন করা কোনও তাত্পর্যপূর্ণ নয়।

আরও পরিমার্জন

আমি হ্রাসের সমস্ত ক্রিয়াকলাপের পরে কয়েকটি সংখ্যক একই সম্ভাব্যতা তৈরি করে লক্ষ্য করেছি, তবে আমি এমন একটি প্যাটার্ন সনাক্ত করতে পারিনি যা তাদের পুনরায় গোষ্ঠীভুক্ত করতে দেয়।

এন = ১১ এর জন্য আমি যে জুটিগুলি লক্ষ্য করেছি তা এখানে রয়েছে:

  10001011 and 10001101
 100101011 and 100110101
 100101111 and 100111101
 100110111 and 100111011
 101001011 and 101001101
 101011011 and 101101011
 101100111 and 110100111
1010110111 and 1010111011
1011011111 and 1011111011
1011101111 and 1011110111

আমি মনে করি সর্বশেষ দুটি সম্ভাবনা সবসময় একই হওয়া উচিত। এটি হ'ল কারণ n + 1 তম অভ্যন্তরীণ পণ্যটি আসলে প্রথমটির মতো।

আমি যা বোঝাতে চেয়েছি তা হল প্রথম এন অভ্যন্তরীণ পণ্যগুলি শূন্য এবং যদি প্রথম এন + 1 হয় তবেই। ইতিমধ্যে অভ্যন্তরীণ পণ্যটি কোনও নতুন তথ্য সরবরাহ করে না কারণ আপনি ইতিমধ্যে এটি ইতিমধ্যে করেছেন। সুতরাং এন শূন্য পণ্য দেয় এমন স্ট্রিংয়ের সংখ্যা হ'ল n + 1 শূন্য পণ্য দেয় এমন সংখ্যার মতো।

আগ্রহের বাইরে, আপনি পরিবর্তে ঠিক কী গণনা করছিলেন?

আপডেটের জন্য ধন্যবাদ তবে আমি "0 2160009216 2176782336" লাইনটি বুঝতে পারি না। এক্ষেত্রে আপনি ঠিক কী গণনা করছেন? প্রথম অভ্যন্তরীণ পণ্যটি শূন্য হওয়ার সম্ভাবনা তার চেয়ে অনেক ছোট।

এটি কীভাবে সংকলন করতে এবং চালাতে হয় সে সম্পর্কে আপনি কিছু পরামর্শ দিতে পারেন? আমি g ++ -Wall -std = c ++ 11 kuroineko.cpp -o kuroineko এবং ./koreoineko 12 চেষ্টা করেছি তবে এটি দেয়terminate called after throwing an instance of 'std::system_error' what(): Unknown error -1 Aborted (core dumped)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.