我正在尝试根据4个方程找出六个值

时间:2018-09-27 12:31:54

标签: c++ math mathematical-expressions

此代码当前输出 0 1 0 1 1 2 F0 0 1 0 1 1 2 F1 0 1 0 1 1 3 F0 0 1 0 1 1 3 F1 0 1 0 1 1 4 F0等。 我正在尝试使用蛮力找出绿色,黄色,紫色,橙色,红色和蓝色的正确值 这些值不能重复(即如果red = 0则blue!= 0),但是我认为这段代码将为我提供多种解决方案,从中我可以选择正确的解决方案。 我的问题是:这有什么问题?

#include <iostream>
using namespace std;

int main()
{
int green, yellow, purple, orange, red, blue, finalresult;
int result1, result2, result3, result4, result5, result6, fresult1, fresult2;

for (green = 0; green < 10; green++)
{

    for (yellow = 0; yellow < 10; yellow++)
    {
        for (yellow = yellow; yellow == green; yellow++)
        {
            yellow = yellow;
        }
        for (purple = 0; purple < 10; purple++)
        {
            for (purple = purple; purple == yellow; purple++)
            {
                purple = purple;
            }
             for (orange = 0; orange < 10; orange++)
             {
                for (orange = orange; orange == purple; orange++)
                {
                    orange = orange;
                }
                  for (red = 1; red < 10; red++)
                  {
                        for (red = red; red == purple; red++)
                        {
                            red = red;
                        }
                        for (blue = 1; blue < 10; blue++)
                        {
                            for (blue = blue; blue == red; blue++)
                            {
                                blue = blue;
                            }
                            finalresult = 0;
                            if(green * yellow == purple * 10 + green)
                            {
                                cout << green << endl << yellow << endl << purple << endl << orange << endl << red << endl << blue << endl;
                                cout << "F" << finalresult << endl;
                                finalresult++;
                            }
                            if (purple * 10 + orange / red == red)
                            {
                                cout << green << endl << yellow << endl << purple << endl << orange << endl << red << endl << blue << endl;
                                cout << "F" << finalresult << endl;
                                finalresult++;
                            }
                            if (yellow * 10 + orange == red * blue)
                            {
                                cout << green << endl << yellow << endl << purple << endl << orange << endl << red << endl << blue << endl;
                                cout << "F" << finalresult << endl;
                                finalresult++;
                            }
                            if (green == red * 10 + green / blue)
                            {
                                cout << green << endl << yellow << endl << purple << endl << orange << endl << red << endl << blue << endl;
                                cout << "F" << finalresult << endl;
                                finalresult++;
                            }
                            if (finalresult == 4)
                            {
                                cout << "V" << endl <<"V" << endl << "V" << endl << "V" << endl << "V" << endl << "V" << endl << "V" << endl << "V" << endl << "V" << endl << "V" << endl << "V" << endl << "V" << endl << "V" << endl;
                                cout << green << endl << yellow << endl << purple << endl << orange << endl << red << endl << blue << endl;

                            }
                        }

                  }

             }

        }

    }

}

}

2 个答案:

答案 0 :(得分:1)

如果我理解这个问题,则必须在所有可能的不同颜色值组合之间进行选择,以解决您的四个方程式。

OP代码中的嵌套循环将提供(几乎有一些循环从1开始)所有可能的组合,但是选择排除重复值的方式是完全错误的。

方程也可以在一个条件下检查。

以下代码应提供预期的结果:

#include <iostream>

int main(void)
{
    long int n = 0, solutions = 0;

    for (int green = 0; green < 10; ++green)
    {
        for (int yellow = 0; yellow < 10; ++yellow)
        {
            if ( yellow == green )    // skip the duplicate values
                continue;

            for (int purple = 0; purple < 10; ++purple)
            {
                if ( purple == green  ||  purple == yellow )
                    continue;

                for (int orange = 0; orange < 10; ++orange)
                {
                    if ( orange == green  ||  orange == yellow  ||  orange == purple )
                        continue;

                    for (int red = 0; red < 10; ++red)
                    {
                        if ( red == green   ||  red == yellow  ||
                             red == purple  ||  red == orange)
                            continue;

                        for (int blue = 0; blue < 10; ++blue)
                        {
                            if ( blue == green   ||  blue == yellow  ||
                                 blue == purple  ||  blue == orange  ||  blue == red )
                                continue;

                            // Now check if the values solve all the equations
                            // Assuming that you don't want integer divisions 
                            if (   purple * 10 + green  == green * yellow
                                && purple * 10 + orange == red * red
                                && yellow * 10 + orange == red * blue
                                &&    red * 10 + green  == green * blue)
                            {
                                std::cout << "Green:  " << green
                                    << "\nYellow: " << yellow
                                    << "\nPurple: " << purple
                                    << "\nOrange: " << orange
                                    << "\nRed:    " << red
                                    << "\nBlue:   " << blue << '\n';
                                ++solutions;
                            }
                            ++n;
                        }
                    }
                }
            }
        }
    }
    // The number of different combinations should be 10 * 9 * 8 * 7 * 6 * 5 = 151200 
    std::cout << "\nCombinations tested: " << n
        << " (out of " << 10*10*10*10*10*10 << ")\n"
        << "Solutions: " << solutions << '\n';
}

执行后,将输出:

Green:  5
Yellow: 3
Purple: 1
Orange: 6
Red:    4
Blue:   9

Combinations tested: 151200 (out of 1000000)
Solutions: 1

编辑

Jarod42answer的启发,我想展示一个更有效的解决方案,该解决方案利用了标准库函数std::next_permutation(和std::prev_permutation的优势) ),而不是跳过不需要的排列,而是直接生成所需的排列。

#include <iostream>
#include <vector>
#include <array>
#include <algorithm>
#include <numeric>

// Applies f() to all the permutations of n values taken k at a time
// where k is the size of the range [first, last)
// n!/(n − k)! iterations are performed
template<class Iterator, class Func>
void for_each_n_permute_k(int n, Iterator first, Iterator last, Func f);

int main()
{
    std::array<int, 6> chosen;
    int solutions = 0;

    for_each_n_permute_k(10, chosen.begin(), chosen.end(), [&chosen, &solutions] () {
        auto & [green, yellow, purple, orange, red, blue] = chosen;

        if (   purple * 10 + green  == green * yellow
            && purple * 10 + orange == red * red
            && yellow * 10 + orange == red * blue
            &&    red * 10 + green  == green * blue)
        {
            std::cout << "Solution found (" << ++solutions << ")\n"
                << "Green:  " << green
                << "\nYellow: " << yellow
                << "\nPurple: " << purple
                << "\nOrange: " << orange
                << "\nRed:    " << red
                << "\nBlue:   " << blue << '\n';
        }
    });
}

// copy the elements from [it1, last) to dest if the predicate applied to
// the corresponding element of [it2, it2 + distance(it1, last)) returns true
template<class Input1It, class Input2It, class OutputIt, class Predicate>
constexpr OutputIt select_if(Input1It it1, Input1It last,
                             Input2It it2, OutputIt dest, Predicate pred)
{
    for( ; it1 != last; ++it1, ++it2)
    {
        if (pred(*it2))
        {
            *dest++ = *it1;
        } 
    }
    return dest;
}

template<class Iterator, class Func>
void for_each_n_permute_k(int n, Iterator first, Iterator last, Func f)
{
    // e.g. for n == 10 -> {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    std::vector<int> numbers(n);
    std::iota(numbers.begin(), numbers.end(), 0);

    // e.g. for n == 10 and k == 6 -> {1, 1, 1, 1, 1, 1, 0, 0, 0, 0};
    std::vector<int> flags(n);
    std::fill(flags.begin(), flags.begin() + std::distance(first, last), 1);

    long long int tested = 0;

    do
    {
        // choose the k elements, e.g. for n == 10 and k == 6 -> {0, 1, 2, 3, 4, 5};
        select_if(numbers.begin(), numbers.end(), flags.begin(), first,
                  [] (int x) { return x == 1; });
        do
        {
            ++tested;
            f();
        } while (std::next_permutation(first, last));

    // 'flags' starts sorted in descending order, so I need the previous permutation
    } while (std::prev_permutation(flags.begin(), flags.end())); 

    std::cout << "\nPermutations tested: " << tested << '\n';
}

它找到遍历所有且仅遍历唯一的(10!/(10-6)!)= 151200个排列的相同解决方案。

答案 1 :(得分:0)

另一种蛮力方式,但限制了组合的麻烦:

#include <iostream>
#include <algorithm>

int main()
{
    int numbers[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

    int tested_combination_count = 0;
    int total_permutation_count = 0;
    int last_blue = 0;
    do
    {
        int green = numbers[0];
        int yellow = numbers[1];
        int purple = numbers[2];
        int orange = numbers[3];
        int red = numbers[4];
        int blue = numbers[5];

        ++total_permutation_count;
        if (last_blue == blue) {
            continue;
        }
        last_blue = blue;
        ++tested_combination_count;
        if (purple * 10 + green  == green * yellow
            && purple * 10 + orange == red * red
            && yellow * 10 + orange == red * blue
            &&    red * 10 + green  == green * blue) {
            std::cout << green << " " << yellow << " " << purple << " "
                      << orange << " " << red << " " << blue << std::endl;
        }
    } while (std::next_permutation(std::begin(numbers), std::end(numbers)));
    std::cout << "Combination tested:" << tested_combination_count
              << " on a total of " << total_permutation_count << std::endl;
}

Demo

5 3 1 6 4 9
Combination tested 151192 on a total of 3628800