সম্ভাব্যতমতম সময়ের মধ্যে এই সংখ্যা ধাঁধার সমস্ত সমাধান সন্ধান করুন


16

ইতিহাস

আমার সংস্থা কোম্পানির মধ্যে প্রত্যেককে একটি সাপ্তাহিক নিউজলেটার পাঠায়। এই নিউজলেটারগুলিতে অন্তর্ভুক্ত একটি ধাঁধা, সাথে কোম্পানির মধ্যে যারা চিৎকার করেছে তাদের সাথে সর্বশেষ ইমেল করা / সর্বশেষ সপ্তাহের ধাঁধাটির সমাধান সরবরাহ করেছিল। এই ধাঁধাগুলির বেশিরভাগই একেবারে তুচ্ছ এবং কোনও প্রযুক্তি সংস্থার পক্ষে সত্যই নিখুঁত, তবে কয়েক মাস আগে একটি ছিল, যা আমার দৃষ্টি আকর্ষণ করেছিল।

আসল ধাঁধা:

নীচে আকার দেওয়া:

ধাঁধা ইমেজ

আপনার 1 থেকে 16 পর্যন্ত প্রাকৃতিক সংখ্যা রয়েছে them এগুলি সমস্তকে এই আকারে ফিট করুন, যাতে সমস্ত সংলগ্ন সারি এবং একযোগে কলামগুলি 29 এর সমষ্টি হতে পারে।

উদাহরণস্বরূপ, এই ধাঁধার ক্ষেত্রে এরকম একটি সমাধান (যা আমি নিউজলেটারে জমা দেওয়া "ক্যানোনিকাল" সমাধান) ছিল:

সলভ ধাঁধা ইমেজ

যাইহোক, এটি সমাধান করার সময়, আমি কিছু বরং আকর্ষণীয় তথ্য পেয়েছি:

  • এটির চেয়ে উল্লেখযোগ্যভাবে আরও কয়েকটি সমাধান রয়েছে; আসলে 9,368 টি সমাধান রয়েছে।
  • আপনি যদি নিয়মটি প্রসারিত করেন তবে কেবল সারি এবং কলামগুলি একে অপরের সমান হতে হবে, অগত্যা 29 নয়, আপনি 33,608 সমাধান পান:
    • 27 এর যোগফলের জন্য 4,440 টি সমাধান।
    • 28 এর যোগফলের জন্য 7,400 টি সমাধান।
    • 29 এর যোগফলের জন্য 9,368 টি সমাধান।
    • 30 এর যোগফলের জন্য 6,096 সমাধান।
    • 31 এর যোগফলের জন্য 5,104 সমাধান।
    • 32 টির যোগফলের জন্য 1,200 সমাধান।

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

মূল পরিসংখ্যান

সমস্যাটি সমাধান করার জন্য আমি প্রথম প্রথম প্রোগ্রামটি এলোমেলো সমাধানগুলি বারবার পরীক্ষা করে দেখেছি এবং যখন সমাধান পেয়েছি তখন থামে stopped আপনি যদি এই সমস্যাটির উপর গাণিতিক বিশ্লেষণ করেন তবে আপনি সম্ভবত ইতিমধ্যে জানেন যে এটি কাজ করা উচিত হয়নি; তবে কোনওভাবে আমি ভাগ্যবান হয়ে উঠলাম, এবং একক সমাধান (আমি উপরে যে পোস্ট করেছি) তা আবিষ্কার করতে প্রোগ্রামটি কেবল এক মিনিট সময় নিয়েছিল। প্রোগ্রামটির পুনরাবৃত্তিগুলি প্রায়শই 10 বা 20 মিনিটের বেশি সময় নেয়, সুতরাং স্পষ্টতই এটি সমস্যার কোনও কঠোর সমাধান ছিল না।

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

এই অ্যালগরিদমটি ব্যবহার করে, আমি প্রথম "যথাযথ" সাফল্য পেয়েছি: প্রোগ্রামটি প্রায় 5 মিনিটের মধ্যে সমস্ত 33,608 সমাধান তৈরি করতে এবং থুতু দিতে পারে।

আমার ম্যানেজারের একটি ভিন্ন পদ্ধতি ছিল: একমাত্র সম্ভাব্য সমাধানগুলির পরিমাণ 27, 28, 29, 30, 31 বা 32 এর পরিমাণ ছিল বলে আমার কাজের ভিত্তিতে জেনে তিনি একাধিক থ্রেডযুক্ত সমাধান লিখেছিলেন যা কেবলমাত্র সেই নির্দিষ্ট মানের জন্যই সম্ভাব্য পরিমাণগুলি পরীক্ষা করে checked তিনি তার প্রোগ্রামটি মাত্র 2 মিনিটে চালাতে সক্ষম হন। সুতরাং আমি আবার পুনরাবৃত্তি; আমি সমস্ত সম্ভাব্য 3/4 ডিজিটের অঙ্কগুলি (প্রোগ্রামের শুরুতে; এটি মোট রানটাইমের মধ্যে গণনা করা) হ্যাশ করেছি এবং এর চেয়ে পূর্বের সম্পন্ন সারির ভিত্তিতে অবশিষ্ট মানটি সন্ধান করার জন্য একটি সারির "আংশিক যোগফল" ব্যবহার করেছি সমস্ত অবশিষ্ট মান পরীক্ষা করে, এবং সময়টি 72 সেকেন্ডে নামিয়ে আনে। তারপরে কিছু মাল্টি-থ্রেডিং যুক্তি দিয়ে আমি এটিকে 40 সেকেন্ডে নামিয়ে আনলাম। আমার ম্যানেজার প্রোগ্রামটি বাড়িতে নিয়ে গিয়েছিল, প্রোগ্রামটি কীভাবে চালিত হয়েছিল সে সম্পর্কে কিছু অপ্টিমাইজেশন করেছে এবং তার সেকেন্ডে 12 সেকেন্ড নেমে গেছে। আমি সারি এবং কলামগুলির মূল্যায়নটি পুনরায় সাজিয়েছি,

এক মাস পরে আমাদের উভয়ই আমাদের প্রোগ্রামগুলি পেয়েছিলাম আমার পরিচালকের জন্য 0.15 সেকেন্ড এবং আমার জন্য 0.33 সেকেন্ড got আমি দাবি করে শেষ করেছি যে আমার প্রোগ্রামটি যদিও দ্রুত ছিল, যেহেতু আমার পরিচালকের প্রোগ্রামটি এটি খুঁজে পেয়েছিল সমস্ত সমাধান পেয়েছিল তখনও সেগুলি কোনও পাঠ্য ফাইলে মুদ্রণ করছিল না। যদি সে তার যুক্তিতে এই যুক্তি যুক্ত করে, তবে এটি প্রায় 0.4-0.5 সেকেন্ডের বেশি সময় নেয়।

আমরা তখন থেকে আমাদের আন্তঃব্যক্তিক চ্যালেঞ্জকে টিকে থাকতে দিয়েছি, তবে অবশ্যই, প্রশ্নটি রয়ে গেছে: পারে এই প্রোগ্রাম দ্রুত তৈরি করা?

আমি আপনাকে বলছি যে চ্যালেঞ্জ এটি।

আপনার চ্যালেঞ্জ

আমরা যে প্যারামিটারগুলির অধীনে কাজ করেছি সেগুলি "29 এর যোগফল" নিয়মটি শিথিল করে "সমস্ত সারি / কলামের সমতুল্য সমান" হতে হবে এবং আমি আপনাকেও এই নিয়মটি সেট করতে যাচ্ছি। তাই চ্যালেঞ্জটি হ'ল: একটি প্রোগ্রাম লিখুন যা খুব কম সময়ে সম্ভব এই ধাঁধার সমস্ত সমাধান খুঁজে পায় (এবং প্রিন্টগুলি!)। আমি জমা দেওয়া সমাধানগুলিতে সিলিং সেট করতে যাচ্ছি: যদি প্রোগ্রামটি তুলনামূলকভাবে শালীন কম্পিউটারে (<8 বছর বয়সী) 10 সেকেন্ডের বেশি সময় নেয়, তবে এটি সম্ভবত গণনা করা খুব ধীর হবে।

এছাড়াও, ধাঁধাটির জন্য আমার কাছে কয়েকটি বোনাস রয়েছে:

  • আপনি কী সমাধানটিকে সাধারণীকরণ করতে পারেন যাতে এটি 16 টি সংখ্যার কোনও সেটের জন্যই কার্যকর হয় int[1,16] ? টাইমিং স্কোরটি মূল প্রম্পট নম্বর সেটের ভিত্তিতে মূল্যায়ন করা হবে, তবে এই কোডপথের মধ্য দিয়ে গেছে passed (-10%)
  • আপনি কী কোডটি এমনভাবে লিখতে পারেন যাতে এটি নিখুঁতভাবে পরিচালনা করে এবং সদৃশ সংখ্যার সাথে সমাধান করে? এটি যতটা সহজ বলে মনে হচ্ছে তত সহজ নয়! "দৃষ্টিগোচরভাবে অভিন্ন" সমাধানগুলি ফলাফল সেটে অনন্য হওয়া উচিত। (-5%)
  • আপনি কি নেতিবাচক সংখ্যাগুলি পরিচালনা করতে পারবেন? (-5%)

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

সমস্ত উদ্দেশ্য এবং উদ্দেশ্যে, "আবর্তন" অনন্য সমাধান হিসাবে বিবেচিত হয়। সুতরাং একটি সমাধান যা কেবলমাত্র একটি পৃথক সমাধানের আবর্তন তার নিজের সমাধান হিসাবে গণ্য হয়।

আমি আমার কম্পিউটারে যে আইডিইগুলি কাজ করছি তা হ'ল জাভা এবং সি ++। আমি অন্যান্য ভাষাগুলির উত্তর গ্রহণ করতে পারি, তবে আপনার কোডটির জন্য আমি একটি সহজ সেটআপ রানটাইম পরিবেশ পেতে পারি তার লিঙ্ক সরবরাহ করতেও পারে।


3
পবিত্র বিড়াল, প্রথম প্রথম প্রশ্ন! ... বোনাস ব্যতীত, যা আমরা বাছাই-নিরুৎসাহ করি (বেশিরভাগ কোড-গল্ফ প্রশ্নে, তাই তাদের এখানে ভাল হওয়া উচিত)
বিড়াল

4
@ কেট আমি মনে করি বোনাসগুলি এখানে অর্থবোধ করে, কারণ যখন আমি নিজের কোডগুলিতে এই সমস্যাগুলি সমাধান করি তখন তারা কোডটি উল্লেখযোগ্য উপায়ে কমিয়ে আনার প্রবণতা পোষণ করে। সুতরাং আমি মনে করি একটি বোনাস অন্তর্ভুক্তি ন্যায্যতা জন্য।
Xirema

2
বিটিডাব্লু, আপনার জায়গায় কি কোনও কাজ চলছে? দেখে মনে হচ্ছে আপনার হাতে সহজেই বস এবং প্রচুর সময় রয়েছে :-)
লেভেল রিভার সেন্ট

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

1
এছাড়াও, 180 ডিগ্রি ঘূর্ণনগুলি কি একই সমাধান বা বিভিন্ন সমাধান হিসাবে বিবেচিত হয়?
স্তর নদী সেন্ট

উত্তর:


7

সি - কাছাকাছি 0.5 সেকেন্ড

এই খুব নিষ্পাপ প্রোগ্রামটি আমার 4 বছরের পুরানো ল্যাপটপে আধ সেকেন্ডে সমস্ত সমাধান দেয়। কোনও মাল্টিথ্রিড, কোনও হ্যাশিং নেই।

উইন্ডোজ 10, ভিজ্যুয়াল স্টুডিও 2010, সিপিইউ কোর আই 7 64 বিট

আইডিয়োনে অনলাইনে চেষ্টা করুন

#include <stdio.h>
#include <time.h>

int inuse[16];
int results[16+15+14];

FILE *fout;

int check(int number)
{
    if (number > 0 && number < 17 && !inuse[number-1])
    {
        return inuse[number-1]=1;
    }
    return 0;
}

void free(int number)
{
    inuse[number-1]=0;
}

void out(int t, int* p)
{
    int i;
    fprintf(fout, "\n%d",t);
    for(i=0; i< 16; i++) fprintf(fout, " %d",*p++);
}

void scan() 
{
    int p[16];
    int t,i;
    for (p[0]=0; p[0]++<16;) if (check(p[0]))
    {
        for (p[1]=0; p[1]++<16;) if (check(p[1]))
        {
            for (p[2]=0; p[2]++<16;) if (check(p[2]))
            {
                t = p[0]+p[1]+p[2]; // top horiz: 0,1,2
                for (p[7]=0; p[7]++<16;) if (check(p[7]))
                {
                    if (check(p[11] = t-p[7]-p[2])) // right vert: 2,7,11
                    {
                        for(p[9]=0; p[9]++<16;) if (check(p[9]))
                        {
                            for (p[10]=0; p[10]++<16;) if (check(p[10]))
                            {
                                if (check(p[12] = t-p[9]-p[10]-p[11])) // right horiz: 9,10,11,12
                                {
                                    for(p[6]=0; p[6]++<16;) if (check(p[6]))
                                    {
                                        if (check(p[15] = t-p[0]-p[6]-p[9])) // middle vert: 0,6,9,15
                                        {
                                            for(p[13]=0; p[13]++<16;) if (check(p[13]))
                                            {
                                                if (check(p[14] = t-p[13]-p[15])) // bottom horiz:  13,14,15
                                                {
                                                    for(p[4]=0; p[4]++<16;) if (check(p[4]))
                                                    {
                                                        if (check(p[8] = t-p[4]-p[13])) // left vert: 4,8,13
                                                        {
                                                            for(p[3]=0; p[3]++<16;) if (check(p[3]))
                                                            {
                                                                if (check(p[5] = t-p[3]-p[4]-p[6])) // left horiz: 3,4,5,6
                                                                {
                                                                    ++results[t];
                                                                    out(t,p);
                                                                    free(p[5]);
                                                                }
                                                                free(p[3]);
                                                            }
                                                            free(p[8]);
                                                        }
                                                        free(p[4]);
                                                    }
                                                    free(p[14]);
                                                }
                                                free(p[13]);
                                            }
                                            free(p[15]);
                                        }
                                        free(p[6]);
                                    }
                                    free(p[12]);
                                }
                                free(p[10]);
                            }
                            free(p[9]);
                        }
                        free(p[11]);
                    }
                    free(p[7]);
                }    
                free(p[2]);
            } 
            free(p[1]);
        }
        free(p[0]);
    }
    for(i=0;i<15+16+14;i++)
    {
        if(results[i]) printf("%d %d\n", i, results[i]);
    }
}

void main()
{
    clock_t begin, end;
    double time_spent;
    begin = clock();

    fout = fopen("c:\\temp\\puzzle29.txt", "w");
    scan();
    fclose(fout);

    end = clock();
    time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
    printf("Time %g sec\n", time_spent);
}

পবিত্র মিষ্টি ilভিল ভ্যাম্পিরিক যীশু, যারা লুপের জন্য বাসা বেঁধেছিলেন। আমি বাজি ধরেছি যা আপনার সংকলকটি সত্যিই খুশি করেছে। এক্সডি
জিরেমা

@ এডসি 65, এফওয়াইআই আপনি int inuse[16];ঠিক দিয়ে প্রতিস্থাপন করতে পারেন int inuse;এবং তারপরে বিটওয়াইজ অপারেটরগুলি ব্যবহার করতে পারেন। এটা তোলে গতি বৃদ্ধি বলে মনে হচ্ছে না যে অনেক, কিন্তু এটা একটু সাহায্য করে।
অ্যান্ড্রু এপস্টেইন

@ অ্যান্ড্রুএপস্টেইন এটি আরও ধীর হয়ে উঠতে পারে - বিটশিফট বনাম ইনডেক্সিং
এডসি 65

@ এডসি 65, বিটশিফ্ট সংস্করণ বনাম আপনার আসল সংস্করণটি পরীক্ষা করতে আমি ডাম্ব্যাঞ্চ ব্যবহারের স্বাধীনতা নিয়েছি । এখানে ফলাফল: ইনডেক্সিং: 0.2253 +/- 5.7590e-05 বিটিশফিং: 0.2093 +/- 6.6595e-05 সুতরাং, আমার মেশিনে প্রায় 16 মিমি স্পিডআপ। আমি যে আদেশটি ব্যবহার করেছি তা হ'ল:dumbbench --precision=.01 -vvv --initial=500 ./solve
অ্যান্ড্রু এপস্টেইন

3

সি ++ - 300 মিলিসেকেন্ড

অনুরোধ অনুযায়ী, আমি এই ধাঁধাটি সমাধান করার জন্য আমার নিজের কোড যুক্ত করেছি। আমার কম্পিউটারে, এটি গড়ে গড়ে ০.০১০ সেকেন্ড (310 মিলি সেকেন্ড) এ দাঁড়িয়ে থাকে তবে ভেরিয়েন্সের উপর নির্ভর করে 287 মিলিসেকেন্ডে চালানো যায়। আমি খুব কমই এটি দেখতে পাচ্ছি যে এটি 350 মিলি সেকেন্ডের ওপরে উঠবে, সাধারণত আমার সিস্টেমটি যদি কোনও আলাদা টাস্ক নিয়ে ডাকা হয়।

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

এছাড়াও, আমার কোড না বেশ সঠিকভাবে সদৃশ হ্যান্ডেল। এটি তাদের ব্যবহার করে সমাধান করতে পারে, তবে এটি সমাধানের সেট থেকে "চাক্ষুষভাবে অভিন্ন" সমাধানগুলি সরিয়ে দেয় না।

#include<iostream>
#include<vector>
#include<random>
#include<functional>
#include<unordered_set>
#include<unordered_map>
#include<array>
#include<thread>
#include<chrono>
#include<fstream>
#include<iomanip>
#include<string>
#include<mutex>
#include<queue>
#include<sstream>
#include<utility>
#include<atomic>
#include<algorithm>

//#define REDUCE_MEMORY_USE

typedef std::pair<int, std::vector<std::pair<int, int>>> sumlist;
typedef std::unordered_map<int, std::vector<std::pair<int, int>>> summap;
typedef std::array<int, 16> solution_space;

class static_solution_state {
public:
    std::array<int, 16> validNumbers;
    summap twosums;
    size_t padding;
    std::string spacing;

    static_solution_state(const std::array<int, 16> & _valid);

    summap gettwovaluesums();
    std::vector<sumlist> gettwovaluesumsvector();
};

static_solution_state::static_solution_state(const std::array<int, 16> & _valid) 
    : validNumbers(_valid) {
    twosums = gettwovaluesums();
    padding = 0;
    for (int i = 0; i < 16; i++) {
        size_t count = std::to_string(validNumbers[i]).size();
        if (padding <= count) padding = count + 1;
    }
    spacing.resize(padding, ' ');
}

class solution_state {
private:
    const static_solution_state * static_state;
public:
    std::array<int, 16> currentSolution;
    std::array<bool, 16> used;
    std::array<int, 7> sums;
    size_t solutions_found;
    size_t permutations_found;
    size_t level;
    std::ostream * log;

    solution_state(const static_solution_state & _sstate);
    solution_state(static_solution_state & _sstate) = delete;
    void setLog(std::ostream & out);
    const int & operator[](size_t index) const;

};

solution_state::solution_state(const static_solution_state & _sstate) {
    static_state = &_sstate;
    sums = { 0 };
    used = { false };
    currentSolution = { -1 };
    solutions_found = 0;
    permutations_found = 0;
    level = 0;
}

void solution_state::setLog(std::ostream & out) {
    log = &out;
}

const int & solution_state::operator[](size_t index) const {
    return static_state->validNumbers[currentSolution[index]];
}

int getincompletetwosum(const static_solution_state & static_state, const solution_state & state);
void permute(const static_solution_state & static_state, solution_state & state, volatile bool & reportProgress, const volatile size_t & total_tests, volatile bool & done);
void setupOutput(std::fstream & out);
void printSolution(const static_solution_state & static_state, const solution_state & state);
constexpr size_t factorial(const size_t iter);

const bool findnext2digits[16]{
    false, false, false,
    true, false,
    false, true, false,
    true, false,
    true, false,
    true, false,
    true, false
};

const int currentsum[16]{
    0, 0, 0,
    1, 1,
    2, 2, 2,
    3, 3,
    4, 4,
    5, 5,
    6, 6
};

const int twosumindexes[7][2]{
    { 0, -1},
    { 2, -1},
    { 5, -1},
    { 5, -1},
    { 0,  7},
    { 11, 4},
    { 10, 9}
};

const std::array<size_t, 17> facttable = [] {
    std::array<size_t, 17> table;
    for (int i = 0; i < 17; i++) table[i] = factorial(i);
    return table;
}();

const int adj = 1;

std::thread::id t1id;

int main(int argc, char** argv) {
    //std::ios_base::sync_with_stdio(false);
    std::array<int, 16> values = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 };
    if (argc == 17) {
        for (int i = 0; i < 16; i++) {
            values[i] = atoi(argv[i + 1]);
        }
    }
    auto start = std::chrono::high_resolution_clock::now();
    const static_solution_state static_state(values);
#if defined(REDUCE_MEMORY_USE)
    const int num_of_threads = max(1u, min(thread::hardware_concurrency(), 16u));
#else
    const int num_of_threads = 16;
#endif
    std::vector<solution_state> states(num_of_threads, static_state);
    for (int i = 0; i < num_of_threads; i++) {
        int start = i * 16 / num_of_threads;
        states[i].permutations_found += start * factorial(16) / 16;
    }
    std::fstream out;
    setupOutput(out);
    std::locale loc("");
    std::cout.imbue(loc);
    volatile bool report = false;
    volatile bool done = false;
    volatile size_t tests = 0;

    std::thread progress([&]() {
        auto now = std::chrono::steady_clock::now();
        while (!done) {
            if (std::chrono::steady_clock::now() - now > std::chrono::seconds(1)) {
                now += std::chrono::seconds(1);

                size_t t_tests = 0;
                for (int i = 0; i < num_of_threads; i++) t_tests += states[i].permutations_found - i * factorial(16) / num_of_threads;
                tests = t_tests;
                report = true;
            }
            std::this_thread::yield();
        }
    });

    if (num_of_threads <= 1) {


        states[0].setLog(out);
        permute(static_state, states[0], report, tests, done);


    } 
    else {
        std::vector<std::thread> threads;
#if defined(REDUCE_MEMORY_USE)
        std::vector<std::fstream> logs(num_of_threads);
#else
        std::vector<std::stringstream> logs(num_of_threads);
#endif
        for (int i = 0; i < num_of_threads; i++) {
            threads.emplace_back([&, i]() {
                if (i == 0) t1id = std::this_thread::get_id();
                int start = i * 16 / num_of_threads;
                int end = (i + 1) * 16 / num_of_threads;
#if defined(REDUCE_MEMORY_USE)
                logs[i].open("T"s + to_string(i) + "log.tmp", ios::out);
#endif
                logs[i].imbue(loc);
                states[i].setLog(logs[i]);

                for (int j = start; j < end; j++) {


                    states[i].currentSolution = { j };
                    states[i].level = 1;
                    states[i].used[j] = true;
                    permute(static_state, states[i], report, tests, done);


                }
            });
        }

        std::string buffer;
        for (int i = 0; i < num_of_threads; i++) {
            threads[i].join();
#if defined(REDUCE_MEMORY_USE)
            logs[i].close();
            logs[i].open("T"s + to_string(i) + "log.tmp", ios::in);
            logs[i].seekg(0, ios::end);
            auto length = logs[i].tellg();
            logs[i].seekg(0, ios::beg);
            buffer.resize(length);
            logs[i].read(&buffer[0], length);
            logs[i].close();
            remove(("T"s + to_string(i) + "log.tmp").c_str());
            out << buffer;
#else
            out << logs[i].str();
#endif
        }
    }
    done = true;
    out.close();

    if (num_of_threads > 1) {
        size_t t_tests = 0;
        for (int i = 0; i < num_of_threads; i++) t_tests += states[i].permutations_found - i * factorial(16) / num_of_threads;
        tests = t_tests;
    }

    size_t solutions = 0;
    for (const auto & state : states) {
        solutions += state.solutions_found;
    }

    auto end = std::chrono::high_resolution_clock::now();

    progress.join();

    auto duration = end - start;
    auto secondsDuration = std::chrono::duration_cast<std::chrono::milliseconds>(duration);
    std::cout << "Total time to process all " << tests << " results: " << std::setprecision(3) << std::setiosflags(std::ostream::fixed) << (secondsDuration.count()/1000.0) << "s" << "\n";
    std::cout << "Solutions found: " << solutions << std::endl;
    //system("pause");
    return 0;
}

void permute(const static_solution_state & static_state, solution_state & state, volatile bool & reportProgress, const volatile size_t & total_tests, volatile bool & done) {
    if (done) return;
    if (state.level >= 16) {
        if (reportProgress) {
            reportProgress = false;
            std::cout << "Current Status:" << "\n";
            std::cout << "Test " << total_tests << "\n";
            std::cout << "Contents: {";
            for (int i = 0; i < 15; i++) std::cout << std::setw(static_state.padding - 1) << state[i] << ",";
            std::cout << std::setw(static_state.padding - 1) << state[15] << "}" << "(Partial Sum: " << state.sums[0] << ")" << "\n";
            std::cout << "=====================" << "\n";
        }
        printSolution(static_state,state);
        state.solutions_found++;
        state.permutations_found++;
    }
    else {
        if (state.level == 3) state.sums[0] = state[0] + state[1] + state[2];

        if (!findnext2digits[state.level]) {
            for (int i = 0; i < 16; i++) {
                if (!state.used[i]) {
                    state.currentSolution[state.level] = i;
                    state.used[i] = true;
                    state.level++;
                    permute(static_state, state, reportProgress, total_tests, done);
                    state.level--;
                    state.used[i] = false;
                }
            }
        }
        else {
            int incompletetwosum = getincompletetwosum(static_state, state);
            if (static_state.twosums.find(incompletetwosum) == static_state.twosums.end()) {
                state.permutations_found += facttable[16 - state.level];
            }
            else {
                size_t successes = 0;
                const std::vector<std::pair<int, int>> & potentialpairs = static_state.twosums.at(incompletetwosum);
                for (const std::pair<int, int> & values : potentialpairs) {
                    if (!state.used[values.first] && !state.used[values.second]) {
                        state.currentSolution[state.level] = values.first;
                        state.currentSolution[state.level + 1] = values.second;
                        state.used[values.first] = true;
                        state.used[values.second] = true;
                        state.level += 2;
                        permute(static_state, state, reportProgress, total_tests, done);
                        state.level -= 2;
                        state.used[values.first] = false;
                        state.used[values.second] = false;

                        successes++;
                    }
                }
                state.permutations_found += facttable[16 - state.level - 2] * ((16 - state.level) * (15 - state.level) - successes); 
            }
        }
    }
}

int getincompletetwosum(const static_solution_state & static_state, const solution_state & state) {
    int retvalue = state.sums[0];
    int thissum = currentsum[state.level];
    for (int i = 0; i < 2 && twosumindexes[thissum][i] >= 0; i++) {
        retvalue -= state[twosumindexes[thissum][i]];
    }
    return retvalue;
}

constexpr size_t factorial(size_t iter) {
    return (iter <= 0) ? 1 : iter * factorial(iter - 1);
}

void setupOutput(std::fstream & out) {
    out.open("puzzle.txt", std::ios::out | std::ios::trunc);
    std::locale loc("");
    out.imbue(loc);
}

void printSolution(const static_solution_state & static_state, const solution_state & state) {
    std::ostream & out = *state.log;
    out << "Test " << state.permutations_found << "\n";
    static const auto format = [](std::ostream & out, const static_solution_state & static_state, const solution_state & state, const std::vector<int> & inputs) {
        for (const int & index : inputs) {
            if (index < 0 || index >= 16) out << static_state.spacing;
            else out
                << std::setw(static_state.padding)
                << state[index];
        }
        out << "\n";
    };
    format(out, static_state, state, { -1, -1, -1,  0,  1,  2 });
    format(out, static_state, state, { 15,  9, 14, 10, -1,  3 });
    format(out, static_state, state, { -1,  8, -1, 11, 12,  4, 13 });
    format(out, static_state, state, { -1,  5,  6,  7});

    out << "Partial Sum: " << (state.sums[0]) << "\n";
    out << "=============================" << "\n";
}

summap static_solution_state::gettwovaluesums() {
    summap sums;
    for (int i = 0; i < 16; i++) {
        for (int j = 0; j < 16; j++) {
            if (i == j) continue;
            std::pair<int,int> values( i, j );
            int sum = validNumbers[values.first] + validNumbers[values.second];
            sums[sum].push_back(values);
        }
    }
    return sums;
}

std::vector<sumlist> static_solution_state::gettwovaluesumsvector() {
    std::vector<sumlist> sums;
    for (auto & key : twosums) {
        sums.push_back(key);
    }

    std::sort(sums.begin(), sums.end(), [](sumlist a, sumlist b) {
        return a.first < b.first;
    });
    return sums;
}

আমি নিশ্চিত যে আপনি সচেতন, আপনি যদি নিজের আউটপুটকে কিছুটা সহজ করেন তবে আপনি একটি শালীন সময় শেভ করতে পারেন। আপনার কোডের জন্য এখানে সময়: 0.1038s +/- 0.0002 এবং সরলিকৃত আউটপুট সহ আপনার কোডের সময় এখানে: 0.0850s +/- 0.0001 সুতরাং, আপনি কমপক্ষে আমার মেশিনে 18 ডলার সঞ্চয় করতে পারেন। আমি দু'টি
অ্যান্ড্রু এপস্টেইন

1

প্রোলগ - 3 মিনিট

এই ধরণের ধাঁধাটি প্রোলোগের জন্য একটি নিখুঁত ব্যবহারের ক্ষেত্রে বলে মনে হচ্ছে। সুতরাং, আমি প্রলোগে একটি সমাধান কোড আপ করেছি! এটা এখানে:

:- use_module(library(clpfd)).

puzzle(P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15) :-
    Vars = [P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15],
    Vars ins 1..16,
    all_different(Vars),
    29 #= P0 + P1 + P2,
    29 #= P3 + P4 + P5 + P6,
    29 #= P9 + P10 + P11 + P12,
    29 #= P13 + P14 + P15,
    29 #= P0 + P6 + P9 + P15,
    29 #= P2 + P7 + P11,
    29 #= P4 + P8 + P13.

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

time(aggregate_all(count, (puzzle(P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15), labeling([leftmost, up, enum], [P9, P15, P13, P0, P4, P2, P6, P11, P1, P5, P3, P7, P14, P12, P10, P8])), Count)).

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

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