Reducir el número de sentecias "if"

Tengo, como parte de un sketch, dos grupos de 4 variables booleanas (ChA, ChB, ChC y ChD) (RdA, RdB, RdC y RdD) que van tomando, durante el trascurso del programa valores de "true" o "false".
En determinado momento necesito comparar cuantas están en "true" y cuantas en "false" entre las de un grupo y las del otro.

Hecho con sentencias "if" quedaría algo así y funciona correctamente.

if (ChA == true && ChB == false && ChC == false && ChD == false) { // 4 sentencias para detectar un "true" en el primer grupo
   ChCount = 1;
 }
if (ChA == false && ChB == true && ChC == false && ChD == false) {
   ChCount = 1;
 }
if (ChA == false && ChB == false && ChC == true && ChD == false) {
   ChCount = 1;
 }
if (ChA == false && ChB == false && ChC == false && ChD == true) {
   ChCount = 1;
 }


 if (ChA == true && ChB == true && ChC == false && ChD == false) { // 6 sentencias para detectar dos "true" en el primer grupo
   ChCount = 2;
 }
if (ChA == true && ChB == false && ChC == true && ChD == false) {
   ChCount = 2;
 }
// etc, etc......


if (ChA == true && ChB == true && ChC == true && ChD == false) { // otras 4 para detectar tres "true"
   ChCount = 3;
 }
if (ChA == true && ChB == true && ChC == false && ChD == true) {
   ChCount = 3;
 }
// etc, etc.....


if (ChA == true && ChB == true && ChC == true && ChD == true) { // finalmente una sentencia para detectar cuatro "true"
   ChCount = 4;
 }


if (RdA == true && RdB == false && RdC == false && RdD == false) { // todo similar para el segundo grupo
   RdCount = 1;
}

// etc, etc............




 if (ChCount != 0 && RdCount == 0) { // para finalmente comparar ChCount con RdCount
   digitalWrite (ChPin, HIGH);
 }
 if (ChCount == RdCount) {
   digitalWrite (ChPin, LOW);
 }

Lo que implica 30 sentencias "if"

Podría resolverlo de alguna manera con menos líneas de código?

FrankBlack:
Tengo, como parte de un sketch, dos grupos de 4 variables booleanas (ChA, ChB, ChC y ChD) (RdA, RdB, RdC y RdD) que van tomando, durante el trascurso del programa valores de "true" o "false".
En determinado momento necesito comparar cuantas están en "true" y cuantas en "false" entre las de un grupo y las del otro.

Hecho con sentencias "if" quedaría algo así y funciona correctamente.

if (ChA == true && ChB == false && ChC == false && ChD == false) { // 4 sentencias para detectar un "true" en el primer grupo

ChCount = 1;
}
if (ChA == false && ChB == true && ChC == false && ChD == false) {
  ChCount = 1;
}
if (ChA == false && ChB == false && ChC == true && ChD == false) {
  ChCount = 1;
}
if (ChA == false && ChB == false && ChC == false && ChD == true) {
  ChCount = 1;
}

if (ChA == true && ChB == true && ChC == false && ChD == false) { // 6 sentencias para detectar dos "true" en el primer grupo
  ChCount = 2;
}
if (ChA == true && ChB == false && ChC == true && ChD == false) {
  ChCount = 2;
}
// etc, etc......

if (ChA == true && ChB == true && ChC == true && ChD == false) { // otras 4 para detectar tres "true"
  ChCount = 3;
}
if (ChA == true && ChB == true && ChC == false && ChD == true) {
  ChCount = 3;
}
// etc, etc.....

if (ChA == true && ChB == true && ChC == true && ChD == true) { // finalmente una sentencia para detectar cuatro "true"
  ChCount = 4;
}

if (RdA == true && RdB == false && RdC == false && RdD == false) { // todo similar para el segundo grupo
  RdCount = 1;
}

// etc, etc............

if (ChCount != 0 && RdCount == 0) { // para finalmente comparar ChCount con RdCount
  digitalWrite (ChPin, HIGH);
}
if (ChCount == RdCount) {
  digitalWrite (ChPin, LOW);
}





Lo que implica 30 sentencias "if"

Podría resolverlo de alguna manera con menos líneas de código?

No se si lo he entendido bien,tal vez puedes usar dos arrays de booleanos:

bool ChCount[4];
bool RdCount[4];
// Rellenar
for (int cont = 0;cont < 4;cont++){
  ChCount[cont] = true // o false ,se rellena con valores obtenidos...
  RdCount[cont] = false // idem
}
// Comparar 

int totalChCount=0,totalRdCount=0;
for(int cont = 0;cont < 4;cont++){
  if(ChCount[cont] == true) {
    totalChCount ++;
  }
  if(RdCount[cont] == true) {
    totalRdCount ++;
  }
}
 if (totalChCount != 0 && totalRdCount == 0) { // para finalmente comparar ChCount con RdCount
   digitalWrite (ChPin, HIGH);
 }
 if (totalChCount == totalRdCount) {
   digitalWrite (ChPin, LOW);
 }

Gracias jose por tu pronta respuesta

Discúlpame pero no me queda claro. En mi ejemplo "ChCount" y "RdCount" reflejan cuantas de las cuatro variables (ChA, ChB, ChC y ChD) y (RdA, RdB, RdC y RdD) están en "true" respectivamente. Estas variables las necesito (no puedo eliminarlas) y funcionan para diversas partes del código.
Cómo haría para volcar el estado de las mismas al array?

Fácil. Cualquier variable que se trabaja entre funciones, debe declararse globalmente (fuera de cualquier función), o con el modificador static.

Lucario448

Si, las tengo correctamente declaradas y el programa funciona correctamente. Lo que no me queda claro es como volcar el estado "true" o "false" de estas variables (ChA, ChB, etc.........) al array que propone jose.

Repito, el sketch funciona bien, lo único que me gustaría es no tener que utilizar las 30 sentencias "if" que mencioné al principio si existe una manera mas "elegante" para resolverlo.

Entonces consigue los valores de la siguiente manera:

boolean b1 = ChCount[0];
boolean b2 = RdCount[0];

Esos ceros que hay por ahí, serían justamente como la última letra de la variable. En otras palabras:

0 = A
1 = B
2 = C
3 = D

Ejemplo: extraer el valor de RdC:

boolean b1 = RdCount[2];

Extraer el valor de ChB:

boolean b1 = ChCount[1];

Creo que con eso ya captas mi idea.

if (ChA == true && ChB == false && ChC == false && ChD == false) { // 4 sentencias para detectar un "true" en el primer grupo
   ChCount = 1;
 }

yo tengo otra manera de resolverlo.
valor = ChA<<3+ChB<<2+ChC<<1+ChD; // le asigno un peso a cada uno indistinto cual es cual.
en tu primer if tienes
ChA = 1
ChB = 0
ChC = 0
ChD = 0
o sea un 1000 = 8 (base 10)
En cada caso tendrás una respuesta similar.
finalmente armo un switch case

 byte valor = ChA+ChB<<1+ChC<<2+ChD<<3; // le asigno un peso a cada uno indistinto cual es cual.
 switch (valor) {
     case 1,2,4,8: ChCount = 1;
                   break;

     case 9, 12, : ChCount = 2;
                   break;
}

Mucho mas fácil no

surbyte

Si!!! Me gusta tu idea con byte y bitshift, lo probaré.

Gracias a todos.

FrankBlack:
Gracias jose por tu pronta respuesta

Discúlpame pero no me queda claro. En mi ejemplo "ChCount" y "RdCount" reflejan cuantas de las cuatro variables (ChA, ChB, ChC y ChD) y (RdA, RdB, RdC y RdD) están en "true" respectivamente. Estas variables las necesito (no puedo eliminarlas) y funcionan para diversas partes del código.
Cómo haría para volcar el estado de las mismas al array?

el total de true queda almacenado en totalChCount y en totalRdCount.Para guardar valores tendras que hacerlo a pelo puesto que los valores pueden ser diferentes para cada variable:

chCount[0] = true; // o false
chCount[1] = false; // o true
chCount[2] = true;
chCount[3] = false;
// idem para rdCount.

¿Y sencillamente así?

chCount= ChA+ChB+ChC+ChD;

noter:
¿Y sencillamente así?

chCount= ChA+ChB+ChC+ChD;

como nos olvidamos de las constantes tras los nombres....

No entiendo dónde quieres llegar con lo de las constantes, jose.
Lo único que puedo decir es que lo he simulado y funciona. Quedaría hacer lo mismocon rdCount, y la comparación final.

noter:
¿Y sencillamente así?

chCount= ChA+ChB+ChC+ChD;

La solución de noter funciona perfectamente sin mas. No se me hubiera ocurrido sumar así las variables booleanas para recuperar su estado.

Gracias!!

Funciona para tu caso específico porque tus salidas responden a esa situación de suma booleana pero podría mostrarte situaciones en las que no lo haría.
De todos modos es la forma mas simple.

surbyte:
Funciona para tu caso específico porque tus salidas responden a esa situación de suma booleana pero podría mostrarte situaciones en las que no lo haría.
De todos modos es la forma mas simple.

No quise liar más la cuestión, y puse directamente la solución más "práctica", pero surbyte tiene razón. Para resumir, digamos que en C y otros lenguajes 1 es un true lógico, pero true no tiene porqué ser 1 necesariamente, ya que está definido como cualquier valor distinto de cero. Lo que ocurre es que en la práctica se suele asignar 1 a true.
La solución más "purista" pasaría por utilizar operador ternario:

chCount= (ChA?1:0) + (ChB?1:0) + (ChC?1:0) + (ChD?1:0);

Pero en este caso, con la excusa de los recursos limitados de arduino se permite la "chapuza" ;).

noter:
No entiendo dónde quieres llegar con lo de las constantes, jose.
Lo único que puedo decir es que lo he simulado y funciona. Quedaría hacer lo mismocon rdCount, y la comparación final.

que no es un comentario negativo hombre!!! Lo que quise decir precisamente es que tienes razon y que detras del true y del false hay un 1 y un 0....

¡Ah! ¡Entendido!
No había captado bien la dirección de la frase, y pensé que indicabas que se me había pasado algo en la lectura de la consulta, lo que tampoco hubiera sido un comentario negativo, que a todos se nos escapan borrones.

surbyte:
Funciona para tu caso específico porque tus salidas responden a esa situación de suma booleana pero podría mostrarte situaciones en las que no lo haría.
De todos modos es la forma mas simple.

Antes de consultar en el foro estuve buscando y por lo que pude entender, en C no hay forma de recuperar o convertir el estado de una variable booleana (true o false) en un valor (0 o 1) ...... si no entendí mal.

En principio me gustó la idea de surbyte con bitshift y switch/case pero la probé y no funcionó.

No pensé que hacerlo como propuso noter funcionara y lo hizo a la perfección.

A los mas experimentados: Es realmente, como dice noter, una "chapuza".

Saludos a todos!!

FrankBlack:
Antes de consultar en el foro estuve buscando y por lo que pude entender, en C no hay forma de recuperar o convertir el estado de una variable booleana (true o false) en un valor (0 o 1) ...... si no entendí mal.

En principio me gustó la idea de surbyte con bitshift y switch/case pero la probé y no funcionó.

No pensé que hacerlo como propuso noter funcionara y lo hizo a la perfección.

A los mas experimentados: Es realmente, como dice noter, una "chapuza".

Saludos a todos!!

Si que puedes,de hecho internamente creo que es un dato numerico ,pero en algun lugar del core hay definidas unas constantes para que puedan usarse tambien los nombres true y false (tambien para HIGH y LOW ,por ejemplo).De hecho si imprimes un booleano veras un numero y no true o false:

bool estado = true;
void setup() {
  Serial.begin(9600);
  Serial.println(estado);
}
void loop() {
   
}
// Esto tambien vale:
int  estado = true;
void setup() {
  Serial.begin(9600);
  Serial.println(estado);
}

void loop() {
   
}