Этот код в настоящее время выходы
и т.п.
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
Я пытаюсь найти правильные значения зеленого, желтого, фиолетового, оранжевого, красного и синего с помощью грубой силы
Эти значения не могут повторяться (т. Е. Если красный = 0, то синий! = 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;
}
}
}
}
}
}
}
}
Если я понял проблему, вы должны выбрать между всеми возможными комбинациями различных значений цвета, которые решают ваши четыре уравнения.
Вложенные циклы в коде 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';
}
После выполнения выдает:
Зеленый: 5 Желтый: 3 Фиолетовый: 1 Оранжевый: 6 Красный: 4 Синий: 9 Проверенные комбинации: 151200 (из 1000000) Решения: 1
РЕДАКТИРОВАТЬ
Подстрекаемый Jarod42«s ответ, Я хотел бы показать более эффективное решение, которое использует преимущества стандартной функции библиотеки 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)!) = 151 200 перестановок.
Другой способ грубой силы, но ограничивающий количество комбинаций:
#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;
}
5 3 1 6 4 9
Combination tested 151192 on a total of 3628800