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

 

 


Tema destacado: Estamos en la red social de Mastodon


  Mostrar Temas
Páginas: [1]
1  Programación / Programación C/C++ / [C] Multiplicación de matrices sparse por vectores en: 12 Junio 2015, 19:00 pm
Buenas chicos, les traigo un laboratorio de C, que hice en un curso de cómputo científico, espero les sea de utilidad a alguno.

Matriz sparse: es una matriz cuyos elementos no nulos figuran una minoría entre todos. Por ejemplo, una matriz 1000x1000 tiene 106 elementos, supongamos que de los cuales sólo el 10% son no-nulos (105). A la hora de resolver diversos problemas se hace útil almacenarla de una manera especial teniendo en cuenta esto.

(Pueden encontrar un poco más de información del tema en la wikipedia en inglés, también hay papers en google académico)

El programa que se presenta pide un archivo el cual tiene la siguiente estructura

indices de fila de elementos no nulos
indices de columna de elementos no nulos
valores no nulos de la matriz asociados al conjunto de indices
valores de un vector b
.... (así sucesivamente)

Se pide un número de matrices a leer. La función leeMatriz lee una matriz específica en el archivo (1 si es la primera, 2 si es la segunda, etc). Se supone que cada elemento de la matriz tiene al menos un elemento no nulo en cada fila y columna. La función matrizPorVector devuelve el puntero hacia el comienzo del arreglo que contiene los valores del resultado de la multiplicación.

Sin más, acá el código

main.c
Código
  1. // Programa principal
  2. //  Se encarga de establecer interfaz con el usuario.
  3.  
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6.  
  7. //Prototipo
  8. int leeMatriz(
  9. char *nomarch, int nummat,
  10. int **ifil, int **icol, double **xval, double **b,
  11. int *nfil, int *ncol);
  12.  
  13. double *matrizPorVector(int *ifil, int *icol, double *xval, double *b, int nza, int nfil);
  14.  
  15. int main()
  16. {
  17. char nombre[100];
  18. char salida[] = "resultados.txt";
  19. FILE *archivo;
  20. int num;
  21. double *xval;
  22. double *b;
  23. int *ifil, *icol;
  24. int nfil, ncol;
  25. int retorno, i, k;
  26. double *resultado;
  27.  
  28. //Se pide al usuario que introduzca los datos para la lectura
  29. printf("Introduce nombre de archivo: ");
  30. scanf("%s", nombre);
  31.  
  32. printf("Introduce numero de matrices en el archivo: ");
  33. scanf("%d", &num);
  34.  
  35. //Abrimos el archivo de salida
  36. if ( (archivo = fopen(salida, "w+")) == NULL)
  37. {
  38. printf("No se ha podido abrir el archivo de salida %s \n", salida);
  39. exit(EXIT_FAILURE);
  40. }
  41.  
  42. //Leemos la cantidad de matrices que el usuario ingresó
  43. for(k=1; k<=num; k++)
  44. {
  45. //Leemos la k-ésima matriz
  46. retorno = leeMatriz(nombre, k, &ifil, &icol, &xval, &b, &nfil, &ncol);
  47.  
  48. //Damos un mensaje alusivo
  49. fprintf(archivo, "La matriz numero %d\r\n", k);
  50.  
  51. //Imprimimos en el archivo de salida, dependiendo de lo que retornó leeMatriz
  52. switch(retorno)
  53. {
  54.  
  55. case -2:
  56. fprintf(archivo, "Los tamaños de los vectores no son compatibles\r\n");
  57. break;
  58.  
  59. case -1:
  60. fprintf(archivo, "El tamaño del vector no coincide con el numero de columnas\r\n");
  61. break;
  62.  
  63. default:
  64. fprintf(archivo, "Los tamaños coinciden. El vector resultado es:\r\n");
  65.  
  66. //Procesamos los datos para obtener el resultado
  67. resultado = matrizPorVector(ifil, icol, xval, b, retorno, nfil);
  68. for(i=0; i<nfil; i++)
  69. fprintf(archivo, "%lf   ", *(resultado+i) );
  70.  
  71. //Liberamos la memoria del vector resultado solo en este caso
  72. free(resultado);
  73. fprintf(archivo, "\r\n");
  74. break;
  75. }
  76. //Liberamos la memoria reservada para volver a llamar
  77. //de manera segura la función malloc dentro de las funciones
  78.  
  79. //Liberamos la memoria de los vectores que generan el par matriz-vector
  80. //luego de esto, quedan apuntando a NULL, tal cosa es lo que espera
  81. //la funcion leeMatriz, al final del programa esto se hace de último
  82. //y por lo tanto nos aseguramos de que liberamos toda la memoria dinamica
  83. //que se utilizó a lo largo del programa
  84. free(ifil);
  85. free(icol);
  86. free(xval);
  87. free(b);
  88.  
  89. fprintf(archivo, "\r\n");
  90. }
  91.  
  92. //Cerramos el archivo de salida
  93. fclose(archivo);
  94.  
  95.  
  96. return 0;
  97. }

matrizPorVector.c
Código
  1. // Funcion que realiza la multiplicacion de una matriz sparse por un vector
  2. // Argumentos.
  3. // Entrada:
  4. // int *ifil, vector de indices de filas
  5. //  int *icol, vector de indices de columnas
  6. //  int nza, cantidad de valores no nulos
  7. //  int nfil, orden de filas
  8. // double *xval, *b, los valores no nulos y el vector
  9.  
  10. // Salida (por return)
  11. // double *, una dirección de memoria, el cual será el comienzo
  12. //  del vector resultado de la multiplicación
  13.  
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16.  
  17. double *matrizPorVector(int *ifil, int *icol, double *xval, double *b, int nza, int nfil)
  18. {
  19. unsigned k; // unsigned i;
  20. double *resultado;
  21.  
  22. if ( ( resultado = (double *) malloc ( nfil*( sizeof(double) ) ) ) == NULL )
  23. {
  24. printf("No hubo memoria disponible para la reserva de un resultado\n");
  25. exit(EXIT_FAILURE);
  26. }
  27.  
  28. //Inicializamos los valores del vector resultado
  29. for(k=0; k<nfil; k++)
  30. *(resultado + k) = 0.0f;
  31.  
  32. // Cada k tal que 0<=k<nza cumple que
  33. // El elemento en la posicion *(ifil+k), *(icol+k) es *(xval+k)
  34. // Sólo hay que recordar que el conjunto de indices en los
  35. // vectores ifil, icol comienzan desde 1, no desde cero
  36. // por lo tanto debemos restarle 1 cuando utilizamos este
  37. // conjunto de indices
  38.  
  39. // Como resultado obtenemos un for más compacto, y además
  40. // un algoritmo mucho más rapido para matrices muy grandes
  41. for(k=0; k<nza; k++)
  42. *(resultado+(*(ifil+k))-1) += (*(b - 1 + (*(icol+k))))*(*(xval+k));
  43.  
  44.  
  45. // Retornamos la direccion de memoria del comienzo del arreglo
  46. return resultado;
  47. }
  48.  

leeMatriz.c
Código
  1. // Funcion que lee matriz desde archivo de texto.
  2. // Argumentos.
  3. // Entrada:
  4. // char *nomarch : nombre de archivo
  5. // int nummat : numero de matriz a leer
  6.  
  7. // Salida (por referencia)
  8. // int *ifil : vector de indices de filas
  9. // int *icol : vector indices de columnas
  10. // double *xval : vector de valores asociado a la matriz en los indices de ifil e icol
  11. // double *b : vector asociado al par nummat de matrices-vectores
  12. // int *nfil : numero de filas
  13. // int *ncol : numero de columnas
  14.  
  15. // Salida (por return)
  16. // -2, si los vectores xval, ifil e icol no tienen el mismo tamaño
  17. // -1, el tamaño de b no corresponde con el nuero de columnas de la matriz
  18. // a, si todos los valores se corresponden, donde a es el numero de elementos no nulos de la matriz
  19.  
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23.  
  24. int leeMatriz(
  25. char *nomarch, int nummat,
  26. int **ifil, int **icol, double **xval, double **b,
  27. int *nfil, int *ncol)
  28.  
  29. {
  30. int a = 0; // Valor de retorno
  31. int nbytes; // Identificador para el retorno de fscanf */
  32. int nval, nb; // Numero de valores no nulos de la matriz, y numero de valores del vector */
  33. char c;
  34. // Caracter que se lee después de los valores */
  35. int foo, aux;
  36. // Un contador y una variable auxiliars */
  37. int bar[4]; // Variables logicas auxiliares
  38.  
  39. FILE *archivo;
  40.  
  41. // Validamos la correcta apertura del archivo
  42. if ( (archivo = fopen(nomarch, "r")) == NULL)
  43. {
  44. printf("No se ha podido abrir el archivo %s \n", nomarch);
  45. exit(EXIT_FAILURE);
  46. }
  47.  
  48.  
  49.  
  50.  
  51. // Saltamos las lineas necesarias hasta la matriz que se nos pide
  52. for (foo = 1; foo<=4*(nummat-1); foo++)
  53. {
  54. do
  55. {
  56. fscanf(archivo, "%c" , &c );
  57. } while( c != '\n' && c != '\r' );
  58. }
  59.  
  60. //Inicializamos la salida, suponemos que los vectores apuntan a nulo en esta llamada.
  61. //Los arreglos (leidos en ese orden)
  62.  
  63. //Guardamos como valor logico cada uno de los siguientes.
  64. bar[0] = ( *ifil = (int *) malloc( sizeof(int) ) ) == NULL;
  65. bar[1] = ( *icol = (int *) malloc( sizeof(int) ) ) == NULL;
  66. bar[2] = ( *xval = (double *) malloc( sizeof(double) ) ) == NULL;
  67. bar[3] = ( *b = (double *) malloc( sizeof(double) ) ) == NULL;
  68.  
  69. //Si alguno de los malloc retorna NULL, imprimimos un mensaje alusivo y salimos
  70. if(bar[0] || bar[1] || bar[2] || bar[3])
  71. {
  72. printf("No hubo memoria disponible al inicializar los pares de vectores asociados a la matriz\n");
  73. exit(EXIT_FAILURE);
  74. }
  75. //El contador de ifil, icol, y del arreglo b
  76.  
  77.  
  78. //Nota importante: los punteros son pasados por referencia, o sea punteros a punteros de tipo
  79. //Las lineas de arriba dicen el contenido del puntero a puntero (que es un puntero) es la direccion
  80. //de memoria que retorna la función malloc en el tamaño especificado
  81.  
  82. *nfil = *ncol = nval = nb = 0;
  83.  
  84. //Leemos la entrada que se nos pide. La lectura completa consta de 4 líneas
  85. //Con este for lo que pretendo es ahorrarnos líneas repetitivas
  86.  
  87.  
  88. for(foo = 1; foo<=4; foo++)
  89. {
  90. do
  91. {
  92. switch(foo)
  93. {
  94.  
  95. //Lectura de ifil
  96.  
  97. case 1:
  98. fscanf(archivo, "%d" , (*ifil+(*nfil)) );
  99. *ifil = (int *) realloc( *ifil, (++(*nfil)+1)*sizeof(int) );
  100. break;
  101.  
  102.  
  103. //Lectura de icol
  104. case 2:
  105. fscanf(archivo, "%d" , (*icol+(*ncol)) );
  106. *icol = (int *) realloc( *icol, (++(*ncol)+1)*sizeof(int) );
  107. break;
  108.  
  109. //Lectura de xval
  110. case 3:
  111. fscanf(archivo, "%lf" , *xval+nval);
  112. *xval = (double *) realloc( *xval, (++nval+1)*sizeof(double) );
  113. break;
  114.  
  115. //Lectura de b
  116. case 4:
  117. fscanf(archivo, "%lf" , *b+nb);
  118. *b = (double *) realloc( *b, (++nb+1)*sizeof(double) );
  119. break;
  120.  
  121.  
  122. }
  123.  
  124. } while ( (nbytes = fscanf(archivo, "%c", &c)) != EOF && c != '\n' && c != '\r' );
  125. //Cada iteración del for lee una línea
  126. }
  127.  
  128. fclose(archivo);
  129.  
  130. //Dado que, cuando llega al fin de línea igualmente se le agrega
  131. //un espacio a los vectores, quitamos este espacio extra
  132.  
  133. //Damos esta solución para el problema de validar que se ha hecho la reserva
  134. //de manera correcta, en lugar de uno por uno, se haen todos, si alguno
  135. //no ha salido como se esperaba, el programa no tiene sentido que continue
  136. bar[0] = ( *ifil = (int *) realloc( *ifil, (*nfil)*sizeof(int) ) ) == NULL;
  137. bar[1] = ( *icol = (int *) realloc( *icol, (*ncol)*sizeof(int) ) ) == NULL;
  138. bar[2] = ( *xval = (double *) realloc( *xval, (nval)*sizeof(double) ) ) == NULL;
  139. bar[3] = ( *b = (double *) realloc( *b, (nb)*sizeof(double) ) ) == NULL;
  140.  
  141. //Si alguno de los realloc retorna NULL, imprimimos un mensaje alusivo y salimos
  142. if(bar[0] || bar[1] || bar[2] || bar[3])
  143. {
  144. printf("No hubo memoria suficiente para hacer realloc a los vectores de una matriz\n");
  145. exit(EXIT_FAILURE);
  146. }
  147.  
  148. if ( *nfil != *ncol || (*nfil != nval || *ncol != nval)  ) return -2;
  149.  
  150.  
  151. //Se toma el mayor valor de los indices de filas/columnas como orden de la matriz
  152. aux = **ifil;
  153. for(foo=1; foo<*nfil; foo++)
  154. if( *(*ifil+foo) > aux )
  155. aux = *(*ifil+foo);
  156. *nfil = aux;
  157.  
  158. aux = **icol;
  159. for(foo=1; foo<*ncol; foo++)
  160. if( *(*icol+foo) > aux )
  161. aux = *(*icol+foo);
  162. *ncol = aux;
  163. //Para este punto, *nfil tiene el orden de la matriz en cuanto
  164. //a filas y *ncol en cuanto a las columnas y por tanto podemos
  165. //comparar con el segundo if para retornar
  166.  
  167. //Por defecto se retorna el numero de elementos no nulos encontrados en xval
  168. a = nval;
  169. //De encontrarse un problema de consistencia, cambiamos el valor de a
  170.  
  171. if ( *ncol != nb ) a = -1;
  172.  
  173. //Retornamos
  174. return a;
  175. }

Saludos, quizá pronto traiga más de este tema

Nota quiero agradecer a mi profesor quien hizo esfuerzo a lo largo del curso trayendo laboratorios interesantes.

PD: como siempre, acepto sugerencias y consejos ;)
2  Programación / Programación C/C++ / [+] Juego plataformista en C++ en: 8 Junio 2015, 19:10 pm
Buenas, soy nuevo en esta comunidad y hoy quiero traer un aporte. EL siguiente código lo hice hace un par de meses a manera de prueba de SFML y Box2D. Más que un juego completo (niveles, menús, etc), se buscaba aplicar los conceptos básicos de las herramientas antes mencionadas.

SFML: es una librería que proporciona una capa a OpenGL para trabajar gráficos. Además de esto, da también otras características interesantes relacionadas con multimedia (sonido, por ejemplo) y networking (para juegos online). Es open source y además multiplataforma (puede, de hecho, compilarse para Android utilizando las herramientas correspondientes). Pagina principal: http://www.sfml-dev.org/

Box2D: es un engine para simulación física en dos dimensiones, proporciona una serie de características útiles. También es open source y además es multiplataforma. Pagina del proyecto: http://box2d.org/ (Un dato interesante es que es utilizado en varios Game Engines, dado que es muy eficiente en sus algoritmos)

Como funciona: en primera instancia se lleva acabo un paralelismo entre pixeles y metros. Al momento de proporcionar información a los objetos de Box2D se hace la conversión correspondiente, y al dibujar en pantalla se hace exactamente lo mismo.

Qué tener en cuenta del codigo fuente
1. El juego se hizo bajo Windows con Visual Studio, por lo tanto, para compilarlo en otras plataformas habría que hacer un par de cambios menores (una o dos líneas)
2. No es un juego completo, pero pienso que ilustra varios conceptos básicos como la pila de cuerpos de un mundo (Box2D) y los métodos más frecuentes de SFML, como crear sprites, renderizarlos, tomar teclas por pantalla, etc.
3. Para poder compilar es obviamente necesario tener las clases mencionadas arriba, en las páginas oficiales encontrarán información acorde a diferentes IDE y SO.

Enlace de descarga para codigo fuente dado que son varios archivos he decidido ponerlo en mediafire, y aquí, nada más el main.cpp
http://www.mediafire.com/download/0j8ab99e9fyzhkn/pltaformista.tar.gz
El comprimido contiene:
main.cpp
Player.cpp / Player.h (objeto que representa el jugador)
Blocks.cpp / Blocks.h (objeto que representa plataformas)
Constants.h (constantes que se usan a lo largo del resto del código)

Acá el main.cpp
Código
  1. /*   __                          
  2. /  |                        
  3. (___| ___  ___  ___       ___
  4. |\   |___)|   )|___)(_/_ |   )
  5. | \  |__  |__/ |__   / / |__/
  6.  __/         |    
  7.  *
  8.  *
  9.  * Este software se ha dado tal como es, el autor no se hace responsable
  10.  * del uso que le pueda dar el usuario final. Así mismo se da el derecho
  11.  * de editar, distribuir y utilizar el código a conveniencia, siempre y
  12.  * cuando se de crédito al autor.
  13.  *
  14.  *
  15.  */
  16.  
  17.  
  18. #pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup")
  19.  
  20. #include <iostream>
  21. #include <Box2D/Box2D.h>
  22. #include <SFML/Graphics.hpp>
  23. #include <sstream>
  24. #include <ctime>
  25. #include "Constants.h"
  26. #include "Block.h"
  27. #include "Player.h"
  28. #include <stdio.h>
  29. #include <Windows.h>
  30.  
  31.  
  32.  
  33.  
  34. using namespace std;
  35.  
  36. int main() {
  37. sf::Clock clock;
  38. sf::Time time; //Esto es para que el simulador fisico se haga proporcional a los segundos que transcurren por frame
  39. //Inicializamos la camara del juego
  40. sf::View camera;
  41. camera.reset( sf::FloatRect(0,0, (int)width, (int)height) );
  42. camera.setViewport( sf::FloatRect(0, 0, 1.0f, 1.0f) );
  43. float cameraPosition;
  44.  
  45.  
  46. //Inicializacion de Box2D
  47. b2World* world = new b2World(gravity);
  48.  
  49. //Inicializacion del App
  50. sf::RenderWindow App(sf::VideoMode(width, height, 30), "Juego prueba");
  51. App.setKeyRepeatEnabled(true);
  52. App.setFramerateLimit(90);
  53. App.setView(camera);
  54. sf::Event Event;
  55.  
  56.  
  57. Player player(world, 32, 32, sf::Vector2f(30, 30), "playerSprite.png"); //Inicializamos un "jugador"
  58. // Recordar hacer clase nivel/mundo que controle eventos independientemente!
  59.  
  60.  
  61.  
  62. std::vector<Block> bloques;
  63. // Este vector de bloques va a contener plataformas y objetos
  64. sf::Texture grass;
  65. grass.loadFromFile("grass.png");
  66. grass.setRepeated(true);
  67. grass.setSmooth(true);
  68.  
  69. bloques.push_back(Block(world, 3000.0f, 50.0f, sf::Vector2f(-200, height - 50.0f), .5f, false, 0, 0, &grass));
  70. //Esto es un suelo!
  71.  
  72.  
  73. sf::Texture bricks;
  74. bricks.loadFromFile("bricks.jpg");
  75. bricks.setRepeated(true);
  76. bricks.setSmooth(true);
  77.  
  78. bloques.push_back(Block(world, 400.0f, 49.0f, sf::Vector2f(300, 300), .5f, false, .5f, 0, &bricks));
  79. bloques.push_back(Block(world, 400.0f, 49.0f, sf::Vector2f(850, 100), .5f, false, .5f, 0, &bricks));
  80. // Inicializamos algunas plataformas
  81.  
  82. //Agregamos un objeto dinamico...
  83. sf::Texture box;
  84. box.loadFromFile("box.png");
  85. box.setSmooth(true);
  86. bloques.push_back(Block(world, 100.0f, 100.0f, sf::Vector2f(450, 150), .5f, true, .5f,  0.0f, &box));
  87.  
  88. //Inicializamos el fondo del escenario (estatico)
  89. sf::Texture bgTexture;
  90. bgTexture.loadFromFile("desert.png");
  91. bgTexture.setSmooth(true);
  92.  
  93. sf::Sprite bgImg;
  94. bgImg.setTexture(bgTexture);
  95. bgImg.setPosition( sf::Vector2f( 0, 0 ) );
  96.  
  97.  
  98. // Game loop
  99. while (App.isOpen())
  100. {
  101. clock.restart();
  102. // Manejo de eventos
  103. while (App.pollEvent(Event))
  104. {
  105. // Si cierra la ventana se cierra el juego
  106. if (Event.type == sf::Event::Closed)
  107. App.close();
  108.  
  109. // Eventos de teclado
  110. if (Event.type == sf::Event::KeyPressed)
  111. {
  112. //Todo esto se puede cambiar por un switch! recordar cambiar!!
  113. if (Event.key.code == sf::Keyboard::D)
  114. player.Run("right");
  115.  
  116. if (Event.key.code == sf::Keyboard::A)
  117. player.Run("left");
  118.  
  119. if (Event.key.code == sf::Keyboard::W)
  120. player.Jump();
  121.  
  122. }
  123.  
  124. if (Event.type == sf::Event::KeyReleased)
  125. player.Stop();
  126.  
  127.  
  128. }
  129.  
  130. //Limpia Pantalla
  131. App.clear();
  132.  
  133. // DIbuja fondo del escenario
  134. App.draw(bgImg);
  135.  
  136. // Dibuja objetos
  137. for (int i = 0; i < int(bloques.size()); i++)
  138. {
  139. App.draw( bloques[i].GetShape() );
  140. }
  141.  
  142. //Dibuja el player
  143. App.draw( player.GetSprite() );
  144.  
  145.  
  146.  
  147. //Los muestra en pantalla
  148. App.display();
  149.  
  150. // Hace update fisico al mundo
  151. time = clock.getElapsedTime();
  152. world->Step(time.asSeconds(), velocityIterations, positionIterations);
  153.  
  154.  
  155. for (int i = 0; i < int(bloques.size()); i++)
  156. {
  157. bloques[i].Update();
  158. }
  159. player.Update();
  160. player.UpdateSprite();
  161.  
  162. // Movemos la camara para que tenga de centro al objeto player!!
  163. cameraPosition = player.dimentions().x + player.screenPosition().x - width/2;
  164. if (cameraPosition < 0)
  165. cameraPosition = 0;
  166.  
  167. camera.reset( sf::FloatRect( cameraPosition, 0, (int)width, (int)height ) );
  168. App.setView(camera);
  169. // Ponemos el fondo donde se pueda ver....
  170. bgImg.setPosition( sf::Vector2f( cameraPosition, bgImg.getPosition().y ) );
  171.  
  172. }
  173.  
  174.  
  175.  
  176. return 0;
  177. }
  178.  


Screenshot

El bloque que está arriba, puede empujarse, caer, etc.. y luego usarlo como plataforma. El resto de las plataformas no se mueven, son estáticas.

Bueno, eso es todo por ahora, acepto sugerencias y críticas. Si hay algunas personas interesadas, haré un tutorial (o más) detallado(s) sobre este tema.

Saludos  ::)
Páginas: [1]
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines