Foros del Web » Programación para mayores de 30 ;) » C/C++ »

[SOLUCIONADO] arreglos y sus elementos repetidos

Estas en el tema de arreglos y sus elementos repetidos en el foro de C/C++ en Foros del Web. sea un arreglo entero int A[8] ={2,4,7,2,3,4,7,7} nos debe indicar en orden sin repetir los elementos: el elemento 2 se repite 2 veces el elemento ...
  #1 (permalink)  
Antiguo 06/04/2015, 02:08
 
Fecha de Ingreso: abril-2015
Mensajes: 8
Antigüedad: 9 años
Puntos: 0
arreglos y sus elementos repetidos

sea un arreglo entero
int A[8] ={2,4,7,2,3,4,7,7}

nos debe indicar en orden sin repetir los elementos:
el elemento 2 se repite 2 veces
el elemento 4 se repite 2 veces
el elemento 7 se repite 3 veces
el elemento 3 se repite 1 veces

quien lo intenta.....saludos
  #2 (permalink)  
Antiguo 06/04/2015, 02:30
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 6 meses
Puntos: 204
Respuesta: arreglos y sus elementos repetidos

No nos tomes por tontos... eso "no se intenta" o se hace o no se hace... otra cosa es que tu no sepas hacerlo e intentes que te hagamos la tarea.

Ponte a hacerlo porque, en caso contrario, no vas a aprender en la vida. Si al hacerlo te aparecen dudas, lo cual sería totalmente lógico, entonces vienes y preguntas tus dudas... que gustosamente te intentaremos solucionar.

Un saludo.
  #3 (permalink)  
Antiguo 06/04/2015, 03:14
 
Fecha de Ingreso: abril-2015
Mensajes: 8
Antigüedad: 9 años
Puntos: 0
Respuesta: arreglos y sus elementos repetidos

Cita:
Iniciado por JarolGarcia Ver Mensaje
sea un arreglo entero
int A[8] ={2,4,7,2,3,4,7,7}

nos debe indicar en orden sin repetir los elementos:
el elemento 2 se repite 2 veces
el elemento 4 se repite 2 veces
el elemento 7 se repite 3 veces
el elemento 3 se repite 1 veces

quien lo intenta.....saludos
.......lo que quiero decir es:

#include<fstream.h>
#include<conio.h>
void main()

{
int A[8],i,j,cont=0;
A[8] ={2,4,7,2,3,4,7,7}
cout<<"\n";
for(i=0;i<N;i++){
for(j=0;j<N;j++){
if(a[i]==a[j])
cont++;
}
cout<<"el elemento "<<a[i]<<" se repite "<<cont<<" veces\n";
cont=0;
}
getch();
}

el problema es que me vota asi por ejemplo A[8] ={2,4,7,2,3,4,7,7}
2 se repite 2 veces
4 se repite 2 veces
7 se repite 3 veces
2 se repite 2 veces
3 se repite 1 veces
4 se repite 2 veces
7 se repite 3 veces
7 se repite 3 veces
pero yo quiero que me vote simplemente asi
2 se repite 2 veces
4 se repite 2 veces
7 se repite 3 veces
3 se repite 1 veces
  #4 (permalink)  
Antiguo 06/04/2015, 03:41
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 6 meses
Puntos: 204
Respuesta: arreglos y sus elementos repetidos

Lo primero, intenta poner ejemplos que compilen. El código que has puesto tiene bastantes errores: variables no declaradas, falta un punto y coma y los includes están mal. Además de eso, es importante decorar el código con las etiquetas "HighLight", para que sea legible... también es bastante importante tabular el código correctamente... esto último no se si lo has hecho o no porque tal y como está el código no se puede saber, pero lo pongo por si acaso.

Hablando de tu problema: Dado que te piden que no repitas la salida, no tiene sentido que, para cada número, recorras el vector desde el principio contando apariciones. Más bien deberías:

1. Para cada número buscas coincidencias en posiciones anteriores:
1a. Si existen pasas al siguiente número puesto que este ya está procesado
1b. Si no se han encontrado, buscas y cuentas las coincidencias que hay en posiciones siguientes... una vez has terminado, muestras el mensaje


Código C++:
Ver original
  1. #include<iostream>
  2.  
  3. int main()
  4. {
  5.   int cont, pasar;
  6.   int i, j;
  7.  
  8.   int a[] = {2, 4, 7, 2, 3, 4, 7, 7};
  9.   const int N = sizeof( a ) / sizeof( int );
  10.  
  11.   std::cout << "\n";
  12.   for ( i = 0; i < N; i++ )
  13.   {
  14.     pasar = 0;
  15.     for ( j = i; j-- && !pasar; )
  16.       pasar = a[i] == a[j];
  17.  
  18.     if( !pasar )
  19.     {
  20.       for( j=i, cont=0; j < N; ++j )
  21.         cont += a[i] == a[j];
  22.  
  23.       std::cout << "el elemento " << a[i] << " se repite " << cont << " veces\n";
  24.     }
  25.   }
  26. }
  #5 (permalink)  
Antiguo 06/04/2015, 12:31
lareto
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: arreglos y sus elementos repetidos

No quiero complicarle la vida a JarolGarcia con una versión más compleja que la que pueda asimilar, pero me parece que puede resultar interesante hacer una comparación entre una solución relativamente simple y artesanal, en estilo C (para lo que tomo como ejemplo y acomodando un poco la respuesta de eferion), y otra en estilo C++.

Yo creo que el estilo C++ tiene una ventaja inmediata: es mucho más fácil pensar en una solución y esa solución es muy fácil de hacer eficiente, mientras que la solución en estilo C puede no ser difícil de pergeniar, pero es más difícil de hacer eficiente o, por lo menos, se necesita bastante más esfuerzo y reinventar varios paraguas para conseguir una solución equivalente. Mi idea es que para obtener una solución eficiente en C++ no hace falta ser demasiado inteligente, sólo estudiar un poco más.

Va el ejemplo de comparación, que espero pueda servirle a alguien.

Para el que quiera compilar y ejecutar el programa, va a necesitar un compilador conforme con el estándar C++11 y un poco de paciencia, porque la prueba así como está en mi máquina se demora casi un minuto entero.

Código C++:
Ver original
  1. #include <iostream>
  2. #include <algorithm>
  3. #include <utility>
  4. #include <unordered_map>
  5. #include <chrono>
  6. #include <iomanip>
  7. #include <cstdlib>
  8.  
  9.  
  10. std::unordered_map<int, int> estilo_cpp(int N)
  11. {
  12.     std::unordered_map<int, int> m;  // las funciones devuelven un map para
  13.                                      // no tener que mostrar con cout
  14.                                      // los miles de valores
  15.  
  16.  
  17.     std::minstd_rand0 generator;     // llena un vector con elementos al azar
  18.  
  19.     std::vector<int> v;
  20.     v.reserve(N);
  21.     for(int i=0; i<N; ++i) {
  22.         v.push_back(generator()%N);
  23.     }
  24.     std::sort(std::begin(v), std::end(v));  // comienza el procese real
  25.  
  26.     int cont = 0;
  27.  
  28.     for(auto i=std::begin(v), j=std::end(v); i!=j; i+=cont) {
  29.         auto rango = std::equal_range(i, j, *i);
  30.         cont = std::distance(rango.first, rango.second);
  31.  
  32.         m[*i] = cont;
  33.     }
  34.  
  35.     return m;
  36. }
  37.  
  38.  
  39. std::unordered_map<int, int> estilo_c(int N)
  40. {
  41.     int cont, pasar;
  42.     int i, j;
  43.     std::unordered_map<int, int> m;  // lo mismo que en la función de arriba
  44.  
  45.     std::minstd_rand0 generator;
  46.  
  47.     int* a = new int[N];
  48.     for(int i=0; i<N; ++i) {
  49.         a[i] = generator()%N;     // llena el array con valores al azar
  50.     }
  51.  
  52.     for ( i = 0; i < N; i++ ) {   // comienza el proceso real
  53.         pasar = 0;
  54.         for ( j = i; j-- && !pasar; )
  55.             pasar = a[i] == a[j];
  56.  
  57.         if( !pasar ) {
  58.             for( j=i, cont=0; j < N; ++j )
  59.                 cont += a[i] == a[j];
  60.  
  61.             m[i] = cont;
  62.         }
  63.     }
  64.  
  65.     delete[] a;
  66.     return m;
  67. }
  68.  
  69.  
  70. int main()
  71. {
  72.     using namespace std::chrono;
  73.     steady_clock::time_point t1;
  74.     duration<double> demora1, demora2;
  75.     std::unordered_map<int, int> m1, m2;
  76.  
  77.     for(int n=1; n<300000; n*=2) {
  78.         std::cout << "n = " << n << '\n';
  79.  
  80.         t1 = steady_clock::now();
  81.         m1 = estilo_c(n);
  82.         demora1 = duration_cast<duration<double>>(steady_clock::now() - t1);
  83.  
  84.         t1 = steady_clock::now();
  85.         m2 = estilo_cpp(n);
  86.         demora2 = duration_cast<duration<double>>(steady_clock::now()- t1);
  87.  
  88.         std::cout << std::setprecision(6) << std::fixed;
  89.         std::cout << "estilo_c()  : " << demora1.count() << " segundos\n";
  90.         std::cout << "estilo_cpp(): " << demora2.count() << " segundos\n";
  91.         std::cout << "diferencia relativa = " << (demora1.count()-demora2.count())/demora2.count() * 100 << " %\n" << std::endl;
  92.         // a partir de 128 elementos las diferencias relativas aumentan proporcionalmente con n.
  93.         // más allá de 32.000 elementos, estilo_c() se hace inviable.
  94.     }
  95.  
  96. }

Última edición por lareto; 06/04/2015 a las 12:41
  #6 (permalink)  
Antiguo 06/04/2015, 15:25
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 6 meses
Puntos: 204
Respuesta: arreglos y sus elementos repetidos

Cita:
Iniciado por lareto Ver Mensaje
No quiero complicarle la vida a JarolGarcia con una versión más compleja que la que pueda asimilar, pero me parece que puede resultar interesante hacer una comparación entre una solución relativamente simple y artesanal, en estilo C (para lo que tomo como ejemplo y acomodando un poco la respuesta de eferion), y otra en estilo C++.
No era mi intención complicarle la vida... explico los pasos y pongo un código que, si bien funciona, no es algo típico que alguien pueda limitarse a copiar y pegar... tiene detalles que cantan.

La idea es que tenga un ejemplo que le sirva de base... pero al final tiene que ser él el que elabore una solución funcional.

Cita:
Iniciado por lareto Ver Mensaje
Yo creo que el estilo C++ tiene una ventaja inmediata: es mucho más fácil pensar en una solución y esa solución es muy fácil de hacer eficiente, mientras que la solución en estilo C puede no ser difícil de pergeniar, pero es más difícil de hacer eficiente o, por lo menos, se necesita bastante más esfuerzo y reinventar varios paraguas para conseguir una solución equivalente. Mi idea es que para obtener una solución eficiente en C++ no hace falta ser demasiado inteligente, sólo estudiar un poco más.
Coincido contigo en parte.

En C se pueden conseguir soluciones mucho más eficientes que C++... pero ello te obliga a reinventar la rueda varias veces, lo cual pocas veces compensa, hasta aquí conforme.

Sin embargo eso de que para programar C++ no hace falta ser demasiado inteligente... es distinto. Creo que para controlar C++ tienes que pensar de forma más abstracta a como se hace con C, pero de ahí a insinuar que programar en C++ es más fácil...

Cita:
Iniciado por lareto Ver Mensaje
Va el ejemplo de comparación, que espero pueda servirle a alguien.
He optimizado un poco tu función C++, lo cual refuerza la teoría de que con un buen diseño en C++ es más fácil aplicar optimizaciones (esta nueva versión es un 25% más rápida):

Código C++:
Ver original
  1. std::unordered_map<int, int> estilo_cpp(int N)
  2. {
  3.     std::unordered_map<int, int> m;  // las funciones devuelven un map para
  4.                                      // no tener que mostrar con cout
  5.                                      // los miles de valores
  6.  
  7.  
  8.     std::minstd_rand0 generator;     // llena un vector con elementos al azar
  9.  
  10.     std::vector<int> v;
  11.     v.reserve(N);
  12.     for(int i=0; i<N; ++i) {
  13.         v.push_back(generator()%N);
  14.     }
  15.  
  16.     std::map< int, int > temp;
  17.     for( auto it = m.begin( ); it != m.end( ); ++it )
  18.       temp[ it->first ]++;
  19.  
  20.     for( auto it = temp.begin( ); it != temp.end( ); ++it )
  21.       m[it->first] = it->second;
  22.  
  23.     return m;
  24. }

Un saludo.
  #7 (permalink)  
Antiguo 06/04/2015, 16:28
lareto
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: arreglos y sus elementos repetidos

Cita:
Iniciado por eferion Ver Mensaje
Coincido contigo en parte.

En C se pueden conseguir soluciones mucho más eficientes que C++...
Bueno, no, yo no dije eso.
Algunas veces se podrán conseguir soluciones más eficientes en C y otras veces no. Incluso creo que es más probable obtener soluciones más eficientes en C++ que en C.

Cita:
...pero de ahí a insinuar que programar en C++ es más fácil...
Otra vez discrepamos; yo no quise insinuar que programar en C++ es más fácil que programar en C, estoy seguro que es más fácil.
Cita:
He optimizado un poco tu función C++... (esta nueva versión es un 25% más rápida)
Esta nueva versión es más rápida porque no hace nada. Pero de todos modos, si al corregirla conservas la idea, no será más rápida; las dos son de una complejidad O(log N) pero la "optimizada" tendría el doble de pendiente, demoraría el doble que mi versión.
  #8 (permalink)  
Antiguo 07/04/2015, 00:39
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 6 meses
Puntos: 204
Respuesta: arreglos y sus elementos repetidos

Cita:
Iniciado por lareto Ver Mensaje
Esta nueva versión es más rápida porque no hace nada. Pero de todos modos, si al corregirla conservas la idea, no será más rápida; las dos son de una complejidad O(log N) pero la "optimizada" tendría el doble de pendiente, demoraría el doble que mi versión.
Si y no... Es cierto que la versión que he puesto al final no funciona... cosas de montar el código directamente en el foro... pero no pasa nada, pongo un ejemplo completo, compilado y probado... ahora si puedo compilar :)

Código C++:
Ver original
  1. std::unordered_map<int, int> estilo_cpp1(std::vector< int > v)
  2. {
  3.     std::unordered_map<int, int> m;  // las funciones devuelven un map para
  4.                                      // no tener que mostrar con cout
  5.                                      // los miles de valores
  6.  
  7.  
  8.  
  9.     std::sort(std::begin(v), std::end(v));  // comienza el procese real
  10.  
  11.     int cont = 0;
  12.  
  13.     for(auto i=std::begin(v), j=std::end(v); i!=j; i+=cont) {
  14.         auto rango = std::equal_range(i, j, *i);
  15.         cont = std::distance(rango.first, rango.second);
  16.  
  17.         m[*i] = cont;
  18.     }
  19.  
  20.     return m;
  21. }
  22.  
  23. std::unordered_map<int, int> estilo_cpp2(std::vector< int > v)
  24. {
  25.     std::unordered_map<int, int> m;  // las funciones devuelven un map para
  26.                                      // no tener que mostrar con cout
  27.                                      // los miles de valores
  28.  
  29.     std::sort(std::begin(v), std::end(v));  // comienza el procese real
  30.     for( auto it = v.begin( ); it != v.end( ); ++it )
  31.       m[ *it ]++;
  32.  
  33.     return m;
  34. }
  35.  
  36. int main()
  37. {
  38.   using namespace std::chrono;
  39.   steady_clock::time_point t1;
  40.   duration<double> demora1, demora2;
  41.   std::unordered_map<int, int> m1, m2;
  42.  
  43.   std::minstd_rand0 generator;     // llena un vector con elementos al azar
  44.  
  45.   for(int n=1; n<30000000; n*=2)
  46.   {
  47.     std::cout << "n = " << n << '\n';
  48.     std::vector<int> v;
  49.     v.reserve( n );
  50.     for ( int i = 0; i < n; ++i )
  51.     v.push_back ( generator() % n );
  52.  
  53.     t1 = steady_clock::now();
  54.     m1 = estilo_cpp1(v);
  55.     demora1 = duration_cast<duration<double>>(steady_clock::now() - t1);
  56.  
  57.     t1 = steady_clock::now();
  58.     m2 = estilo_cpp2(v);
  59.     demora2 = duration_cast<duration<double>>(steady_clock::now()- t1);
  60.  
  61.     std::cout << std::setprecision(6) << std::fixed;
  62.     std::cout << "estilo_cpp1(): " << demora1.count() << " segundos\n";
  63.     std::cout << "estilo_cpp2(): " << demora2.count() << " segundos\n";
  64.     std::cout << "diferencia relativa = " << (demora1.count()-demora2.count())/demora2.count() * 100 << " %\n" << std::endl;
  65.   }
  66. }

...conseguimos exactamente la misma salida y con una mejora del rendimiento que varía... con pocos elementos he llegado a una mejora cercana al 2000% (poco fiable son procesos muy rápidos y cualquier interrupción dispara los tiempos) pero con cifras más altas la mejora se situa en torno al 12% - 15%.

Por cierto, he sacado la generación del vector fuera de las funciones por dos motivos:

1. Su generación no afecta a la medida de tiempos (medidas más precisas)
2. Ambas funciones van a trabajar con la misma colección de datos.

Sobre el motivo de usar el mapa... pues no se, como no podía probarlo tampoco tenía muy claro el impacto que podía tener con respecto a tu versión... esta mañana lo he probado y efectivamente rueda un 20% más lento (aprox.), cosas del directo.

Un saludo
  #9 (permalink)  
Antiguo 07/04/2015, 05:36
lareto
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: arreglos y sus elementos repetidos

Me cito a mí mismo...
Cita:
Yo creo que el estilo C++ tiene una ventaja inmediata: es mucho más fácil pensar en una solución y esa solución es muy fácil de hacer eficiente, mientras que la solución en estilo C puede no ser difícil de pergeniar, pero es más difícil de hacer eficiente o, por lo menos, se necesita bastante más esfuerzo y reinventar varios paraguas para conseguir una solución equivalente. Mi idea es que para obtener una solución eficiente en C++ no hace falta ser demasiado inteligente, sólo estudiar un poco más.
Y me cito textualmente por dos motivos; el primero es para plantarme en la cara que puse pergeniar, así, con 'ni', y el segundo es para insistir:

- Idear una solución C++ suele ser más fácil que idear una solución C.

- Hacer eficiente (que no es lo mismo que optimizar) una solución C++ es más fácil que hacer eficiente una solución C.

El ejemplo que puse tenía la intención de comparar una primera solución C con una primera solución C++. Y dejando correr el ejemplo, puede verse que mientras que esa primera solución C es de grado O(N log N), su homóloga C++ es de grado O(log N). Entonces, optimizar la primera no sólo es más difícil, sino que lo prudente sería buscarse otra, con lo que se duplica el esfuerzo sólo para llegar al mismo lugar donde nos dejaba la segunda.

Otro tema es el de las optimizaciones, que vienen después de haber elegido los algoritmos y de tener todo funcionando correctamente, y, como su nombre indica, se busca mejorar lo hecho.

Y es en este asunto en donde se ha embarullado eferion.

Cita:
...conseguimos exactamente la misma salida y con una mejora del rendimiento que varía...
No todavía.

Estoy seguro que mi primera versión puede optimizarse, y sí, estoy de acuerdo con que (si ya no es necesaria la comparación con la versión original de estilo C) es mejor separar la generación de datos y la función responsable del cómputo; pero si tu versión anterior trabajaba para no hacer nada, esta otra trabaja para dejar todo como está.
  #10 (permalink)  
Antiguo 07/04/2015, 06:52
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 6 meses
Puntos: 204
Respuesta: arreglos y sus elementos repetidos

Cita:
Iniciado por lareto Ver Mensaje
Estoy seguro que mi primera versión puede optimizarse
Seguro puedes estar... la versión que te he puesto es el ejemplo.
Cita:
Iniciado por lareto Ver Mensaje
Idear una solución C++ suele ser más fácil que idear una solución C
totalmente de acuerdo. Es un lenguaje de más alto nivel y eso facilita las cosas.. Siguiendo la misma regla de 3, hacer lo mismo en C# o en Java suele ser muchísimo más facil que hacerlo en C++... más fácil con menos errores y en menos tiempo.

Cita:
Iniciado por lareto Ver Mensaje
pero si tu versión anterior trabajaba para no hacer nada, esta otra trabaja para dejar todo como está.
La versión que he puesto genera exactamente la misma salida que la versión que tu has puesto... es decir, ante una misma entrada generan una misma salida. Si mi versión trabaja para dejar todo como está la tuya también.

Tu has tirado de std::distance para calcular el número de items repetidos y yo he ido acumulando las repeticiones en el mapa directamente... si dejase las cosas como están las salidas de ambas funciones serían diferentes.
  #11 (permalink)  
Antiguo 07/04/2015, 17:01
lareto
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: arreglos y sus elementos repetidos

No veo cómo un cambio trivial a un programa trivial, y que no produce ninguna diferencia, puede provocar tanta excitación.

Y, ah, por cierto, este es mi programa trivial, el tuyo es es el de más arriba, ¿recuerdas? Aunque puedo copiarlo aquí también:
Código:
#include<iostream>
 
int main()
{
  int cont, pasar;
  int i, j;
 
  int a[] = {2, 4, 7, 2, 3, 4, 7, 7};
  const int N = sizeof( a ) / sizeof( int );
 
  std::cout << "\n";
  for ( i = 0; i < N; i++ )
  {
    pasar = 0;
    for ( j = i; j-- && !pasar; )
      pasar = a[i] == a[j];
 
    if( !pasar )
    {
      for( j=i, cont=0; j < N; ++j )
        cont += a[i] == a[j];
 
      std::cout << "el elemento " << a[i] << " se repite " << cont << " veces\n";
    }
  }
}
Incluso, mira, en esta dirección puedes mostrarnos cómo queda todo más fácil y eficiente en C# y en Java si te apetece:
http://rextester.com/runcode

Última edición por lareto; 07/04/2015 a las 19:25
  #12 (permalink)  
Antiguo 10/04/2015, 13:52
 
Fecha de Ingreso: abril-2015
Mensajes: 8
Antigüedad: 9 años
Puntos: 0
Respuesta: arreglos y sus elementos repetidos

encontré la manera

Código:
#include <stdio.h>
#include <string.h>

int main()
{
   int arrayPrincipal[10]={1,2,3,7,4,1,7,1,2,1};
   int aux[10];
   int x,y,pos,size=10,contador;

   for(x=0;x<size;x++)
   {
      pos=0;
      contador=0;
      for(y=0;y<size;y++)
      {
         if(arrayPrincipal[x] != arrayPrincipal[y]){
            aux[pos++]=arrayPrincipal[y];
         }else{
            contador++;
         }
      }

      printf("El numero %d se repite %d veces\n",arrayPrincipal[x],contador);
      size-=contador;
     for(int u=0;u<size;u++){
     arrayPrincipal[u]=aux[u];
    }
    x--;
   }
   return 0;
}

Última edición por JarolGarcia; 10/04/2015 a las 13:58
  #13 (permalink)  
Antiguo 11/04/2015, 16:17
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 2 meses
Puntos: 3
Respuesta: arreglos y sus elementos repetidos

perdon, me confundi.

Última edición por aguml; 11/04/2015 a las 16:43

Etiquetas: arreglo, arreglos, elementos, int, repetidos
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 20:54.