Crear conjunto de números y prueba de pertenencia

Saludos, por favor miembros del foro, necesito por favor una ayuda, no se códigos usar para poder crear un conjunto de elementos y luego resolver si un elemento X, pertenece o no al conjunto de elementos. Gracias!

Ok y dinos que tiene que ver esto con Arduino?

¡Caramba¡ supuse que se referia al arduino. No pense en ese detalle. Bueno como ya he perdido el tiempo lo publico, quizas le sirva a alguien, si no tiene un arduino lo mismo aprende algo de programacion
Saludos .

Una de las infinitas formas de solucionar tu pregunta @parasitic_art , (si tiees un arduino), podria ser esta:

#define N_elementos 10 // por ejemplo un conjunto de 10 elementos

int conjunto [N_elementos]; // Se crea el conjunto
bool flag; //variable necesaria.

// Este setup vale solo para conexion con el puerto serie
void setup () {
  Serial.begin(9600);
}

void loop () {
  // Llenamos el conjunto
  for (int x = 0; x <= N_elementos - 1; x++) {
    //lo podemos rellenar introduciendo numeros con la consola, leyendo botones o sensores.. etc
    //Para esta prueba lo relleno con numeros aleatorios entre 0 y 254
    conjunto [x] = random (0, 15);
  }
  Serial.println();
  // genero tambien aleatoriamente el numero a comprobar si pertenece al conjunto.
  int y = random (0, 15);
  //   y ahora lo importante la verificacion a ver si esta.
  for (int x = 0; x <= N_elementos - 1; x++) {
    if (conjunto [x] == y) {
      // Se hace lo oportuno,yo lo presento en el monitor serie

      //*************************************************************
      Serial.println ("los elementos del conjunto son.");
      for (int n = 0; n <= N_elementos - 1; n++) {
        Serial.print (conjunto [n]);
        Serial.print (",");
      }
      Serial.println ();
      Serial.print ("El elemento a comprobar es: ");
      Serial.println (y);
      Serial.println ("El elemento si pertenece al conjunto");
      //*************************************************************

      flag = true; // Bandera para posteriores operaciones que le indicara al código que ha habido coincidencia.
      break;// interrumpimos la comprobacióm para no continuar la comprobacion del conjunto inutilmente
    }
  }
  // aqui se ha salido de la comprobacion obramos en consecuencia.
  // comprobamos la variable flag para ver si ha habido o no coincidencia.
  if (flag == true ) { // ha habido coincidencia Y esta en el conjunto ya lo presente en el monitor serial
    flag = false; // a cero para nueva comprobacion
  }
  else { // "y" no esta en el conjunto se obra en consecuencia yo lo presento en el monitor serial.
    Serial.println ("los elementos del conjunto son:");
    for (int n = 0; n <= N_elementos - 1; n++) {
      Serial.print (conjunto [n]);
      Serial.print (",");
    }
    Serial.println ();
    Serial.print ("El elemento a comprobar es: ");
    Serial.println (y);
    Serial.println ("El elemento no pertenece al conjunto");
  }
  delay (10000);// espera de 10 seg para repetir el ejemplo.
}

Creo que esta bien comentada.
Saludos

[Off topic]

@gonpezzi, entiendo que has hecho el código deprisa y corriendo, probando cosas, quitando y poniendo hasta que has logrado que funcione; y así tener un ejemplo práctico de cómo se podría resolver el problema. A riesgo de parecer pedante, y sólo con carácter didáctico, me gustaría comentar un par de cosas sobre el código que has puesto.

Un pequeño detalle respecto a tus bucles. Para ello tomemos como ejemplo este:

  for (int x = 0; x <= N_elementos - 1; x++) {

Aunque para este caso funciona perfectamente y en principio el resultado sería el mismo; es aconsejable que en la condición comprobemos simplemente si es menor, y así no tener que restar uno. De manera que el bucle quedaría tal que así:

  for (int x = 0; x < N_elementos; x++) {

Esta es la forma habitual de encontrarnos un bucle en C/C++ para recorrer todos los valores de cero a N_elementos - 1. Recomiendo esta por tres razones: una es que así el Arduino no tiene que hacer el cálculo de restar uno en cada comparación. Aunque, para este caso, N_elementos es una «constante» (un literal para ser más exactos ya que se ha definido con un #define, aunque lo mismo pasaría si se define como una «variable» de tipo const), así que a la hora de generar el código el valor de N_elementos - 1 es una «constante» y directamente compara con ese resultado de la resta, calculado en tiempo de compilación, ahorrando tiempo en la ejecución ya que no hace la resta ni accedería a la «variable» N_elementos (en el caso de haberse definido con const) al ejecutarse el programa. Es decir, lo de restar uno no «ralentiza» el programa siempre que N_elementos no sea realmente una variable. Lo que he dicho parece un trabalenguas, lo sé, pero es lo que hay.

El segundo motivo es la «legibilidad» del código. Cualquiera, al ver N_elementos - 1 puede creer de entrada que el bucle no está recorriendo todos los elementos, sino justo hasta el elemento N_elementos - 1, teniendo que fijarse bien en que el operador de comparación es el <= y no el <. O dicho de otro modo, ese - 1 mete «ruido» a la hora de «leer» el código por parte de un humano. Lo que puede llevar a confusión, entre otras cosas, porque lo habitual es poner < N_elementos, sin más. Basta para ello buscar en el código del entorno de desarrollo de Arduino y en las librerías que se tengan (en los ficheros, *.cpp o *.ino) y se podrá comprobar cuántas veces se usa el <= en un bucle que empieza de cero. Yo lo he hecho en lo que tengo instalado, y sólo me lo he encontrado en un programa de ejemplo de una librería. Y hay infinidad de bucles con el < que empiezan con cero.

Tercer motivo y el más importante de todos. Formalmente, para manejar tamaños e índices de vectores, arrays, arreglos o matrices (como gusten llamarlo, yo los suelo llamar arrays aunque el inglés no es lo mío), el tipo de variable que se utiliza es size_t. Buscar en Google «qué es size_t en c». Pues bien, este tipo de variable tiene la particularidad de ser un entero sin signo, y esto de «sin signo» es crucial en este caso. Si en lugar de int declaramos la variable x del bucle de tipo size_t:

  for (size_t x = 0; x <= N_elementos - 1; x++) {

Alguien conocedor del size_t, al verlo en la definición de x, ya se predispone a pensar que x es un índice para recorrer un array; y en este caso así es. Esta misma persona de entrada podría creer que se va a recorrer del primero hasta el penúltimo elemento del array (por eso del - 1), pero ahí no está el problema gordo.

Con suerte, dependiendo de cómo esté configurado el compilador y de qué caso se trate, el compilador nos podría dar un aviso tal que así:

aviso: comparison between signed and unsigned integer expressions [-Wsign-compare]
   for (size_t x = 0; x <= N_elementos - 1; x++) {

… Y nosotros ver o no ese aviso. Independientemente de si lo vemos o no: si dejamos el código tal como está y el valor de N_elementos es cero porque se da el caso de que tenemos un array vacío, el valor de N_elementos - 1 bien pudiera ser -1 si N_elementos es con signo. Pero eso da igual porque al comparar x con -1, nos encontramos que estamos comparando un size_t (que es un entero sin signo) con un -1. ¿Y qué pasa en el caso de comparar un entero sin signo con un entero con signo? Pues que el entero con signo se interpreta como un entero sin signo. En el caso del Arduino UNO, que size_t es un entero sin signo de 16 bits, interpreta el -1 como el máximo valor de un entero sin signo de 16 bits, es decir, como un 65535. Así que lo que compara es x <= 65535. Y como x sólo puede tener valores entre 0 y 65535, esta condición se va a cumplir siempre. Por lo tanto, nunca saldrá del bucle.

Prueben este programa:

void setup () {
  Serial.begin(9600);
   int y = 3;
   Serial.println(F("Comienzo"));
   for (size_t x = 0; x <= y - 1; x++) {
     Serial.println(x);
  }
  Serial.println(F("Fin"));
}

void loop() {
}

El compilador me da el aviso:

aviso: comparison between signed and unsigned integer expressions [-Wsign-compare]
    for (size_t x = 0; x <= y - 1; x++) {
                         ^

Pero yo no le hago caso, así que lo que obtengo en el monitor serie es:

Comienzo
0
1
2
Fin

Que es justo lo que quería.
Pero si a la variable y le asigno cero porque no quiero recorrer ningún elemento: cambiamos para ello el 3 por un cero quedando la línea de la definición de la variable y así:

   int y = 0;

Resulta que al ejecutar el programa lo que se obtiene en el monitor serie es algo así:

Comienzo
0
1
2
3
4
5

Y sigue soltando números indefinidamente. En el caso del Arduino UNO, al llegar al 65535 vuelve a 0 y continúa con 1, 2... Ese es el peligro de la comparación x <= y - 1. Sin embargo, si dejamos la declaración int y = 0 y ponemos la comparación x < y:

void setup () {
  Serial.begin(9600);
   int y = 0;
   Serial.println(F("Comienzo"));
   for (size_t x = 0; x < y; x++) {
     Serial.println(x);
  }
  Serial.println(F("Fin"));
}

void loop() {
}

… entonces obtenemos en el monitor serie lo que se esperaba:

Comienzo
Fin

Efectivamente, no muestra ningún elemento. Por ello recomiendo hacer el bucle con el operador < y sin restar uno, si se quiere contar desde cero a n - 1. Es por estos problemas que se pueden dar al comparar enteros sin signo con enteros con signo, por lo que el compilador nos avisa de que estamos haciendo este tipo de comparaciones.

En cuanto al diseño del programa: una cosa que yo no habría hecho, es poner a false la variable flag en esta parte del código:

 if (flag == true ) { // ha habido coincidencia Y esta en el conjunto ya lo presente en el monitor serial
    flag = false; // a cero para nueva comprobación
  }

Porque en una posible ampliación del programa, tal vez volviera a necesitar saber después de ese punto si se había encontrado el elemento en el array. Con lo que tendría que tenerlo en cuenta y seguramente cambiar esa parte del programa. Lo que yo haría es asegurar que flag es falso justo antes de empezar a buscar:

  flag = false;
  //   y ahora lo importante la verificacion a ver si esta.
  for (int x = 0; x <= N_elementos - 1; x++) {

Además, la variable flag no está expresamente inicializada con un valor «conocido» al arrancar el programa. Los Arduinos suelen arrancar con la memoria toda llena de ceros, con lo que a efectos prácticos la variable tendría un valor false por defecto, pero yo aconsejo asegurarse e inicializarla al declararla. A no ser que estemos seguros de que la vamos a establecer inmediatamente de declararla, antes de tomar su valor.

Otra cosa que me hace pensar que el ejemplo se hizo deprisa y corriendo, es que está duplicada la parte que muestra el contenido del array y lo que se busca. Es algo que suelo hacer, cuando se trata de una prueba rápida para ver que tal funciona alguna idea que se me ocurre. Una vez realizada una parte, hago un copy+paste de ella y la duplico en otro lado con ligeras modificaciones o a veces la dejo tal cual. En este caso, simplemente basta con quitar el mostrar el array dentro de la búsqueda y mostrarlo siempre después del bucle de búsqueda. Así se deja para después de la búsqueda lo que se ha de hacer en cada caso.

Resumiendo, seguramente el código de ejemplo yo lo habría hecho algo más parecido a esto:

#define N_elementos 10 // por ejemplo un conjunto de 10 elementos

int conjunto[N_elementos]; // Se crea el conjunto
bool flag = false; // variable necesaria que nos ayuda a saber si el elemento se encuentra en el conjunto

// Este setup vale solo para conexion con el puerto serie
void setup () {
  Serial.begin(9600);
}

void loop () {
  // Llenamos el conjunto
  for (size_t x = 0; x < N_elementos; x++) {
    //lo podemos rellenar introduciendo numeros con la consola, leyendo botones o sensores.. etc
    //Para esta prueba lo relleno con numeros aleatorios entre 0 y 254
    conjunto[x] = random (0, 15);
  }
  Serial.println();
  // genero tambien aleatoriamente el numero a comprobar si pertenece al conjunto.
  int y = random (0, 15);
  flag = false; // Inicialmente no hemos encontrado el valor
  //   y ahora lo importante la verificacion a ver si esta.
  for (size_t x = 0; x < N_elementos; x++) {
    if (conjunto[x] == y) {
      flag = true; // Bandera para posteriores operaciones que le indicara al código que ha habido coincidencia.
      break;// interrumpimos la comprobacióm para no continuar la comprobacion del conjunto inutilmente
    }
  }
  // aqui se ha salido de la comprobacion
  //*************************************************************
  Serial.println ("los elementos del conjunto son.");
  for (size_t n = 0; n < N_elementos; n++) {
    if (n > 0) {
      Serial.print (","); // Ponemos una coma para separar los elementos si no estamos mostrando el primero
    }
    Serial.print (conjunto[n]);
  }
  Serial.println ();
  Serial.print ("El elemento a comprobar es: ");
  Serial.println (y);
  //*************************************************************
  // comprobamos la variable flag para ver si ha habido o no coincidencia.
  if (flag == true ) { // ha habido coincidencia Y esta en el conjunto ya lo presente en el monitor serial
    // Se hace lo oportuno,yo lo presento en el monitor serie
    Serial.println ("El elemento sí pertenece al conjunto");
  }
  else { // "y" no esta en el conjunto se obra en consecuencia yo lo presento en el monitor serial.
    Serial.println ("El elemento no pertenece al conjunto");
  }
  delay (10000);// espera de 10 seg para repetir el ejemplo.
}

Como bien dijo @gonpezzi, hay infinitas formas de hacer un programa. Todo esto lo he dicho desde mi punto de vista y experiencia. Con la intención de informar y formar a quienes quieran aprender de mis errores. Aprovechando el ejemplo de código que ha puesto @gonpezzi. Que, como ya he dicho más de una vez, seguramente lo ha hecho deprisa y corriendo. Pero que sirve perfectamente como ejemplo para dar una idea de cómo solucionar lo que se consulta. Así como una excusa para que yo haga un off topic.

1 Like