Mümkün olan en kısa sürede bu sayı bulmacasının tüm çözümlerini bulun


16

Tarih

Şirketim, şirket içindeki herkese haftalık bir bülten gönderir. Bu bültenlere bir bilmece de dahil, geçen haftaki bilmeceye ilk e-posta gönderen / çözüm sağlayan şirkette kim olduğu için yapılan bir çekiliş. Bu bilmecelerin çoğu oldukça önemsiz ve bir teknoloji şirketi için dürüstçe oldukça sıkıcı, ancak dikkatimi çeken bir, birkaç ay vardı.

Orijinal Bilmece:

Aşağıdaki şekil göz önüne alındığında:

Bulmaca Resmi

1'den 16'ya kadar Doğal Sayılara sahipsiniz. Hepsini bitişik sıralar ve bitişik sütunlar 29'a kadar olacak şekilde bu şekle sokun.

Örneğin, bu bulmacanın böyle bir çözümü (bültene gönderdiğim "kanonik" çözüm):

Çözülmüş Bulmaca Resmi

Ancak, çözme sırasında oldukça ilginç bazı bilgiler buldum:

  • Bundan çok daha fazla çözüm var; aslında 9.368 çözüm var.
  • Kural kümesini, yalnızca satırların ve sütunların 29'a değil, birbirine eşit olmasını gerektirecek şekilde genişletirseniz, 33.608 çözüm elde edersiniz:
    • 4.440 Toplam 27 çözüm.
    • 2800 için 7.400 çözüm.
    • 9.368 Toplam 29 çözelti.
    • 6.096 Toplam 30 çözüm.
    • 5.104 Toplam 31 çözüm.
    • 32 toplamda 1.200 çözüm.

Bu yüzden ben ve arkadaşlarım (çoğunlukla sadece yöneticim olsa da, “Genel Amaçlı” programlama becerilerine sahip benden başka tek kişi olduğu için) ayın büyük bir kısmında devam eden bir meydan okumaya başladık - başka, gerçek bir işimiz vardı - ilgili yükümlülüklerimizi yerine getirmek zorunda kaldık - her bir çözümü en hızlı şekilde bulabilecek bir program yazmaya çalışmak.

Orijinal İstatistikler

Sorunu çözmek için yazdığım ilk program rastgele çözümleri tekrar tekrar kontrol etti ve bir çözüm bulduğunda durdu. Bu problem üzerinde Matematiksel analiz yaptıysanız, muhtemelen bunun işe yaramaması gerektiğini biliyorsunuzdur; ama bir şekilde şanslıydım ve programın tek bir çözüm bulması sadece bir dakika sürdü (yukarıda gönderdiğim çözüm). Programın tekrar çalışmaları genellikle 10 veya 20 dakika kadar sürdü, bu yüzden bu sorunun kesin bir çözümü değildi.

Bulmacanın olası her permütasyonuyla yinelenen Yinelenen bir Çözüme geçtim ve bir araya gelmeyen toplamları ortadan kaldırarak birçok çözümü bir kerede attım. IE karşılaştırdığım ilk satır / sütun zaten eşit olmasaydı, bulmacanın içine izin verilen başka hiçbir şeyin bunu değiştirmeyeceğini bilerek hemen o dalı kontrol etmeyi bırakabilirdim.

Bu algoritmayı kullanarak, ilk "uygun" başarıyı elde ettim: program yaklaşık 33 dakikada tüm 33.608 çözümleri üretip tükürebilirdi.

Yöneticimin farklı bir yaklaşımı vardı: çalışmalarıma dayanarak, mümkün olan tek çözümlerin toplamının 27, 28, 29, 30, 31 veya 32 olduğunu bilerek, sadece bu belirli değerler için olası toplamları kontrol eden çok iş parçacıklı bir çözüm yazdı. Programını sadece 2 dakika içinde çalıştırmayı başardı. Bu yüzden tekrar ettim; Tüm olası 3/4 haneli toplamları (programın başında; toplam çalışma zamanında sayılır) hashedim ve kalan değeri daha önce tamamlanmış bir satıra göre aramak için bir satırın "kısmi toplamını" kullandım. kalan tüm değerleri test eder ve zamanı 72 saniyeye indirir. Sonra çok iş parçacıklı bir mantıkla 40 saniyeye indirdim. Yöneticim programı eve götürdü, programın nasıl çalıştığına dair bazı optimizasyonlar yaptı ve 12 saniyeye indi. Satırların ve sütunların değerlendirmesini yeniden sıraladım,

Bir ay sonra programlarımızdan en hızlısı yöneticimiz için 0.15 saniye, benim için 0.33 saniye oldu. Programımın daha hızlı olduğunu iddia ettim, çünkü yöneticimin programı, tüm çözümleri bulmasına rağmen, bunları bir metin dosyasına yazdırmıyor. Bu mantığı koduna eklediyse, genellikle 0.4-0.5 saniye kadar sürdü.

Biz bu yana geçinmeye bizim içi kişisel bir meydan okuma izni verdim, ama tabii ki, soru kalıntıları: edebilir bu program daha hızlı yapılabilir?

Size göstereceğim zorluk budur.

Sizin Mücadeleniz

Altında çalıştığımız parametreler, "tüm satırlar / sütunlar toplamları eşit" olmak için "toplam 29" kuralını rahatlattı ve ben de sizin için bu kuralı ayarlayacağım. Bu nedenle, Zorluklar: Bu bilmece için tüm çözümleri mümkün olan en kısa sürede bulan (ve yazdırılan!) Bir program yazın. Gönderilen çözümlere bir tavan koyacağım: Program nispeten iyi bir bilgisayarda (<8 yaşında) 10 saniyeden fazla sürerse, sayılamayacak kadar yavaş.

Ayrıca, bulmaca için birkaç bonusum var:

  • Çözümü, sadece 16 sayı kümesi için çalışacak şekilde genelleştirebilir misiniz int[1,16]? Zamanlama skoru, ayarlanan orijinal bilgi istemi numarasına göre değerlendirilecek, ancak bu kod yolundan geçirilecektir. (% 10)
  • Kodu, yinelenen sayılarla zarif bir şekilde işleyecek ve çözecek şekilde yazabilir misiniz? Bu göründüğü kadar basit değil! "Görsel olarak özdeş" çözümler sonuç kümesinde benzersiz olmalıdır. (5%)
  • Negatif sayıları ele alabilir misiniz? (5%)

Ayrıca Kayan Nokta Sayılarını işleyen bir çözüm üretmeye çalışabilirsiniz , ancak elbette, bu tamamen başarısız olursa şok olmaz. Eğer sağlam bir çözüm bulursanız, bu büyük bir bonus değerinde olabilir!

Tüm niyet ve amaçlar için, "Rotasyonlar" benzersiz çözümler olarak kabul edilir. Dolayısıyla, sadece farklı bir çözümün dönüşü olan bir çözüm kendi çözümü olarak sayılır.

Bilgisayarımda çalıştığım IDE'ler Java ve C ++. Diğer dillerden gelen yanıtları kabul edebilirim, ancak kodunuz için kurulumu kolay bir çalışma ortamı alabileceğim bir bağlantı da sağlamanız gerekebilir.


3
Kutsal kediler, güzel ilk soru! ... cesaret kırdığımız bonuslar hariç (çoğunlukla kod golf soruları için, bu yüzden burada iyi olmalılar)
kedi

4
@cat Bonusların burada mantıklı olduğunu düşünüyorum, çünkü kendi kodumda bu sorunları çözdüğümde, kodun önemli ölçüde yavaşlamasına neden oldular. Bu yüzden, dahil etmeyi haklı çıkarmak için bir bonus olduğunu düşünüyorum.
Xirema

2
BTW, yerinizde herhangi bir iş var mı? kolay bir patron ve ellerinde bol zaman var gibi geliyor :-)
Level River St

1
Yinelenen sayılarla, iki özdeş sayının değiş tokuş edildiği yinelenen çözümleri yazdırmak uygun mudur? bu bonusun nasıl yorumlandığı konusunda büyük bir fark yaratacaktır. Lütfen açıklığa kavuşun, ancak bu bonusu tamamen ortadan kaldırmayı düşünürüm.
Level River St

1
Ayrıca, 180 derece rotasyonlar aynı çözelti veya farklı çözeltiler olarak mı kabul edilir?
Level River St

Yanıtlar:


7

C - 0,5 saniyeye yakın

Bu çok naif program, 4 yaşındaki dizüstü bilgisayarımdaki tüm çözümleri yarım saniye içinde veriyor. Multithread yok, karma yok.

Windows 10, Visual Studio 2010, CPU çekirdeği I7 64 bit

İdeone'de çevrimiçi deneyin

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

Kutsal tatlı Kötü Vampir İsa, döngüler için yuvalanmış olanlar. Bahse girerim derleyicinizi gerçekten mutlu etti. XD
Xirema

@ edc65, FYI int inuse[16];sadece ile değiştirebilir int inuse;ve sonra onu işlemek için bitsel işleçleri kullanabilirsiniz. Hızı bu kadar artırmıyor gibi görünüyor , ama biraz yardımcı oluyor.
Andrew Epstein

Bitcoin vs
Indexing

@ edc65, bitshift sürümüne karşı orijinal sürümünüzü test etmek için dumbbench kullanma özgürlüğünü aldım. İşte sonuçları: Endeksleme: 0.2253 +/- 5.7590e-05 Bitshifting: 0.2093 +/- 6.6595e-05 Yani, makinemde yaklaşık 16 ms'lik bir hızlanma. Kullandığım komut şuydu:dumbbench --precision=.01 -vvv --initial=500 ./solve
Andrew Epstein

3

C ++ - 300 Milisaniye

İstek üzerine, bu bulmacayı çözmek için kendi kodumu ekledim. Bilgisayarımda, ortalama 0.310 saniyede (310 milisaniye) saatler varyansa bağlı olarak, varyansa bağlı olarak 287 milisaniye kadar hızlı çalışabilir. Çok nadiren 350 milisaniyenin üzerine çıktığını görüyorum, genellikle sadece sistemim farklı bir görevle boğulmuşsa.

Bu zamanlar, programda kullanılan kendi kendine raporlamaya dayanmaktadır, ancak harici bir zamanlayıcı kullanarak test ettim ve benzer sonuçlar elde ettim. Programdaki ek yük yaklaşık 10 milisaniye ekliyor gibi görünüyor.

Ayrıca benim kod değil oldukça düzgün çiftleri işlemek. Bunları kullanarak çözebilir, ancak çözüm kümesinden "görsel olarak özdeş" çözümleri ortadan kaldırmaz.

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

Emin olduğunuzdan emin olarak, çıktınızı biraz basitleştirirseniz, iyi bir zaman tıraş edebilirsiniz. Kodunuzun zamanı: 0.1038s +/- 0.0002 Ve basitleştirilmiş çıktı ile kodunuzun zamanı: 0.0850s +/- 0.0001 Yani, en azından makinemde ~ 18ms tasarruf edebilirsiniz. Her iki versiyonu da 500+ kez koştum, aptallar
Andrew Epstein

1

Prolog - 3 dakika

Bu tür bir bulmaca Prolog için mükemmel bir kullanım örneği gibi görünüyor. Bu yüzden Prolog'da bir çözüm kodladım! İşte burada:

:- 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.

Ne yazık ki, beklediğim kadar hızlı değil. Belki de bildirim programlamasında (veya özellikle Prolog'da) daha deneyimli bir kişi bazı optimizasyon ipuçları sunabilir. Kuralı puzzleaşağıdaki komutla başlatabilirsiniz :

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)).

Burada çevrimiçi deneyin . 29Tüm çözümleri üretmek için koddaki s yerine istediğiniz sayıyı kullanabilirsiniz . Haliyle, 29 çözeltinin tümü yaklaşık 30 saniye içinde bulunur, bu nedenle tüm olası çözümleri bulmak için yaklaşık 3 dakika olmalıdır.

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