Как упростить проверить условия на истину с несколькими значениями?
Я думаю что это походе чем то на код грея где все условия проверяются и исполняются последовательно, но с одним условием, нельзя повторять то что уже исполнилось.
По сути я ожидаю когда весь массив заполниться и код начинает проверку по условиям, единственное я не могу остановить цикл поэтому проверки должны учитывать это.
Вот что я хочу упростить
if(time[0] == true && time[1] == true) {
std::cout << i << " - i | " << " XD :) 0 " << "\n" << std::endl;
time[1] = false;
}
else if(time[0] == true && time[1] == false) {
std::cout << i << " - i | " << " XD :) 1 " << "\n" << std::endl;
time[0] = false;
}
else if(time[0] == false && time[1] == true) {
std::cout << i << " - i | " << " XD :) 2 " << "\n" << std::endl;
time[1] = false;
}
Я тут использовал только 2 значения в массиве, но будет еще такое, где массив размером 3
if(time[0] == true && time[1] == true && time[2] == true) {
std::cout << i << " - i | " << " XD :) 0 " << "\n" << std::endl;
time[2] = false;
}
else if(time[0] == true && time[1] == true && time[2] == false) {
std::cout << i << " - i | " << " XD :) 1 " << "\n" << std::endl;
time[1] = false;
}
else if(time[0] == true && time[1] == false && time[2] == false) {
std::cout << i << " - i | " << " XD :) 2 " << "\n" << std::endl;
time[0] = false;
}
else if(time[0] == false && time[1] == false && time[2] == true) {
std::cout << i << " - i | " << " XD :) 3 " << "\n" << std::endl;
time[2] = false;
}
else if(time[0] == false && time[1] == true && time[2] == false) {
std::cout << i << " - i | " << " XD :) 4 " << "\n" << std::endl;
time[1] = false;
}
else if(time[0] == false && time[1] == true && time[2] == true) {
std::cout << i << " - i | " << " XD :) 5 " << "\n" << std::endl;
time[2] = false;
}
else if(time[0] == true && time[1] == false && time[2] == true) {
std::cout << i << " - i | " << " XD :) 6 " << "\n" << std::endl;
time[0] = false;
}
Я кстати не уверен что правильно написал второй вариант, но вроде все учтено.
Полный код на эксперименты https://godbolt.org/z/vMsTWfe4x
Ответы (3 шт):
Две таблицы. xds по трём булевым индексам возвращает значение xd для печати. clear по трём булевым индексам возвращает какую переменную стереть:
#include <iostream>
int main() {
// xd
// ttt -> 0 -> ttf
// ttf -> 1 -> tff
// tff -> 2 -> fff
// fft -> 3 -> fff
// ftf -> 4 -> fff
// ftt -> 5 -> ftf
// tft -> 6 -> fft
const int xds[2][2][2] = {
{{-1, 3}, {4, 5}},
{{ 2, 6}, {1, 0}},
};
const int clear[2][2][2] = {
{{-1, 2}, {1, 2}},
{{ 0, 0}, {1, 2}},
};
bool time[3] = {true, true, true};
for (int i = 0; ; ++i) {
int xd = xds[time[0]][time[1]][time[2]];
if (xd < 0) {
break;
}
std::cout << i << " - i | " << " XD :) " << xd << '\n';
time[clear[time[0]][time[1]][time[2]]] = false;
}
}
$ g++ -std=c++17 -pedantic -Wall -Wextra -Werror table.cpp && ./a.out 0 - i | XD :) 0 1 - i | XD :) 1 2 - i | XD :) 2
Ещё один вариант с двумя таблицами. Теперь таблицы - одномерные массивы. Индекс в них строится из массива time:
#include <iostream>
int main() {
// xd
// ttt -> 0 -> ttf
// ttf -> 1 -> tff
// tff -> 2 -> fff
// fft -> 3 -> fff
// ftf -> 4 -> fff
// ftt -> 5 -> ftf
// tft -> 6 -> fft
const int xds[] = {
-1, // 0b000
3, // 0b001
4, // 0b010
5, // 0b011
2, // 0b100
6, // 0b101
1, // 0b110
0 // 0b111
};
const int clear[] = {
-1, // 0b000
2, // 0b001
1, // 0b010
2, // 0b011
0, // 0b100
0, // 0b101
1, // 0b110
2 // 0b111
};
bool time[3] = {true, true, true};
for (int i = 0; ; ++i) {
int j = 0;
for (bool t : time) {
j = 2 * j + static_cast<int>(t);
}
int xd = xds[j];
if (xd < 0) {
break;
}
std::cout << i << " - i | " << " XD :) " << xd << '\n';
time[clear[j]] = false;
}
}
const size_t bad_index = ~ size_t(0);
template<unsigned Size>
size_t lastFlagIndex( const bool (&array) [Size] )
{
// Можно сделать тоже с помощью стандартных алгоритмов. Но ненужно: вас это пока запутает.
for(size_t i=0; i<Size; ++i)
if( array[ Size-i-1 ] )
return Size-i-1;
return bad_index ; // Если ни один флаг не установлен - возвращаем заведомо неверное значений флага.
}
template<unsigned Size>
size_t flagsToBinaryValue( const bool (&array) [Size] )
{
size_t ret=0;
for(bool f: array)
ret = ret *2 + (f?1:0);
return ret;
}
....
// Вместо цепочки if-else:
if( lastFlagIndex(time)!=bad_index )
{
std::cout << i << " - i | " << " XD :) " << flagsToBinaryValue(time) << "\n" << std::endl;
time [ lastFlagIndex(time) ] = false;
}
@Harry не понял, ну ладно
Ну, чтоб было понятнее... Ваши переходы между состояниями выглядят так (возле стрелок — то, что выводится, состояния — time[0]time[1]time[2]):

Кстати, я бы использовал не массив bool, а просто какой-то unsigned с соответствующими битовыми представлениями...
И получается весь ваш код со всеми if'ами —
struct DKA
{
int value;
unsigned char next;
} dka[8] = {
{ 0xFF, 0xFF },
{ 3, 0 }, { 4, 0 },
{ 5, 2 }, { 2, 0 },
{ 6, 1 }, { 1, 4 },
{ 0, 6 } };
unsigned char step(unsigned char t, int i)
{
if (dka[t].next == 0xFF) return t;
std::cout << i << " - i | " << " XD :) " << dka[t].value << '\n';
return dka[t].next;
}
Если ну очень нужно через массив — что-то типа
unsigned char x = (time[0]<<2)|(time[1]<<1)|time[0];
x = step(x,i);
time[2] = x&1;
time[1] = x&2;
time[0] = x&4;
Собственно, вот и весь код.
Ах, да!
Программа полностью — аналог той, что на https://godbolt.org/z/vMsTWfe4x ...
#include <iostream>
#include <algorithm>
const int numb = 5;
struct DKA
{
int value;
unsigned char next;
} dka[8] = {
{ 0xFF, 0xFF }, { 3, 0 }, { 4, 0 },
{ 5, 2 }, { 2, 0 }, { 6, 1 },
{ 1, 4 }, { 0, 6 } };
unsigned char step(unsigned char t, int i)
{
if (dka[t].next == 0xFF) return t;
std::cout << i << " - i | " << " XD :) " << dka[t].value << '\n';
return dka[t].next;
}
int main()
{
unsigned char time = 0;
for (int h = 0; h < 20; ++h)
{
time = 0x07;
for (int i = 0, z = 0, n = 0; i < 10; ++i, ++n, ++z)
{
std::cout << n << " - n | " << i << " - i | " << " run " << std::endl;
time = step(time,i);
}
}
}