最短時間でこの数字パズルのすべての解決策を見つける


16

歴史

私の会社は、毎週のニュースレターを社内の全員に送信しています。これらのニュースレターには、先週のなぞなぞの解決策を最初にメールしたり提供したりした会社の誰に対しても叫び声とともに、なぞなぞが含まれています。これらのなぞなぞのほとんどは非常に些細なものであり、正直なところハイテク企業にとってはかなり退屈なものですが、数か月前に私が注意を引いたものがありました。

オリジナルのなぞなぞ:

以下の形状を考えます:

パズル画像

1〜16の自然数があります。すべての連続する行と連続する列の合計が29になるように、すべてをこの形状に合わせます。

たとえば、このパズルに対するそのようなソリューション(ニュースレターに提出した「標準的な」ソリューション)は次のとおりです。

解決されたパズル画像

しかし、それを解決する過程で、かなり興味深い情報を見つけました。

  • それよりもはるかに多くのソリューションがあります。実際、9,368のソリューションがあります。
  • ルールセットを拡張して、行と列が29である必要はなく、互いに等しいことだけを要求する場合、33,608のソリューションが得られます。
    • 合計27の4,440のソリューション。
    • 合計28の7,400のソリューション。
    • 29の合計のための9,368のソリューション。
    • 合計30の6,096のソリューション。
    • 合計31の5,104ソリューション。
    • 合計32の1,200ソリューション。

だから私と私の同僚(主に私のマネージャーは、「一般目的」のプログラミングスキルを持っている私以外の唯一の人物だったので)は、1か月のほとんど続いた挑戦に着手しました。関連する義務-可能な限り迅速にすべてのソリューションを見つけるプログラムを作成しようとするために。

元の統計

問題を解決するために私が書いた最初のプログラムは、単にランダムな解決策を何度もチェックし、解決策が見つかった時点で停止しました。この問題について数学的分析を行ったことがあれば、おそらくこれが機能してはならないことをすでに知っているでしょう。しかし、どういうわけか私は幸運に恵まれ、プログラムが1つのソリューション(上記で投稿したもの)を見つけるのに1分しかかかりませんでした。プログラムを繰り返し実行すると、多くの場合10〜20分かかるため、これは明らかに問題の厳密な解決策ではありませんでした。

パズルのあらゆる可能な順列を反復する再帰的ソリューションに切り替え、合計していない合計を削除することで、多くのソリューションを一度に破棄しました。IE私が比較した最初の行/列が既に等しくなかった場合、パズルに入れ替わったものがそれを変更しないことを知って、そのブランチのチェックをすぐに停止できました。

このアルゴリズムを使用して、最初の「適切な」成功が得られました。プログラムは、約5分で33,608のソリューションすべてを生成して吐き出すことができました。

私のマネージャーは異なるアプローチを持っていました:私の仕事に基づいて、可能な解決策は27、28、29、30、31、または32の合計しかないと知っていたので、彼はそれらの特定の値についてのみ可能な合計をチェックするマルチスレッドソリューションを書きました。彼はわずか2分でプログラムを実行することができました。だから私は再び繰り返しました。可能なすべての3/4桁の合計をハッシュし(プログラムの開始時に、合計ランタイムでカウントされます)、行の「部分合計」を使用して、以前に完了した行に基づいて、以前に完了した行に基づいて残りの値を検索しました残りのすべての値をテストし、時間を72秒に短縮しました。その後、いくつかのマルチスレッドロジックを使用して、40秒に短縮しました。私のマネージャーは、プログラムを家に持ち帰り、プログラムの実行方法についていくつかの最適化を実行し、12秒に短縮しました。行と列の評価を並べ替え、

私たちのどちらかが1か月後にプログラムを取得した最速の時間は、マネージャーが0.15秒、私が0.33秒でした。私のマネージャーのプログラムはすべての解決策を見つけましたが、それらをテキストファイルに出力しなかったので、私は私のプログラムがより高速であると主張しました。彼がコードにそのロジックを追加した場合、多くの場合、0.4〜0.5秒かかりました。

私たちは、以来、生存するまで、当社内の個人的な挑戦を許されましたが、当然のことながら、質問の遺跡は:することができます。このプログラムは高速化できますか?

それが私が皆さんに提起する挑戦です。

あなたの挑戦

私たちが取り組んだパラメーターは、「29の合計」ルールを緩和し、代わりに「すべての行/列の合計が等しくなる」ようにしました。このルールを皆さんにも設定します。したがって、課題は次のとおりです。この謎に対するすべての解決策を可能な限り短時間で発見(および印刷!)するプログラムを作成します。提出されたソリューションに上限を設定します。比較的まともなコンピューター(<8歳)でプログラムに10秒以上かかる場合、カウントするには遅すぎる可能性があります。

また、パズルにはいくつかのボーナスがあります:

  • ソリューションを一般化して、16個の数値のセットだけでなく、それでも機能するようにできますint[1,16]か?タイミングスコアは、元のプロンプト番号セットに基づいて評価されますが、このコードパスを通過します。(-10%)
  • 重複した数値を適切に処理して解決する方法でコードを記述できますか?これは見かけほど簡単ではありません!「視覚的に同一」のソリューションは、結果セット内で一意である必要があります。(-5%)
  • 負の数を処理できますか?(-5%)

あなたもすることができますしようとハンドルがの浮動小数点数というソリューションを生成するが、それは全く失敗した場合はもちろん、ショックを受けることはありません。しかし、堅牢なソリューションを見つけた場合、それは大きなボーナスの価値があるかもしれません!

すべての意図と目的に対して、「回転」はユニークなソリューションと見なされます。したがって、異なるソリューションの単なるローテーションであるソリューションは、独自のソリューションとしてカウントされます。

コンピューターで作業しているIDEはJavaとC ++です。他の言語からの回答を受け入れることもできますが、コードのセットアップが容易なランタイム環境を入手できる場所へのリンクも提供する必要があります。


3
神聖な猫、素敵な最初の質問!(主に上...私たちは、落胆みかんボーナスを除き、コード・ゴルフ、彼らは罰金ここにする必要がありますので、ご質問)

4
@catボーナスはここで理にかなっていると思います。なぜなら、自分のコードでこれらの問題を解決したとき、コードが大幅に遅くなる傾向があったからです。だから、私はボーナスを含めることを正当化するためだと思います。
Xirema

2
ところで、あなたの場所で行っている仕事はありますか?のんきな上司がいて、十分な時間があるように思えます:
Level River St

1
番号が重複している場合、2つの同じ番号が交換される重複ソリューションを印刷しても問題ありませんか?それはそのボーナスがどのように解釈されるかに関して大きな違いを生むでしょう。明確にしてください、しかし、私はそのボーナスを完全に排除することを検討します。
レベルリバーセント

1
また、180度の回転は同じソリューションと見なされますか、異なるソリューションと見なされますか?
レベルリバーセント

回答:


7

C-0.5秒に近い

この非常に素朴なプログラムは、私の4歳のラップトップで0.5秒ですべてのソリューションを提供します。マルチスレッドなし、ハッシュなし。

Windows 10、Visual Studio 2010、CPUコアI7 64ビット

ideoneでオンラインで試す

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

神聖な甘い邪悪な吸血鬼のイエス、ループの入れ子。しかし、それはあなたのコンパイラを本当に幸せにしてくれるに違いありません。XD
Xirema

@ edc65、FYIに置き換えてint inuse[16];int inuse;ビット単位演算子を使用して操作できます。速度を上げるようには見えないことくらい、それは少しのに役立ちます。
アンドリューエプスタイン

@AndrewEpsteinそれはさらに遅くなる可能性があります-ビットシフトとインデックス作成
-edc65

@ edc65、dumbbenchを使用して元のバージョンとビットシフトバージョンをテストする自由を取りました。結果は次のとおりです。インデックス:0.2253 +/- 5.7590e-05ビットシフト:0.2093 +/- 6.6595e-05したがって、私のマシンで約16msの速度向上が実現しました。私が使用するコマンドは以下のとおりであった:dumbbench --precision=.01 -vvv --initial=500 ./solve
アンドリュー・エプスタイン

3

C ++-300ミリ秒

リクエストごとに、このパズルを解決するために独自のコードを追加しました。私のコンピューターでは、平均で0.310秒(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 、出力が単純化されたコードの時間です。 したがって、少なくとも私のマシンでは、〜18ms節約できます。私が使用して、捨て外れ値との両方のバージョン500+回走ったdumbbench
アンドリュー・エプスタイン

1

プロローグ-3分

この種のパズルは、Prologの完璧なユースケースのようです。そこで、Prologでソリューションをコーディングしました!ここにあります:

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

残念ながら、期待したほど速くはありません。宣言型プログラミング(または特にProlog)に詳しい人が、最適化のヒントを提供できるかもしれません。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コード内のsの代わりに任意の数を使用して、すべてのソリューションを生成できます。現状では、29のソリューションはすべて約30秒で検出されるため、可能なソリューションをすべて検出するには約3分かかります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.