elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado:


  Mostrar Mensajes
Páginas: 1 2 3 4 5 6 [7] 8 9 10 11
61  Programación / Programación C/C++ / Re: Sumar los elementos de un vector con DyV en: 18 Diciembre 2018, 10:15 am
...Con ese punto medio hice la forma propuesta por YreX-DwX, quedando muy similar a como estaba el programa al inicio, lo dejo abajo por las dudas:
Código:
...
int sumaDyV( int *vec, int inicio, int fin ) {
    if( inicio == fin ) {
        return vec[inicio];
    }
    if ( (fin - inicio) == 1)
  {
        return sumaDyV(vec, inicio, inicio) + sumaDyV( vec, fin, fin);
    }
    else {
        return sumaDyV(vec, inicio, (inicio+fin)/2) + sumaDyV( vec, ((inicio+fin)/2)+1, fin);
    }
}
Voy a tener en cuenta usar el [i,...,j) con if ( i == j )  return 0; para subsegmentos.
Gracias!

A ti!
No obstante, ahora el caso de  YreX-DwX es redundante, no es necesario. De tu forma, si

Código:
( (fin - inicio) == 1) 

Entonces el tamaño del subsegmento es 2, y consecuentemente en el caso recursivo se partirá en dos submitades. Sigue valiendo el cálculo del punto medio del caso general.

Una razón más para emplear el convenio  [i..j) !

62  Programación / Programación C/C++ / Re: Sumar los elementos de un vector con DyV en: 17 Diciembre 2018, 21:12 pm
Para que funcione tienes que distinguir 3 casos (te falta 1):
- Si inicio y fin son iguales -> return v[inicio]
- Si la diferencia entre inicio y fin es 1 -> return sumaDyV(v, inicio, inicio) + sumaDyV(v, fin, fin)
- Si la diferencia es mayor que 1 -> return sumaDyV(v, inicio, fin/2) + return sumaDyV(v, fin/2+1, fin)
Suerte. :-X
Hola. Creo que ese no es el problema.

El problema es que no está computando bien el punto medio.

Código
  1. int sumaDyV( int *vec, int inicio, int fin ) {
  2.    if( inicio == fin ) {
  3.        return vec[inicio];
  4.    }
  5.    const int half = (inicio + fin)/2;
  6.    return sumaDyV(vec, inicio, half) + sumaDyV( vec, half +1, fin);
  7. }

Ahora queda:

Código:
Dimension del vector: 5

Numero en la posicion 0: 2

Numero en la posicion 1: 2

Numero en la posicion 2: 2

Numero en la posicion 3: 2

Numero en la posicion 4: 3

Resultado: 11

Por cierto, que te recomiendo usar para subsegmentos el convenio [i..j) , semiabierto por la derecha, en vez de [i..j-1], cerrado por los dos lados, que es el que usas. Es más inmediato a la lectura de C, y permite valorar la longitud del segmento con la simple diferencia (j-i), contra las más compleja ((j-1)-i+1).
(Además, es legítimo preguntar por la suma de ls elements del vector vacío)


Lo pongo según mi versión:
Código
  1. #include <iostream>
  2. using namespace std;
  3. int sumaDyV( const int *vec, const int inicio, const int fin );
  4.  
  5. int main() {
  6.    int N;
  7.    cin>>N;
  8.    int *vec = new int[N];
  9.    for(int i = 0; i<N;i++)   cin>>vec[i];
  10.    cout<<sumaDyV( vec, 0, N )<< endl;
  11.    delete[] vec;
  12.    return 0;
  13. }
  14.  
  15. // Inmersion:
  16. // P :   0 <= i <= j <= N
  17. // Q :   n = \sum k : i<= k < j : V[k];
  18. int sumaDyV( const int *V, const int i, const int j ) {
  19.    if ( i == j )  return 0;
  20.    if ((j - i) == 1)  return V[i];    
  21.    const int half = (i + j)/2;
  22.    return sumaDyV(V, i, half) + sumaDyV( V, half, j);
  23. }


Ah! yo no me preocuparía de hacer "friendly" la entrada - salida... No están pedidiendo una aplicación, solo la exhibición de un algoritmo!
63  Programación / Programación C/C++ / Re: Ayuda C++ suma de digitos hasta un solo digito. en: 13 Noviembre 2018, 17:56 pm


Dejo un ejemplo funcionan con metodo RECURSIVO. Lo deje con comentarios para puedas seguir un poco el codigo.

Código
  1. ...
  2. int suma_de_digitos_recursiva(int numero) {
  3. char temporal[20] = {0};
  4. int suma = 0;
  5. int len,i;
  6. sprintf(temporal,"%i",numero); //Aqui "copiamos" el numero a una cadena de texto para poder iterar facilmente sobre cada digitio individual del numero
  7. printf("Prosesando el numero %s\n",temporal);
  8. len = strlen(temporal); //Sacamos la longitud del numero
  9. if(len == 1) { //Si la longitud del numero es solo de uno ya no hacemos nada retornamos el numero
  10. printf("Finalizamos, el numero tiene un solo digito\n");
  11. return numero;
  12. }
  13. else { //Si la longitud es mayor que uno sumamos los digitos individuales
  14. i = 0;
  15. while(i < len) {
  16. suma += temporal[i] - '0';
  17. i++;
  18. }
  19. printf("La suma es %i\n",suma);
  20. return suma_de_digitos_recursiva(suma);
  21. }
  22. }
  23.  
...

2 COMENTARIOS:
  • Aunque la solución sea correcta, parece que la función recursiva tiene a su vez, un bucle, que podriamos computar también recursivamente
  • Yo pienso que los protocolos de entrada-salida hay que dejarlos al margen de las funciones de cómputo. Simplemente, ayuda a separar la I/0 del procesamiento


Propongo esta:

Código
  1. /*
  2.  
  3. NOTE: In this context, we can safely take log(0)=0 as an extension of ordinary log, for which 0 is undefined
  4.  
  5.  
  6.  P : N >= 0
  7.  fun sumDigits(int N) dev s
  8.  Q : s = \sum i : 0 <= i <= log(N) : (N/10^i)%10
  9.  
  10.  INMERSION
  11.  
  12.  FINAL APPROACH
  13.  
  14.  P' = P and 0<= n <= N and ac = \sum i : 0 <= i <= log(N/n) : (N/10^i)%10
  15.  fun sumDigits(int n,int ac) dev s
  16.  Q' = Q[N/n]
  17.  
  18.  Init call: n=N ac=0
  19.  
  20.  case n=0 : return ac
  21.  case n>0 : return sumDigits(n/10,ac+n%10)
  22.  
  23.  
  24. */
  25. #include <iostream>
  26. using namespace std;
  27. #define MAX 10000
  28.  
  29. int sumDigitsG(const int n, const int ac)
  30. {
  31.  if (n) return sumDigitsG(n/10,ac+n%10);
  32.  return ac;
  33. }
  34.  
  35. int sumDigits(const int N)
  36. {
  37.  return sumDigitsG(N,0);
  38. }
  39.  
  40. /* Formalization for solveG omitted */
  41.  
  42. void solveG(const int N,int V[], int &num)
  43. {
  44.  if (N>=10) {
  45.    V[num++]=sumDigits(N);
  46.    solveG(V[num-1],V,num);
  47.    return;
  48.  }
  49.  return;
  50. }
  51.  
  52.  
  53.  
  54. int main(int argc, char **args)
  55. {
  56.  int V[MAX];
  57.  int N;
  58.  for ( ; cin >> N ; )
  59.    {
  60.      int num=0;
  61.      solveG(N,V,num);
  62.      for (int n=0; n<num ;n++)  cout << V[n] << " " ;
  63.      cout << endl;
  64.    }
  65. }
  66.  
  67.  


Y algunos casos de prueba. Se da un número, y el programa da el vector con la suma de los digitos de ese, del que se obtiene... hasta llegar a una cigra
Código:
 g++ sumDigits2.cc -o main && ./main
13
4
1456
16 7
177777
36 9
64  Programación / Programación C/C++ / Re: Duda con contador de palabras en C para principiantes en: 25 Octubre 2018, 16:21 pm
Estos son algunos de los casos de prueba que utilicé, y las salidas que obtuve con mi código:


....

En todo caso, no me parece que sea una solución incorrecta para un ejercicio de nivel básico.

Mis excusas. He probado ya tus códigos y son como dices. Aunque la estrategia de "existeLetra" como flag de comienzo no la entendía.
65  Programación / Programación C/C++ / Re: Duda con contador de palabras en C para principiantes en: 24 Octubre 2018, 10:55 am
Hola dresden, gracias por responder. Así aprenderé algo también.

Mi razonamiento al estudiar tu código, sin ejecutarlo, fue el siguiente :

  • creo (no estoy seguro), que scanf no procesa el espacio ' ' como carácter, por lo que nunca evaluará espacios en la cadena.. Suponiendo que si, entonces
  • o  bien isalpha(' ') es true, en cuyo caso existeLetra es true, y es evaluado por la parte positiva del primer condicional... En ese caso, la traza '    .' (5 espacios y un punto) da al menos 5 palabras, pues incrementa nPalabras 5 veces. Es esto correcto?
  • o bien isalpha(' ') es false,en cuyo caso  nunca es evaluado por la condición del if, nPalabras no se incrementa. 'hola'  daría 0 palabras.
  • ocurre que efectivamente, 'hola.' se incrementará en 1. Esto implica  que isalpha('.') es true.

 Y según el manual

Citar



isalpha()
checks for an alphabetic character; in the standard "C" locale, it is equivalent to (isupper(c) || islower(c)). In some locales, there may be additional characters for which isalpha() is true-letters which are neither upper case nor lower case.


Es decir, que en el estándar C locale, sería false. Debe ser que tu computador esté configurado a sp (Spanish) y acierta arbitrariamente, marcando isalpha(' ') false y isalpha('.') true  , pero con otra configuración, no está garantizado





... Lo que es habitual en este tipo de ejercicios, donde se suelen asumir entradas ideales.
En mi opinión, las frases "ideales" deben acabar en C,  en un carácter nulo, y no deben incluir símbolos como Comas, acentos y "puntos y Comas". La única razón es ajustarse a la esencia del Problema, que deja de ser portable en otros "locales".... Pero esto es opinable...

En lo que respecta a los casos que mandas, el segundo me llama la atención, puesto que según lo anterior '    .' (5 espacios y un blanco) debería dar 1, y te da 0, que es lo correcto.

Es realmente la salida de tu código?
No Le veo la explicación, pero puede que esté equivocado.
Debería verse



Código
  1. Total palabras: 0
  2.  

Un saludo, amigo... A ver si me sacas de dudas...
Estoy solo con un móvil y no puedo probar tus códigos.

Estos son algunos de los casos de prueba que utilicé, y las salidas que obtuve con mi código:



Código
  1. .
  2. 0
  3.  
  4.       .
  5. 0
  6.  
  7. ,;.
  8. 0
  9.  
  10. ,  ;    .
  11. 0
  12.  
  13. Hola.
  14. 1
  15.  
  16. Hola      .
  17. 1
  18.  
  19.        Hola   .
  20. 1
  21.  
  22. En un lugar de la Mancha, de cuyo nombre no quiero acordarme...
  23. 12
  24.  
  25. En    lugar             , de cuyo nombre no quiero          .
  26. 7
  27.  
  28. En un lugar.
  29. 3

Como se puede ver, cuando no existen palabras o cuando hay más de un espacio entre las palabras el cálculo es correcto.

No tomé en cuenta, intencionalmente, el conteo de números dentro de la frase, porque al2000 no lo planteó como parte del problema:

Código
  1. Ahora vienen 7 espacios:       , con estos otros suman 12:     .
  2. 7

En todo caso, no me parece que sea una solución incorrecta para un ejercicio de nivel básico.
66  Programación / Programación C/C++ / Re: Duda con contador de palabras en C para principiantes en: 23 Octubre 2018, 18:35 pm
La solución anterior es incorrecta: en el momento en que haya más de un espacio entre palabras, o mismamente cuando no haya palabras, el cálculo es errónea.

Propongo esta.

No tengo un compilador a mano para probarlo...
Pero si metes una frase, sin punto al final, no hace falta, debe funcionar.... No metas más que 'a', 'z' y ' '

Código
  1.  
  2.  
  3. /*
  4.  
  5.  
  6.   P : V[0..N) , N>= 0  
  7.   Q : (c = # i, j: 0 <= i < j <= N : word(V, i, j))
  8.  
  9.       where
  10. word(V,n,m) : allesnb(n, m) and (n>0 - > V[n-1]=' ') and  (m<N- > V[m]=' ')
  11.  
  12.  
  13. Snapshot invariant:
  14. -------------------
  15.  
  16.  
  17.  
  18.  
  19.  
  20.  
  21.    I : Q[N/n]
  22.        and 0 <= n <= N
  23.      
  24.  
  25.    B : n<N
  26.  
  27.  
  28.    C(n) = N - n  >= 0
  29.  
  30.    Init:
  31.    -----
  32.      n,c = 0,0
  33.  
  34.    Step:
  35.    ------
  36.      n= n + 1 (Clearly, quota decreases)
  37.  
  38.  
  39.    Restore:
  40.    --------
  41.       c = c +\chi (V[n]! =' ' && (n=0 ||   V[n-1]==' '))
  42.  
  43.  
  44.    Pseudo-code:
  45.    ------------
  46.  
  47.    n,c= 0,0
  48.    while  n < N
  49.        c = c +\chi (V[n]! =' ' && (n=0 ||   V[n-1]==' '))
  50.       n= n +1
  51.    end
  52.    return c
  53.  
  54.    
  55. O(N) since while;s body is in O(1) and f_iter in O(N)
  56.        
  57. */
  58.  
  59. #include <iostream>
  60. #include <algorithm> // max,min
  61. #include <string> // to string, to use
  62.  
  63.  
  64. using namespace std;
  65. #define MAX 100000
  66.  
  67.  
  68. /* See full development and derivation above*/
  69. int solve(const char V[], const int N)
  70. {
  71.  int c,n;
  72.  for(n=c=0;n<N;n++)
  73.       c +=(V[n]!=' ' && (!n ||   V[n-1]==' '));
  74.  return c;
  75. }
  76.  
  77.  
  78. int main(int argc, char *arg[])
  79. {
  80.  int n,N;
  81.  string V;
  82.  for(;getline(cin, V) ;)
  83.      cout << solve(V. c_str() ,V.length() ) << endl;
  84.  return 0;
  85. }
  86.  
  87.  
67  Programación / Programación C/C++ / Re: Ayuda con listas sinples en: 5 Septiembre 2018, 14:52 pm
El problema es que mi modulo de agregar nodo al final me agrega un nodo pero adelante como lo soluciono? Desde ya gracias chavales

Código
  1. #include <iostream>
  2. #include <stdlib.h>
  3. ...
  4. typedef struct tlista{
  5. pnodo inicio;
  6. int contador;
  7. };
  8.  
  9. void inicia(tlista &lista);
  10. void crear(pnodo &nuevo);
  11. void agregar_inicio(tlista &lista, pnodo nuevo);
  12. void agregar_final(tlista &lista, pnodo nuevo);
  13. void agregar_orden(tlista &lista, pnodo nuevo);
  14. pnodo quitar_inicio(tlista &lista);
  15. pnodo quitar_final(tlista &lista);
  16. pnodo quitar_nodo(tlista &lista, int valor);
  17. bool buscar_nodo(tlista lista,int valor);
  18. void mostrar(tlista lista);
  19. }

Ya el planteamiento de la signatura del tipo lista que haces es incorrecto. El programador usuario del tipo de datos lista no debe preocuparse del tuoi "pnodo"... Solo necesita saber el tipo de lista y el tipo de valor. Lo otro queda oculto, y solo lo conoce el implementador.

Siguiendo tu convenio, sería algo así:

Código
  1. void inicia(tlista &lista);
  2. void agregar_inicio(tlista &lista, int valor);
  3. void agregar_final(tlista &lista, int valor);
  4. void agregar_orden(tlista &lista, int valor);
  5. void quitar_inicio(tlista &lista);
  6. void quitar_final(tlista &lista);
  7. void quitar_valor(tlista &lista, int valor);
  8. void mostrar(tlista lista);
68  Programación / Programación C/C++ / Re: Ayuda con el siguiente programa. en: 3 Septiembre 2018, 15:08 pm
Podria evitarse el overflow al convertir el angulo gigante en el pequeno equivalente, por ejemplo

Código
  1. float G2R(float g) {
  2.    while(g > 360) {
  3.        g -= 360;
  4.    }
  5.    return g*PI/180;
  6. }

2 mejoras a esto:
- En vez de iterar restando 360, dividir por 360, y luego restar directamente la cantidad de veces que cabe 360 en el numero gigante.
- Algo similar hay que hacer para angulos negativos gigantes

Solo puedo decir una cosa : GENIAL.

No creo que sea un defecto por el posible overflow, (de hecho me parece que no hay overflow, como dije antes...) El algoritmo mismo exige 0 <= r <= 2pi

Propongo, para simplificar tantos positivos como negativos grandes, la macro

Código
  1. #define G2R(g) ((g%360)*PI/180)
  2.  

Aunque el operador (%) solo admite int, y ni podamos meter "floats".

Código
  1. int g;
  2.  for ( ; cin >> g ; )
  3.  

Ahora, tnemeos
Código:
0 90 180 270 360
          0 0.0000 0.0000
         90 1.5708 1.0000
        180 3.1416 0.0000
        270 4.7124 -1.0000
        360 0.0000 0.0000
0 -90 -180 -270 -360
          0 0.0000 0.0000
        -90 -1.5708 -1.0000
       -180 -3.1416 -0.0000
       -270 -4.7124 1.0000
       -360 0.0000 0.0000
0 1170 1260 1350 1440  # I.e  [0,90,180,270,360] + 360x3
          0 0.0000 0.0000
       1170 1.5708 1.0000
       1260 3.1416 0.0000
       1350 4.7124 -1.0000
       1440 0.0000 0.0000
0 -1170 -1260 -1350 -1440
          0 0.0000 0.0000
      -1170 -1.5708 -1.0000
      -1260 -3.1416 -0.0000
      -1350 -4.7124 1.0000
      -1440 0.0000 0.0000

Como Dios manda.... ;-)
69  Programación / Programación C/C++ / Re: Computo de funciones trigonométricas en: 31 Agosto 2018, 15:23 pm
Como dices, tu solución carece de "valor" en tanto que utilizas la librería <math.h>, que resuelve el problema que se te pide.

El cálculo de funciones trigonométricas se puede abordar desde muchos puntos de vista (calculo numérico, teoremas de trigonometría), pero todos ellos serán imprecisos en sus resultados en la medida que el sistema de tipos de C, (float) esta limitado en su capacidad para representar, no digamos ya cualquier número real, si no muchos números racionales, por ejemplo (1/3).

El clásico método para aproximar la función seno ( el resto, coseno y tangente, investigalos por tu cuenta) se basa en el Teorema de Taylor que permite el cómputo del valor de sen en términos de operraciones elementales, productos, sumas, potencias y divisiones:

Código:
 sinus(x) = sum i : 0<= i : (((-1)^i)/(2i+1)!)*x^(2i+1)

Como no es posible extenderme puesto que no es un curso de análisis numérico, baste decir que en toda implementación hay que tener en cuenta la precisión con la que abordamos el problema, en nuestro caso, hasta las diezmilésimas (10^-4)

Allá va el código. La línea central, la más compleja de elaborar, es la 28. Expplicar de donde se saca es un poco complejo sin entrar en manipulaciones algebraicas. Baste decir que t es el sumando correspondeinte al valor n. Lo que hace 28 es actualizar t para la siguiente vuelta, y esto se puede hacer en función del valor que tiene actualmente t.

Código
  1. #include <iostream>
  2. #include <iomanip> // To format floats into screen
  3.  
  4. /* Uses Taylor formula to compute sin(x), x in gradiants
  5.    
  6.    sinus(x) = sum i : 0<= i : (((-1)^i)/(2i+1)!)*x^(2i+1)
  7.  
  8.    Any computer program makes a finite computation, hence
  9.    we only add summands up to epsilon (in our case, 10^-4)
  10.  
  11.  */
  12.  
  13. #define PI 3.1416
  14. #define G2R(g) (g*PI/180)
  15. #define EPSILON 0.0001
  16. #define ABS(x) ((x>=0)?x:-x)
  17.  
  18. using namespace std;
  19.  
  20. /* P: r given in radians */
  21. float sinus(const float r)
  22. {
  23.  int n;
  24.  float s,t;
  25.  for(n=s=0,t=r; ABS(t) >= EPSILON ; n++)
  26.    {
  27.      s+=t;
  28.      t = ((-1)*r*r*t)/((2*n+3.0)*(2*n+2.0));
  29.    }
  30.  return s;
  31. }
  32.  
  33.  
  34. int main(int argc, char *args[])
  35. {
  36.  float g;
  37.  for ( ; cin >> g ; )
  38.    {
  39.      const float r = G2R(g);
  40.      std::cout << std::fixed << std::setw( 11 ) << std::setprecision(4)
  41. << g << " " <<  r << " " << sinus(r) << endl;
  42.    }
  43.  
  44. }

Y a continuación, la salida a algunos casos de angulos conocidos, como son  aquellos de seno 0,1,-1 y 0.5.
La primera columna marca el ánglo en grados, la segunda en radianes (aproximado) y la tercera la función seno del mismo....Se aprecia como en el caso de 360 grados cuyo seno es 0, arroja una aproximaci'on de 0,0001

Código:
0 90 180 270 360 
     0.0000 0.0000 0.0000
    90.0000 1.5708 1.0000
   180.0000 3.1416 0.0000
   270.0000 4.7124 -1.0000
   360.0000 6.2832 0.0001
30 150 210 330
    30.0000 0.5236 0.5000
   150.0000 2.6180 0.5000
   210.0000 3.6652 -0.5000
   330.0000 5.7596 -0.5000
1200
  1200.0000 20.9440 5.4417

El último caso es llamativo, pues da un error incoherente...El seno sólo puede ser entre -1 y 1. Nuevamente, se debe a la imprecisión para representar numeros grandes, y ciertamente, si te fijas en el producto del código de la línea 28, esta incluye un valor "relativamente grande", que float es incapaz de representar. Ojo a los errores en el cálculo numérico!
70  Programación / Programación C/C++ / Re: Violación de segmento en sockets en: 16 Julio 2018, 16:19 pm
No es posible. Un programa tan simple....
El error debe estar en las otras cosas...las que no son de sockets

Código
  1. #include <sys/types.h>        
  2. #include <sys/socket.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <unistd.h>
  6.  
  7. int main()
  8. {
  9.  int packet_socket;
  10.  if ((packet_socket = socket(AF_INET, SOCK_STREAM, 0))==-1)
  11.    {
  12.      perror("socket");
  13.      exit(1);
  14.    }
  15.  
  16.  if (close(packet_socket)==-1)
  17.    {
  18.      perror("close");
  19.      exit(1);
  20.    }
  21.  exit(0);
  22. }
  23.  

Probando esto en UNIX

Código:
(./main && echo "OK") || echo "NOK"

Da la salida
Código:
OK
Páginas: 1 2 3 4 5 6 [7] 8 9 10 11
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines