viernes, 30 de mayo de 2014

Ejemplos de introducción: ENSAMBLADOR MIPS.

Empezamos con la programación en ensamblador MIPS con esta entrada que contiene unos ejemplos bastante sencillitos para empezar. Si no se sabe nada acerca del repertorio de instrucciones de MIPS es recomendable leer algo acerca de ellas, al menos qué es lo que hacen, pues si no os será imposible realizar los ejercicios posteriores de una complejidad mayor.

Os dejo tres ejemplos básicos para empezar a conocer las instrucciones más usuales add, lw, sw, beq, j... En la próxima entrada serán un poco más difíciles ;)

Suma de dato1 y dato1 almacenada en la variable sum.
.data
dato1:	.word 2				
dato2:	.word 5				
sum:	.word 0				

.text
main:	lw $8, dato1($0)		# cargamos el primer dato en el registro $8
	lw $9, dato2($0)		# cargamos el segundo dato en el registro $9
	add $10, $8, $9			# sumamos los dos registros y el resultado lo almacenamos en $10
	sw $10, sum($0)			# almacenamos el resultado ($10) en su variable (sum)
	
fin:	li $2, 10			# cargamos parametro necesario para terminar programa
	syscall				# llamada al sistema que termina un programa

Escribir en la variable max el valor máximo contenido en las variables dato1 y dato2.
.data
dato1:	.word 2				
dato2:	.word 5				
max:	.word 0				

.text
main:		lw $8, dato1($0)	
		lw $9, dato2($0)	
		slt $10, $8, $9		
		beq $10, $0, d1		
		sw $9, max($0)		
		j fin				
d1:		sw $8, max($0)		
fin:		li $2, 10			
		syscall	

Suma de los valores almacenados en un vector.
.data
tam: .word 8
datos: .word 2, 4, 6, 8, -2 -4, -6 -7
res: .word 0
.text
main:  lw $8, tam($0)
  la $9, datos
  sub $11, $11, $11
loop:  lw $10, 0($9)  
  add $11, $11, $10
  addi $9, $9, 4
  addi $8, $8, -1
  beq $8, $0, salir
  j loop
salir:  sw $11, res($0)
  li $2, 10
  syscall

domingo, 25 de mayo de 2014

Ejercicio de Concurrencia en Java: Agentes y fumadores con Monitores y Locks

Os dejo dos soluciones diferentes a un ejercicio de Concurrencia en Java. Una es usando monitores y la otra usando locks/condiciones. La verdad es que cambian bastante poco ambas soluciones pero así se tienen más claras las diferencias entre ambos métodos.
Os dejo el enunciado y los dos códigos, primero el de locks y luego el de monitores.


Considera un sistema formado por tres hebras fumadores que se pasan el día liando cigarros y fumando. Para liar un cigarro necesitan tres ingredientes: tabaco, papel y cerillas. Cada fumador dispone de un surtido suficiente (para el resto de su vida) de uno de los tres ingredientes. Cada fumador tiene un ingrediente diferente, es decir, un fumador tiene una cantidad infinita de tabaco, el otro de papel y el otro de cerillas. Hay también una hebra agente que pone dos de los tres ingredientes encima de una mesa. El agente dispone de unas reservas infinitas de cada uno de los tres ingredientes y escoge de forma aleatoria cuáles son los ingredientes que pondrá encima de la mesa.Cuando los ha puesto, el fumador que tiene el otro ingrediente puede fumar (los otros dos no). Para ello coge los ingredientes, se lía un cigarro y se lo fuma. Cuando termina de fumar vuelve a repetirse el ciclo. En resumen, el ciclo que debe repetirse es :
“agente pone ingredientes fumador hace cigarro fumador → → fuma → fumador
termina de fumar → agente pone ingredientes → ...”
Es decir, en cada momento a lo sumo hay un fumador fumando un cigarrillo.

Soluciones:

Está claro que siempre hay múltiples soluciones a un mismo problema, así que os ofrezco la manera que yo he tenido de hacerlo.

Para este problema he creado 4 clases diferentes: Agente, Fumador, Main y SalaFumadores. Tanto para monitores como para locks, las tres primeras son iguales, simplemente cambia la clase SalaFumadores, pues es donde hacemos la sincronización con estos dos métodos distintos.

Os dejo primero las clases comunes y posteriormente las dos clases SalaFumadores diferentes.

Agente.java


import java.util.Random;


public class Agente extends Thread {
 private SalaFumadores sala;
 private Random r;
 public Agente(SalaFumadores sala){
  this.sala = sala;
  r= new Random();
 }
 public void run (){
  while(true){
   sala.colocar(r.nextInt(3)+1);
  }
 }
}


Fumador.java
public class Fumador extends Thread{
 private int id;
 private SalaFumadores sala;
 public Fumador(int id, SalaFumadores sala){
  this.id = id;
  this.sala = sala;
 }
 public void run(){
  while(true){
   try {
    sala.entrafumar(id);
    System.out.println("Fumador "+id+" está fumando.");
    Thread.sleep(1000);
    sala.terminafumar(id);
   } catch (InterruptedException e) { e.printStackTrace(); }
  }
 }
}

Main.java
public class Main {
 public static void main(String[] args) {
  SalaFumadores sala = new SalaFumadores();
  Fumador fumador1 = new Fumador(1, sala);
  Fumador fumador2 = new Fumador(2, sala);
  Fumador fumador3 = new Fumador(3, sala);
  Agente agente = new Agente(sala);
  fumador1.start();
  fumador2.start();
  fumador3.start();
  agente.start();
  
 }
}
SalaFumadores.java con locks/condiciones.
import java.util.concurrent.locks.*;
 

public class SalaFumadores {
 /*
  * NOTA:
  * Para simplificar el problema considero que los ingredientes son tres enteros 1, 2 y 3.
  * Cada fumador vendrá representado por el número de ingrediente que tiene, es decir,
  * el fumador 1 posee el ingrediente 1.
  * Además en la mesa de la sala el agente pone dos ingredientes más, por lo que la mesa
  * se identificará con el entero del ingrediente que falta, es decir, si mesa = 1 significa
  * que en la mesá están los ingredientes 2 y 3, pero no el 1. Para representar que la mesa 
  * está vacía ponemos la variable mesa a 0.
  */
 
 static int mesa; //representa que ingrediente no esta
 static Lock l;
 static Condition [] puedofumar;
 static boolean alguienFuma;
 static Condition puedocolocar;
 
 public SalaFumadores(){
  l = new ReentrantLock(true);
  puedofumar =  new Condition[3];
  puedofumar[0] = l.newCondition();
  puedofumar[1] = l.newCondition();
  puedofumar[2] = l.newCondition();
  puedocolocar= l.newCondition();
  mesa = 0;
  alguienFuma = false;
 }
 
 public void entrafumar(int id){
  l.lock();
  try{
   while(mesa != id || alguienFuma){
    try {
     puedofumar[id-1].await();
    } catch (InterruptedException e) {e.printStackTrace(); }
   }
   //ya puedo fumar
   
   mesa = 0; //cojo los ingredientes
   alguienFuma = true;

   
  
  }finally{
   l.unlock();
  }
 }
 
 public void terminafumar(int id){
  l.lock();
  try {
   alguienFuma = false;
   puedocolocar.signal();
  } finally{
   l.unlock();
  }
 }
 
 public void colocar (int ingrediente){ // ingrediente que falta en la mesa
  l.lock();
  
  try{
   while( mesa !=0 || alguienFuma){
    try {
     puedocolocar.await();
    } catch (InterruptedException e) {e.printStackTrace(); }
   }
   mesa = ingrediente;
   System.out.println("En la mesa falta el ingrediente "+ mesa);
   
   puedofumar[mesa-1].signal();
   
  }finally{
   l.unlock();
  }
  
 }
}
SalaFumadores.java con Monitores
public class SalaFumadores {
 /*
  * NOTA:
  * Para simplificar el problema considero que los ingredientes son tres enteros 1, 2 y 3.
  * Cada fumador vendrá representado por el número de ingrediente que tiene, es decir,
  * el fumador 1 posee el ingrediente 1.
  * Además en la mesa de la sala el agente pone dos ingredientes más, por lo que la mesa
  * se identificará con el entero del ingrediente que falta, es decir, si mesa = 1 significa
  * que en la mesá están los ingredientes 2 y 3, pero no el 1. Para representar que la mesa 
  * está vacía ponemos la variable mesa a 0.
  */
 public static int mesa = 0; // indicará qué elemento falta en la mesa
 public static boolean alguienFumando = false;
 
 
 
 public synchronized void entrafumar( int ingrediente){
  while(mesa != ingrediente || alguienFumando){
   try {
    //System.out.println("El fumador "+ ingrediente + " no puede fumar aún.");
    wait();
   } catch (InterruptedException e) {e.printStackTrace();} 
  }
  // se hace el cigarro
  mesa = 0; //mesa vacía
  //fuma
  alguienFumando = true;
 }
 public synchronized void terminafumar(){
  alguienFumando = false;
  notifyAll();
 }
 
 public synchronized void colocar(int noesta){
  while(mesa != 0 || alguienFumando){
   try {
    //System.out.println("No puedo poner ingredientes aún");
    wait();
   } catch (InterruptedException e) {e.printStackTrace();} 
  }
  mesa = noesta;
  System.out.println("En la mesa no hay ingrediente "+ mesa);
  notifyAll();
 }
}

viernes, 23 de mayo de 2014

Ejercicios de Concurrencia en Java

Aquí dos ejercicios de concurrencia en Java, el primero es de semáforos y en el segundo usamos locks y condiciones.



En un sistema industrial existen tres sensores que realizan mediciones del nivel de temperatura, humedad y luz respectivamente. Cuando se han recogido mediciones de los tres sensores, existe un dispositivo “trabajador” encargado de realizar ciertas tareas según las mediciones realizadas. El dispositivo no puede comenzar a realizar sus tareas hasta que se han recogido mediciones de los tres sensores, y los sensores no pueden volver a realizar mediciones hasta que el dispositivo finaliza sus tareas. El proceso se repite de forma indefinida de manera que cuando el dispositivo finaliza sus tareas, volverá a esperar a que haya mediciones de los tres sensores. Realizar utilizando semáforos el modelado de dicho sistema. Modelar el dispositivo trabajador y cada sensor como una hebra (con lo cual habrá un total de 4 hebras). Modelar el proceso de realizar mediciones y las tareas del dispositivo con retrasos aleatorios y valores de tipo entero. Inicialmente puede suponerse que los sensores pueden comenzar haciendo peticiones.

import java.util.Random;
import java.util.concurrent.Semaphore;


public class Ejercicio1 {

 private static Semaphore semTrabajador = new Semaphore(0, true);
 private static Semaphore [] semsensores = new Semaphore[3];
 private static int [] datos = new int[3];
 private static Random r = new Random();
 
 public static class Trabajador extends Thread {
  public void run (){
   while(true){
   try {
    semTrabajador.acquire(3);
     
    
    sleep(r.nextInt(500));  // tiempos de espera aleatorio simulando la tarea del trabajador 
          //(tiempo que tarda el recoger los datos por ejemplo)
    System.out.println("Temperatura: " + datos[0]);
    System.out.println("Humedad: "+ datos[1]);
    System.out.println("Luz: " + datos[2] + "\n");
   
    
    semsensores[0].release();
    semsensores[2].release();
    semsensores[1].release(); 
    
   } catch (InterruptedException e) { e.printStackTrace();   }
   }
  }
 }
 
 public static class Sensor extends Thread {
  private int id;
  public Sensor(int id){
   this.id = id;
  }
  public void run(){
   while(true){
   try {
    semsensores[id].acquire();
    
    //coge el dato
    sleep(r.nextInt(500)); // tiempos de espera aleatorio simulando la tarea del sensor
    datos[id] = r.nextInt(50);
    //System.out.println("datos["+id+"] = "+ datos[id]);
    
    semTrabajador.release();
    
   } catch (InterruptedException e) { e.printStackTrace();  }
   }
  }
 }
 
 
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  
  Trabajador trabajador = new Trabajador ();
  Sensor sensor0 = new Sensor (0);
  Sensor sensor1 = new Sensor (1);
  Sensor sensor2 = new Sensor (2);
  
  semsensores [0] = new Semaphore (1, true);
  semsensores [1] = new Semaphore (1, true);
  semsensores [2] = new Semaphore (1, true);
  

  trabajador.start ();
  sensor0.start ();
  sensor1.start ();
  sensor2.start ();
 }

}




Dos tipos de procesos A y B entran en una habitación. Un proceso de tipo A no puede marcharse de la habitación hasta que no ha visto 2 procesos de tipo B. Un proceso de tipo B no puede marcharse de la habitación hasta que no ha visto 1 proceso de tipo A. Cualquier proceso (A o B) se marcha de la habitación en cuanto ha visto el número de procesos que necesita del otro tipo (no espera ninguna otra condición). Suponiendo que tienes NA procesos de tipo A y NB de tipo B, implementa este sistema utilizando un objeto sala que sincroniza a los procesos de tipo A y B, y que proporciona los métodos
void entraA(int id); y void entraB(int id);

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.locks.*;


 public  class Sala {
 
 static Lock l = new ReentrantLock(true); 
 static Condition salirA= l.newCondition();
 static Condition salirB = l.newCondition();
 static List<Integer> listaA = new ArrayList<Integer>();
 static List<Integer> listaB = new ArrayList<Integer>();
 static int [] vistosA;
 static int [] vistosB;
 static ProcesoA [] procesosA;
 static ProcesoB [] procesosB;
 
 public void entraA(int id){
  // Un proceso de tipo A no puede marcharse de la
  // habitación hasta que no ha visto 2 procesos de tipo B
  l.lock();
  try{
  listaA.add(id);
  
  System.out.println("Proceso A "+ id + " entra en la sala");
  
  vistosA[id] = listaB.size();
  System.out.println("\t Proceso A" + id + " ve a los procesos B "+ listaB.toString());
  
  for(int b: listaB){
   vistosB[b]++;
   System.out.println("\t Procesos A "+ id +" y B "+ b + " se ven");
  }
  salirB.signalAll();
  
  
  
  while(vistosA[id] < 2){
   try {
    salirA.await();
   } catch (InterruptedException e) {e.printStackTrace();}
  }
  
  
  listaA.remove(new Integer(id));
  System.out.println("Proceso A "+ id + " ha salido de la sala");
  } finally {
   l.unlock();
  }

  
 }
 
 public void entraB(int id){
  //Un proceso de tipo B no puede marcharse de la habitación hasta
  // que no ha visto 1 proceso de tipo A.
  l.lock();
  try{
  listaB.add(id);
  System.out.println("Proceso B "+ id + " entra en la sala");
  
  vistosB[id] = listaA.size();
  System.out.println("\t Proceso B "+id + " ve a los procesos A "+ listaA.toString());
  
  for(int a: listaA){
   vistosA[a]++;
   System.out.println("\t Procesos A "+ a +" y B "+ id + " se ven");
  }
  salirA.signalAll();
  
  while(vistosB[id] < 1){
   try {
    salirB.await();
   } catch (InterruptedException e) {e.printStackTrace();}
  }
  
  
  listaB.remove(new Integer(id));
  System.out.println("Proceso B "+ id + " sale de la sala");
  } finally {
   l.unlock();
  }
 }
 
 static public class ProcesoA extends Thread{
  int id;
  Sala sala;
  public ProcesoA(int id, Sala s){
   this.id = id;
   this.sala = s;
  }
  public void run(){
   this.sala.entraA(this.id);
  }
 }
 
 
 static public class ProcesoB extends Thread{
  int id;
  Sala sala;
  public ProcesoB(int id, Sala s){
   this.id = id;
   this.sala = s;
  }
  public void run(){
   this.sala.entraB(this.id);
  }
 }
 
 public static void main(String[] args) {
  Random r = new Random();
  int NA = r.nextInt(5)+2;
  int NB = r.nextInt(5)+2;
  System.out.println("NA = "+ NA + " NB = "+ NB);
  Sala s = new Sala();
  vistosA = new int[NA];
  vistosB= new int[NB];
  procesosA = new ProcesoA [NA];
  procesosB = new ProcesoB[NB];
  
  for(int i =0; i < NA; i++){
   procesosA[i] = new Sala.ProcesoA(i,s); 
  }
  for(int i =0; i < NB; i++){
   procesosB[i] = new Sala.ProcesoB(i,s); 
  }
  
  for(int j =0; j < NB; j++){
   procesosB[j].start();
  }
  for(int i =0; i < NA; i++){
   procesosA[i].start();
  }
  

 }

}

viernes, 16 de mayo de 2014

Algoritmos de Ordenación: QuickSort en C++

Hola de nuevo gente. Vaya lío que tenemos últimamente entre trabajos y exámenes U.u'.
Por suerte he pillado tiempo y he recodeado el Quicksort para C++. El código en sí es casi idéntico, pero  hay pequeños detalles que muestro con los comentarios. Si no sabéis como trabaja este algoritmo, os remito al post anterior.

Aquí tenéis el código:

// QuickSort.cpp: Aplicación del algoritmo QuickSort en C++
// Adrián Muñoz Lloret.
#include <iostream>  //para cin y cout
#include <stdlib.h>  //para el rand()

using namespace std;

void quickSort(int *A, int izq, int der) {  
 //En C y C++ los arrays son punteros, por lo que hay que poner '*A'.
 int piv = A[izq];
 int i = izq;
 int j = der;
 int aux;

 while (i < j) {
  while (A[i] <= piv && i < j) i++;
  while (A[j] > piv) j--;
  if (i < j) {
   aux  = A[i];
   A[i] = A[j];
   A[j] = aux;
  }
 }

 A[izq] = A[j];
 A[j] = piv;
 if (izq<j - 1)
  quickSort(A, izq, j - 1);
 if (j + 1 <der)
  quickSort(A, j + 1, der);

}

int main() {
 int A[10];
 cout << " El array de valores es: " << endl;
 for (int i = 0; i < 10; i++) {
  A[i] = rand();
  cout << A[i] << " ";
 }
 cout << endl << " Y el array de valores ordenados es: " << endl;
 quickSort(A, 0, 9);

 for (int i = 0; i < 10; i++) {
 // A[i] = rand();   Comento esto para que solo lo muestre.
  cout << A[i] << " ";
 }
 system("pause > nul");
 return 0;
}


Espero que os sirva y hasta dentro de poco, espero :)

Saludos ;)

domingo, 11 de mayo de 2014

Algoritmos de Ordenación: QuickSort en Java

Buenas gente. Llevo ya tiempo planteándome hacer entradas con algoritmos de ordenación y búsqueda (sobre todo). Y me he decidido a hacer el primero.

QuickSort fue desarrollado por Hoare en 1960 y se basa en le técnica de 'divide y vencerás' para ordenar un array de elementos. Para ello se toma un elemento cualquiera del array al que llamaremos 'pivote' y todos los elementos menores los movemos a su izquierda y los mayores a su derecha. A continuación se realiza lo mismo con las dos partes.
Sería algo así:
Una posible implementación del código (no la única) sería la siguiente:

public class quicksort {
 public static void quicksort(int A[], int izq, int der) {

    int piv=A[izq];      // tomamos el primer elemento como pivote
    int i=izq;       // i realiza la búsqueda de izquierda a derecha
    int j=der;       // j realiza la búsqueda de derecha a izquierda
    int aux;
   
    while(i<j){               // mientras no se crucen...
       while(A[i]<=piv && i<j) i++;  // busca un elemento mayor que pivote,
       while(A[j]>piv) j--;         // busca un elemento menor que pivote,
       if (i<j) {                     // si los encuentra y no se han cruzado...                     
           aux= A[i];                 // los intercambia.
           A[i]=A[j];
           A[j]=aux;
       }
     }
     A[izq]=A[j];      // colocamos el pivote en su lugar de la forma [menores][pivote][mayores]
     A[j]=piv;       
     if(izq<j-1)
        quicksort(A,izq,j-1);   // ordenamos mitad izquierda
     if(j+1 <der)
        quicksort(A,j+1,der);   // ordenamos mitad derecha
  }
}

Pues gente, Veréis que tampoco es demasiado complejo no? Tengo ganas de empezar con algunos más avanzados ^^ Saludos, y espero que os guste tanto como a mi todo esto :)

miércoles, 7 de mayo de 2014

Ejercicios C++: Registros y arrays (II)

Dada una matriz bidimensional de N×M elementos de tipo entero, implementar un programa
que lea dicha matriz y visualice por pantalla el mayor elemento de la matriz junto con la fila
y columna en la que se encuentra. Si el elemento mayor aparece varias veces, se deja a
criterio del alumno cuál seleccionar.
#include <iostream>
using namespace std;

typedef int TFilas[100];
typedef TFilas TMatriz[100];

void leerDimension(unsigned& n, unsigned& m){
 cout << "Introduce número de filas: ";
 cin >> n;
 cout << "Introduce número de columnas: ";
 cin >> m;
}

void leerMatriz(TMatriz& matriz, unsigned nf, unsigned nc){
 cout << "Introduce los valores de la matriz."<< endl;
 for(unsigned f = 0; f < nf; f++){
  for(unsigned c= 0; c < nc; c++){
   //cout << "Fila "<< f+1 <<". Columna "<<c+1<<"->";
   cin >> matriz[f][c];
  }
 }
}

void buscarMayor(const TMatriz& matriz, unsigned nf, unsigned nc){
 int mayor = matriz[0][0];
 int columna=1, fila=1;

 for(unsigned f = 0; f < nf; f++){
  for(unsigned c= 0; c < nc; c++){
   if(matriz[f][c] > mayor){
    mayor = matriz[f][c];
    columna = c+1;
    fila = f+1;
   }
  }
 }

 cout << "El mayor elemento de la matriz es el " <<mayor << " situado en la fila "<<fila<< " y la columna "<<columna;

}

int main() {
 cout << "Buscar el mayor valor de una matriz." << endl; 
 unsigned n, m;
 TMatriz matriz;
 leerDimension(n,m);
 leerMatriz(matriz, n, m);
 buscarMayor(matriz, n, m);
 return 0;
}

Dada una matriz bidimensional de N×N elementos de tipo entero, implementar un programa que indique si esa matriz es simétrica. Una matriz es simétrica si aij = aji para todo i distinto de j con i, j =1,2,3,4,...,N.

#include <iostream>
using namespace std;

typedef int TFilas[100];
typedef TFilas TMatriz[100];

void leerDimension(unsigned& n){
 do{
 cout << "Introduce número de filas y columnas (<100) : ";
 cin >> n;
 }while(n < 1 || n > 100);
}

void leerMatriz(TMatriz& matriz, unsigned n){
 cout << "Introduce los valores de la matriz."<< endl;
 for(unsigned f = 0; f < n; f++){
  for(unsigned c= 0; c < n; c++){
   //cout << "Fila "<< f+1 <<". Columna "<<c+1<<"->";
   cin >> matriz[f][c];
  }
 }
}

bool simetrica(const TMatriz& matriz, unsigned n){
 bool a = true;
 for(unsigned i = 1; i<= n; i++){
  for(unsigned j = 1; j<= n; j++){
   if(i!=j){
    if(matriz[i][j]!=matriz[j][i]){
     a = false;
    }

   }
  }
 }
 return a;
}

int main() {
 cout << "Comprobar si una matriz es simétrica." << endl; // prints !!!Hello World!!!
 unsigned n;
 TMatriz matriz;
 leerDimension(n);
 leerMatriz(matriz, n);
 if(simetrica(matriz,n)){
  cout << "La matriz es simétrica.";
 }else{
  cout << "La matriz no es simétrica";
 }
 return 0;
}


Un cuadrado mágico de orden n es una ordenación de los números 1 a n2 en una tabla
cuadrada de manera que la suma de cada fila y cada columna y las dos diagonales
principales es la misma.
Sea typedef unsigned Cuadrado[N][N];
Diseñar la siguiente función:
bool Es_Magica(const Cuadrado& A);
// Devuelve true si A es un cuadrado mágico y false en caso contrario
#include <iostream>
using namespace std;

typedef unsigned TFilas[100];
typedef TFilas TMatriz[100];

void leerDimension(unsigned& n){
 do{
 cout << "Introduce número de filas y columnas (<100) : ";
 cin >> n;
 }while(n < 1 || n > 100);
}

void leerMatriz(TMatriz& matriz, unsigned n){
 cout << "Introduce los valores de la matriz."<< endl;
 for(unsigned f = 0; f < n; f++){
  for(unsigned c= 0; c < n; c++){
   //cout << "Fila "<< f+1 <<". Columna "<<c+1<<"->";
   cin >> matriz[f][c];
  }
 }
}

unsigned sumaFila(const TMatriz& matriz, unsigned n, unsigned fila){
 unsigned suma = 0;
 for(unsigned i = 0; i < n; i++){
  suma+= matriz[fila][i];

 }

 return suma;
}

bool sumaFilas(const TMatriz& matriz, unsigned n, unsigned& ant1){
 bool sumasNoIguales= true;
 unsigned i = 1;
 ant1 = sumaFila(matriz, n, 0);
 while(sumasNoIguales== true && i < n){
  if(ant1 == sumaFila(matriz,n, i)){
   sumasNoIguales = true;
  }else{
   sumasNoIguales = false;
  }
  i++;
 }
 if(sumasNoIguales== true){
   cout << "Suma de las filas: "<< ant1<< endl;
 }
 return sumasNoIguales;
}

unsigned sumaColumna(const TMatriz& matriz, unsigned n, unsigned columna){
 unsigned suma = 0;
  for(unsigned i = 0; i < n; i++){
   suma+= matriz[i][columna];

  }

  return suma;
}

bool sumaColumnas(const TMatriz& matriz, unsigned n, unsigned& ant2){
 bool a = true;
 unsigned i = 1;
 ant2 = sumaColumna(matriz, n, 0);
 while(a== true && i < n){
  if(ant2 == sumaColumna(matriz,n, i)){
   a = true;
  }else{
   a = false;
  }
  i++;
 }
 if(a== true){
  cout << "Suma de las columnas: "<< ant2<< endl;
 }
 return a;
}


unsigned sumaDiagonalP(const TMatriz& matriz, unsigned n){
 unsigned suma = 0;
 for(unsigned i = 0; i< n; i++){
   for(unsigned j = 0; j< n; j++){
    if(i==j){
     suma += matriz[i][j];
    }
   }
  }
 cout << "Suma diagonal principal: "<< suma << endl;
 return suma;
}

unsigned sumaDiagonalS(const TMatriz& matriz, unsigned n){
 unsigned suma = 0;
 unsigned j = n-1;
 for(unsigned i = 0; i < n; i++){
  suma += matriz[i][j];
  j--;
 }
 cout << "Suma diagonal secundaria: "<< suma << endl;
 return suma;
}

bool Es_Magica(const TMatriz& A, unsigned n, unsigned ant1, unsigned ant2){
 bool es=false;
 bool sumaFilasIgual, sumaColumnasIgual;
 sumaFilasIgual = sumaFilas(A, n, ant1);
 sumaColumnasIgual = sumaColumnas(A, n,ant2);

 if(ant1 == ant2){
 if(sumaFilasIgual== true && sumaColumnasIgual== true){

  if(sumaDiagonalP(A, n) == sumaDiagonalS(A,n) ){
    es = true;
   }
 }
 }
 return es;
}

int main() {
 cout << "Averiguar si es un cuadrado mágico." << endl; // prints !!!Hello World!!!
 unsigned n;
 TMatriz matriz;
 leerDimension(n);
 leerMatriz(matriz, n);
 unsigned ant1=0, ant2=0;
 bool es;
 es = Es_Magica(matriz,n,ant1,ant2);

 if(es){
  cout << endl;
  cout << "Es cuadro mágico.";
 }else{
  cout << endl;
  cout << "No es cuadrado mágico.";
 }






 return 0;
}

Para realizar operaciones con números complejos, podemos definir el siguiente tipo:
struct TComplejo {
double p_real, p_imaginaria;
}
Se pide implementar un programa que dado un array de números complejos, imprima por
pantalla el número complejo de mayor módulo.
#include <iostream>

#include <math.h>
using namespace std;

const unsigned MAXIMO = 2;

struct TComplejo {
 double p_real, p_imaginaria;
};

typedef TComplejo TArrayComplejos[MAXIMO];




void leerArray(TArrayComplejos& complejos){
 cout << "Introduce "<<MAXIMO<<" números complejos."<< endl;
 for(unsigned i=0; i < MAXIMO; i++){
  cout << i+1<<".Parte real: ";
  cin >> complejos[i].p_real;
  cout << i+1<<".Parte imaginaria: ";
  cin >> complejos[i].p_imaginaria;
 }
}
void mostrarComplejo(TComplejo  a){
 cout << a.p_real << "+" << a.p_imaginaria <<"i" << endl;
}
void mostrarArray(const TArrayComplejos& complejos){
 cout << "El array de números es: "<< endl;
 for(unsigned i=0; i< MAXIMO; i++){
  mostrarComplejo(complejos[i]);
 }
}

double moduloComplejo(TComplejo num){
 double modulo;
 modulo = sqrt(pow(num.p_imaginaria,2)+ pow(num.p_real, 2));
 return modulo;
}

void buscarMayor(const TArrayComplejos& complejos){
 double mayor = moduloComplejo(complejos[0]);
 TComplejo resultado = complejos[0];

 for(unsigned i=1; i <= MAXIMO; i++){
  if(moduloComplejo(complejos[i]) > mayor ){
   mayor = moduloComplejo(complejos[i]);
   resultado = complejos[i];
  }
 }




 cout << "El complejo de mayor módulo es ";
 mostrarComplejo(resultado);
 cout << endl;

}


int main() {
 cout << "Imprime por pantalla el número complejo de mayor módulo." << endl; // prints !!!Hello World!!!
 TArrayComplejos complejos;
 leerArray(complejos);
 mostrarArray(complejos);

 buscarMayor(complejos);

 return 0;
}
La regla para generar el cuadrado mágico (si n es impar) del ejercicio 3 es la siguiente:

Se empieza con 1 en la mitad de la primera fila, a continuación subir a la izquierda
diagonalmente (si en este proceso se pasa el borde del cuadrado hay que considerar
como si el plano entero estuviese recubierto con dicho cuadrado) hasta alcanzar una
casilla del cuadrado llena; a continuación bajar un espacio a partir del último
cuadrado que se rellenó y continuar.

Diseñar un algoritmo que construya un cuadrado mágico para cualquier constante N impar
dada. Construir un programa que solicite dicho valor al usuario y visualice su cuadrado
mágico por pantalla.

#include <iostream>

using namespace std;


typedef unsigned TFilas[100];
typedef TFilas TMatriz[100];

void leerDimension(unsigned& n){
 do{
 cout << "Introduce número de filas y columnas (<100) : ";
 cin >> n;
 }while(n < 1 || n > 100);
}

void inicializarMatriz(TMatriz& matriz, unsigned n){

  for(unsigned f = 0; f < n; f++){
   for(unsigned c= 0; c < n; c++){
    matriz[f][c] =0;
   }
  }
}

void CuadradoMagico(TMatriz& matriz, unsigned n){
 unsigned fila = 0;
 unsigned nfila;
 unsigned columna = unsigned(n/2);
 unsigned ncolumna;
 for(unsigned i=1; i <= n*n; i++){
  if(matriz[fila][columna] == 0){
   matriz[fila][columna] = i;
  } else {
   fila++;
   matriz[fila][columna] = i;
  }

  nfila = fila;
  ncolumna= columna;

   if(columna == 0){
    ncolumna = n-1;
   }else{
    ncolumna--;
   }

   if(fila == 0){
    nfila = n-1;
   }else{
    nfila--;
   }
  if(matriz[nfila][ncolumna] == 0){
   fila = nfila;
   columna= ncolumna;
  }else{
   //columna = ncolumna;
   fila++;
  }

 }
}

void imprimirMatriz(const TMatriz& matriz, unsigned n){
 for(unsigned f = 0; f < n; f++){
   for(unsigned c= 0; c < n; c++){
    cout <<"\t "<< matriz[f][c];
   }
   cout << endl;
  }
}



int main() {

 TMatriz matriz;
 unsigned n;
 leerDimension(n);
 inicializarMatriz(matriz, n);
 CuadradoMagico(matriz,n);
 imprimirMatriz(matriz, n);
 return 0;
}
Escribir un programa que lea una sucesión de 10 números naturales, encuentre el valor máximo y lo imprima junto con el número de veces que aparece, y las posiciones en que esto ocurre. El proceso se repite con el resto de la sucesión hasta que no quede ningún elemento por tratar.

Ejemplo de entrada: 7 10 143 10 52 143 72 10 143 7
Salida generada: 143 aparece 3 veces, en posiciones 3 6 9.
                        72 se repite 1 vez, en posición 7.
                         ...
                        7 aparece 2 veces, en posiciones 1 10.
#include  <iostream>
using namespace std;

const unsigned MAXIMO =10;
typedef unsigned TArray[MAXIMO];

void leerArray(TArray& numeros){
 cout << "Introduce 10 números naturales." << endl;
 for(unsigned i= 0; i < MAXIMO; i++ ){
  cin >> numeros[i];
 }
}
unsigned contarNumero(const TArray& numeros, unsigned num){
 unsigned contador=0;

 for(unsigned i= 0; i < MAXIMO; i++){
  if(numeros[i]== num){
   contador++;
  }
 }
 return contador;

}

void buscarPosiciones(const TArray& numeros, unsigned num, unsigned contador){
 unsigned i = 0;
 unsigned c= 0;

 if(contador == 1){
  cout << " vez, en la posición ";
 }else{
  cout << " veces, en posiciones ";
 }
 while(i < MAXIMO  && c <= contador){
  if(numeros[i]== num){
   cout << i +1 << " ";
   c++;
  }
  i++;
 }
 cout <<"" << endl;
}
unsigned buscarMayor(const TArray& numeros){
 unsigned mayor = numeros[0];
 for(unsigned i= 1; i < MAXIMO; i++){
  if(numeros[i] > mayor){
   mayor = numeros[i];
  }
 }
 return mayor;
}

void eliminarUsado(TArray& numeros, unsigned mayor){
 for(unsigned i= 0; i < MAXIMO; i++){
  if(numeros[i] == mayor){
   numeros[i] = 0;
  }
 }
}



int main() {
 unsigned mayor, contador;
 TArray numeros;
 leerArray(numeros);
 mayor = buscarMayor(numeros);

 while(mayor != 0){
  cout << mayor << " aparece ";
   contador = contarNumero(numeros, mayor);
   cout << contador;
   buscarPosiciones(numeros, mayor, contador);
   eliminarUsado(numeros, mayor);
   mayor = buscarMayor(numeros);
 }



 return 0;
}
Ale.

lunes, 5 de mayo de 2014

Dividir en cifras un número. C++

Buenas gente, hoy os traigo algo facilito debido a que ya he visto a muchos 'novatillos' en la web preguntando como se hace esto. Lo que voy a hacer es coger un número y dividirlo en sus cifras separadas. Para ello primero haré una función que me devuelva el número de cifras del número y otra que vaya calculándolos.
#include <iostream>
#include <math.h>

using namespace std;


// Lo que hacemos es ir dividiendo el número entre 10, entre 100, entre 1000... Hasta que el número y el resto den lo mismo.
int cuantasCifras(int numero) {
 int divisor = 10;
 int residuo = 0;
 int cifras_aux = 0;

 while (residuo != numero){
  residuo = numero % divisor;
  divisor = divisor * 10;
  cifras_aux++;
 }
 cifras_aux--;
 return cifras_aux;
}

void dividir_en_digitos(int numero, int cifras) {

  int divisor = 10;
  int residuo = 0;
  int digito = 0;
  int cifras_aux = cifras;
 
 
  //Se eleva el divisor de forma que tenga el mismo número de cifras que nuestro número inicial
  divisor = pow(divisor, (cifras_aux));
  cout << "divisor: " << divisor << endl;
  
 while (cifras_aux >= 0){
   //El cociente son Digitos de izquiera a derecha
   digito = numero / divisor;
     
   //El residuo se convierte en el numero
   residuo = numero % divisor;
   numero = residuo;
     
   //El divisor disminuye
   divisor = divisor / 10;
   cout << "digito: " << digito << endl;
   cifras_aux--;
 }
}



int main() {
 
  int num;
  cout << "Ingrese un numero para mostrarlo separado en digitos: " << endl; 
  cin >> num; 

  dividir_en_digitos(num, cuantasCifras(num));
 
  system("PAUSE");
  return 0;
 
}
 

Bueno, espero que no lo hayais visto demasiado difícil. De ser así os aconsejo que clickeeis aquí debajo en la etiqueta de 'Básico' y miréis ahí las entradas. Si tenéis dudas con el algoritmo avisadme ;)

Nos vemos.

domingo, 4 de mayo de 2014

Comparando dos archivos de texto en C++.

Buenas gente. Hoy os traigo un pequeño proyecto muy bien comentado de un amigo donde yo he aprendido mucho y espero que vosotros también. Solo lo he probado con la extensión .txt, pero supongo que funcionaría con cualquiera. He de decir que en linux esto es innecesario puesto que se puede hacer con un simple diff, pero aquí estamos para aprender, ¿no? :p

NOTA: Debido al define limpiar, este código funciona con Windows y Linux, pero no con otros Sistemas Operativos como iOS. Sería cuestión de añadirle uno para tu sistema ;)

#include <iostream> // entrada y salida por consola
#include <fstream>  // entrada y salida por ficheros
#include <string>   // para string
#include <stdlib.h> // para system
#include <stdio.h>  //para remove
#include <iomanip>  // pata setw
using namespace std;

#ifdef _WIN32
#define  limpiar  system("cls")
#endif

#ifdef linux
#defain  limpiar   system("clear");
#endif

int main() {
 cout << "No te equivoques a la hora de escribir, la ruta, o el archivo, porque si no deberas volver a empezar...\n\n";
 cout << "\tIntroduce la ruta del primer archivo: ";
 string s1;
 getline(cin, s1);//cojo de la consola la primera ruta con espacios incluidos

 cout << "\tIntroduce la ruta del segundo archivo: ";
 string s2;
 getline(cin, s2); // y aqui la segunda ruta

 const char* Ruta1 = s1.c_str(); //Las transformo a const char ya que mas a delante
 const char* Ruta2 = s2.c_str(); //las utilizare para abrir ficheros, y si no son const char se queja el compilador
 //basicamente lo que hace s1.c_str() es asignar al puntero Ruta1 la posicion donde empieza el string, 

 ifstream File1(Ruta1, ios::in); //Abrimos los dos ficheros en modo de lectura
 ifstream File2(Ruta2, ios::in); //

 if (File1.fail() || File2.fail()){ // en el caso de que uno de los dos ficheros no exista...
  limpiar;
  cout << "Ha habido un error, escriba correctamente la Ruta o el archivo\n";
  cout << "Aprete intro para continuar";
  cin.get();  // esperamos a que aprete intro
  limpiar;
  main();     //volvemos a empezar
 }
 else {//si ambos ficheros se han encontrado y se han abierto correctamente...
  ofstream comparacion("Comparacion.txt", ios::out); //declaramos y abrimos otro fichero en modo de escritura
  bool iguales = true;
  int cont = 0, linea = 0;
  limpiar;
  cout << "Iniciando comparacion....\n";

  while (!File1.eof() && !File2.eof()) { // mientras que ninguno de los dos ficheros se haya acabado
   ++linea;
   string a, b;
   getline(File1, a); // metemos en el string a la primera linea del fichero 1
   getline(File2, b); // metemos en el string b la primera linea del fichero 2
   if (a != b) { // si son diferentes....
    ++cont;
    cout << flush << "Error numero " << cont << " en la linea " << linea << endl << flush;
    comparacion << flush << "Error numero " << cont << " en la linea " << linea << endl << flush;
    iguales = false;
    cout << setw(20) << right << s1 << " : " << a << endl;
    cout << setw(20) << right << s2 << " : " << b << endl;
    comparacion << setw(20) << right << s1 << " : " << a << endl;
    comparacion << setw(20) << right << s2 << " : " << b << endl;
   }//Sacamos por pantalla en un formato determinado las diferencias y tambien en un fichero
  }
  if (!File1.eof() && File2.eof()) {//en el caso de que hayamos llegado al final del primer fichero pero no del segundo...
   cout << "El archivo " << Ruta2 << " es mas corto que " << Ruta1 << endl;
   comparacion << "El archivo " << Ruta2 << " es mas corto que " << Ruta1 << endl;
  }
  if (!File2.eof() && File1.eof()) {//... al reves que el anterior
   cout << "El archivo " << Ruta1 << " es mas corto que " << Ruta2 << endl;
   comparacion << "El archivo " << Ruta1 << " es mas corto que " << Ruta2 << endl;
  }
  comparacion.close();//cerramos el fichero de salida!! (esto es importante cuando abrimos un fichero mas a delante se ha de cerrar)
  if (iguales) cout << "\nEnhorabuena los dos ficheros son iguales\n";
  cout << "*--------Fin de la comparacion-------*\n";
  cout << "Pulse s si quiere guardar los datos en un archivo\n En caso contrario pulse otra letra\n";
  char c;
  cin >> c;
  if (c != 's') remove("Comparacion.txt");//en el caso de que el usuario no quiera un fichero con las diferencias sacadas por la
  //consola, pues el que habiamos creado y llenado con todos los datos lo eliminamos
 }
} 

Bueno, espero que hayáis aprendido tanto como yo con esta práctica :p La verdad es que la veo muy interesante.

Saludos ;)

viernes, 2 de mayo de 2014

Hack en c++ para modificar la vida en un Juego Simple

Buenas. Os voy a hablar en esta entrada un poco de la pequeña 'investigación' que estoy haciendo. 
Mi objetivo es crear una IA que sea de capaz de jugar a un juego (cual, me lo reservo aún :p) sin que nadie se pueda dar cuenta de que es un bot. Para ello ahora mismo estoy empezando desde abajo, viendo como se relaciona un juego más básico con el pc. Aquí os esplicaré como crear un programa que te cambie la vida a la que tu quieras en el juego. El juego que voy a usar en esta prueba es el Hack, Slash, Loot (Versión 8), que es un pequeño juego de 8MB que podríais encontrar en la 'bahía del pirata' (por ejemplo xP) pero que no pondré enlaces porque tiene derechos de autor (está en Steam). Podría hacer publicidad y deciros que podeis conseguirlo gratis y original para Steam o Desura juntando puntos en ésta página. Si quisierais saber como conseguir puntos rápidos avisadme :p.

Bueno, voy a empezar consiguiendo lo primero que me hace falta... La dirección de memoria de la vida. Para ello necesitáis un programa llamado Cheat Engine, el cual podéis descargarlo de su página original o de Mega (me interesa más que lo descargueis de éste segundo :p).

Bueno. Primero abriremos el Juego. En mi caso lo he dejado como está todo y le he dado directamente a Start New Game (a la derecha del todo). Vemos que la vida comienza en 30. 

Abrimos Cheat Engine y clickeamos en el icono que hay arriba, debajo de 'File' y elegimos el juego que vamos a modificar. Escribimos un 30, seleccionamos 'Exact Value' y le damos a First Scan. Ésto buscará todos los registros que tengan un 30 como valor.
                    


A mi me han salido 665 resultados. Os aviso que las direcciones van a variar, no tiene que daros exactamente los mismos resultados que a mi.

Ahora vamos a movernos en el juego y perder algo de vida. Lo más fácil es (cuando haya un enemigo cerca) clickear en nosotros, pues esto hará pasar un turno. Cuando hayamos perdido vida, apuntamos en Value la nueva vida y le damos a Next Scan. Next Scan es una herramienta muy buena ya que lo que hace es buscar el valor entre los resultados que nos habían salido anteriormente. De ésta forma busca los resultados que antes eran 30 y ahora (en mi caso) 24. A mi solo me ha hecho falta hacer el Next Scan una vez. Si os han salido más solo debéis volver a perder vida y hacer otro Next Scan.

Hacemos doble click en la dirección y de esa forma la guardamos abajo. Ya tenemos la dirección dinámica (al final explicaré lo malo de éste tipo de direcciónes) de la vida.

Ahora vamos a ir a nuestro IDE de C++ (en mi caso Visual Studio 2013) y vamos a empezar a implementar el pequeño cheat, pero antes...
Un poco de información antes de comenzar
¿Qué son las direcciones de memoria dinámicas?
La memoria dinámica es un espacio de almacenamiento que se solicita en tiempo de ejecución. Esto quiere decir que estas direcciones, las cuales se solicitan "al momento" no siempre serán iguales. Varían, a diferencia de las direcciones de memoria estáticas (las que veremos en el próximo tutorial).
¿Qué es un puntero?
Un puntero o apuntador es una variable que referencia una región de memoria; en otras palabras es una variable cuyo valor es una dirección de memoria.Mas claro que eso, imposible.
¿Qué es un HANDLE?
Un handle (en español "manejador") es una referencia a un objeto. Wikipedia no podría ser mas claro :Los handles son usados cuando una aplicación hace referencia a bloques de memoria u objetos manejados por otro sistema.
HWND se usa para referenciar a una ventana (pertenece a user32)HANDLE para referenciar a un objeto. (pertenece a kernel32)
Fuente

El código es el siguiente:

#include <iostream>
#include <windows.h>

using namespace std;

int main()
{
 // Primero buscaremos la ventana activa.
 HWND hVentana;
 if (!(hVentana = FindWindow(NULL, "Hack, Slash, Loot.")))
 {
  MessageBox(NULL, "No se pudo encontrar la ventana", "Error", MB_OK);
  return -1;
 }
 
 system("echo Encuentra la Ventana :)");

 DWORD pid;
 if (!(GetWindowThreadProcessId(hVentana, &pid)))
 {
  MessageBox(NULL, "No se puede encontrar el ID del proceso", "Error", MB_OK);
  return -1;
 }
 system("echo Encuentra el pid :)");

 HANDLE hProcess;
 if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid)))
 {
  MessageBox(NULL, "No se pudo obtener el handle del proceso", "Error", MB_OK);
  return -1;
 }
 system("echo Encuentra el proceso :)");

 DWORD Buffer;
 DWORD BytesT;
        // Aqui debajo donde pone 0x108C76B0 teneis que poner 0x<vuestra direccion de memoria>
 ReadProcessMemory(hProcess, (LPCVOID)0x108C76B0, &Buffer, sizeof(Buffer), &BytesT);
 printf("\n La vida es de %d \n", Buffer);
 system("pause > nul");

 //Ya hemos leido la dirección. 
 //Ahora vamos a escribir en ella :p CRACKERS!!!!!
 long newBuffer;
 char *aux = "";
 cout << endl << "Introduce la nueva Vida : ";
 cin >> newBuffer;
 if (!WriteProcessMemory(hProcess, (LPVOID)0x108C76B0, &newBuffer, sizeof(newBuffer), &BytesT))
 {
  MessageBox(NULL, "No se pudo escribir la direccion de memoria", "Error", MB_OK);
  return -1;
 }
 cout << endl << "Vida Cambiada con Exito. =)" << endl;
 system("pause");
 return 0;
}

Ahora compilamos y... TACHAN!!


250 de vida, a ver quien se mete con nosotros. Ahora os diré una pequeña trampa. Si aún no habéis cerrado el Cheat Engine (no deberíais, pues no os he dado permiso :p) y clickeais abajo en la dirección guardada, en el campo value; podéis escribir un valor y se cambiará igual que como lo hemos hecho.
¿ENTONCES PARA QUÉ HEMOS HECHO TANTO LÍO DE CÓDIGO?
No me peguéis xD. Como ya he dicho, lo que quiero es crear un bot. Para ello el bot deberá leer una dirección de memoria y escribir en otras, ¿no? Pues al usar ReadProcessMemory y WriteProcessMemory ya hemos empezado a enterarnos de como vamos a poder hacer que nuestro bot se comunique con el entorno.

Ahora las malas noticias. Cuando cerremos el juego y lo volvamos a abrir la dirección de memoria habrá cambiado (eso significa que es dinámica). Por lo que (otro día cuando me entere yo mejor :p) subiré cómo arreglar esto.

Ya para acabar debo agradecer a Mad Antrax su tutorial que me ha venido de perlas. Os lo recomiendo.

Saludos ;)