Category Archives: Programas

Gráfica de Seno y Coseno en C++

Juand a través de un comentario me pidió ayuda con un programa que grafique utilizando gotoxy las gráficas de seno y coseno en c++. El programa me pareció interesante y, aunque tuve que desempolvar el Borland C++ que usaba en la prepa, lo hice… feo, pero lo hice.

A mi parecer, para graficar por ejemplo la función seno, hacen falta 3 pasos:

1. Hacer un ciclo de 0 a 360º (con aumentos de 5 queda muy bien) con for, algo muy normal.

2. Calcular, obviamente, el seno de cada valor. Para esto la librería math.h nos regala la función sin(). Su uso es el obvio, pero el asunto es que todas las funciones trigonométricas que usa c++ trabajan en radianes. Es decir que primero tendremos que convertir nuestro ángulo en radianes y luego ya sacar el seno. Si la variable ‘i’ contiene el ángulo y tenemos ya definida la constante PI, la función quedaría así:
sin(i/180*PI)

3. Luego viene la parte más rara, convertir ese valor en un entero que pueda meter como coordenada en un gotoxy. Si tenemos una variable int y y la igualamos a nuestra función anterior podría quedar bien si multiplicamos por 10:
int x, y; y = sin(i/180*PI)*10; gotoxy(x,y);
Nos quedaría nuestra gráfica en una escala 1:10, pero al correr el programa veremos que hay muchos valores de seno que son 10 (por el redondeo) y por lo tanto la gráfica se ve achatada.

Para mejorar un poco eso (de todos modos queda un poco fea) podemos usar la función ceil() incluida también en la librería math.h que nos redondea los decimales. Y esta vez multiplicamos por 20, redondeamos, dividimos entre 2 y convertimos a int. Nos vuelve a quedar escala 1:10 (¿o 10:1 …? no se) pero ya no hay tantas cantidades amontonadas en el 10 y -10.

El programa ya listo para graficar seno está aquí abajo, obviamente para graficar coseno sólo hay que cambiar la función sin por cos, y copiar, pegar y hacer un menú no debe ser difícil.

#include
#include
#include
#define PI 3.14159265

int main()
{
	int x=2, y;
	for(float i=0; i<=360; i+=5)
	{
		y = ceil(sin(i/180*PI)*20)/2;
		gotoxy(x, 12-y);printf("o");
		x++;
	}
	getch();

	return 0;
}

gráfica seno

Advertisements

Calcular ángulos de un triángulo en C++

En el post anterior vimos cómo saber si un triángulo es rectángulo, acutángulo u obtusángulo en C++, y les anticipé que haría una nueva versión del mismo programa pero que nos calculara además los ángulos del triángulo.

El programa es este.

#include
#include
using namespace std;

#define PI 3.14159265 // nuNcA cAmbieZz we!!
int main()
{
    float a, b, c, A, B, C;
    cout <> a;
    cout <> b;
    cout <> c;
    A = acos((b*b+c*c-a*a)/(2*b*c))*180/PI;
    B = acos((a*a+c*c-b*b)/(2*a*c))*180/PI;
    C = acos((a*a+b*b-c*c)/(2*a*b))*180/PI;
    if(A == 90 || B == 90 || C == 90)
        cout << "El triangulo es rectangulo. ";
    if(A < 90 && B < 90 && C < 90)
        cout < 90 || B > 90 || C > 90)
        cout << "El triangulo es obtusangulo. ";
    cout << "nY sus angulos son: A:" << A << " , B:" << B << " y C:" << C;

    cin.get();cin.get();
}

Para calcular los ángulos utilizamos la ley de cosenos, de hecho en el anterior también lo utilizamos pero no completamente (la ley de cosenos es una ‘ampliación’ del teorema de pitágoras). La ley de cosenos la vemos comúnmente como:
a2 = b2 + c2 -2(b*c)*cos(A)
Si la despejamos en cos(A), nos queda:
cos(A) = (b2 + c2 - a2) / 2(b*c)
Si despejamos A (o sea el ángulo), obtenemos:
A = arccos(b2 + c2 - a2 / 2(b*c))
Que es lo que utilizamos calcular los ángulos, lamentablemente la función que nos da C++ en su librería math.h, acos() nos devuelve el resultado en radianes. Para convertirlo a grados solo tenemos que multiplicar el resultado por 180/PI. Ahora que ya tenemos los tres ángulos de nuestro triángulo, es facilísimo saber cuando es cada tipo de triángulo.

La función acos() está en la librería math.h y sirve para encontrar el arco coseno. En esta librería hay muchas funciones muy útiles: math.h

Otro detalle sencillo pero que no habíamos visto es el asunto de PI. Al principio del programa nos encontramos con:
#define PI 3.14159265
Esto significa que estamos declarando una constante con el nombre PI y con un valor de 3.14159265. Una constante, como su nombre lo indica, nunca cambia a lo largo del programa.

Bueno, pues fue un programa bastante entretenido, me gustó hacerlo 🙂

Saber si un triángulo es rectángulo, acutángulo u obtusángulo en C++

Emanuel por medio de un comentario me pidió ayuda para hacer un programa en c++ que nos dijera si un triángulo es rectángulo, acutángulo u obtusángulo pidiendo solamente los lados. El programa me pareció interesante de hacer y pues lo hice 🙂

El programa resulta bastante sencillo, pero para deducir cómo hacerlo está un poco complicado. Veamos la siguiente imágen:

Triángulos

El triángulo 1 es un clásico triángulo rectángulo. Si aumentáramos el lado c de 5 a 6 obviamente el ángulo aumentaría y por lo tanto sería un triángulo obtusángulo (2). Si por el contrario, disminuyéramos el lado de c 5 a 4, el ángulo disminuiría y por lo tanto sería un triángulo acutángulo (3).

Sabiendo esto veamos cómo se comporta Pitágoras en cada caso (o sea no él, su teorema):

Si despejamos su famoso teorema obtenemos que a2 + b2 – c2 = 0.

Veamos como se comporta este teorema en nuestro triángulo 1:
32 + 42 - 52 = 0
¡Listo!, ya sabemos que el triángulo es rectángulo, porque el teorema de Pitágoras sólo sirve para triángulos rectángulos.

Ahora con el triángulo 2 (obtusángulo):
32 + 42 - 62 = -11
¡Un número negativo! Con los triángulos obtusángulos el teorema de Pitágoras da números negativos.

Y por último el triángulo 3 (acutángulo):
32 + 42 - 42 = 9
¡Un número positivo! Con los triángulos acutángulos el teorema de Pitágoras da números positivos.

Ahora que ya sabemos cómo identificar cada triángulo nos surge otro problema: El usuario sólo va a introducir tres lados cualquiera, ¿cómo saber cual es a, cual es b y cual es c? Pues no hay forma de saberlo, hay que hacer cada paso tres veces tomando el teorema como a2 + b2 – c2, luego a2 + c2 – b2 y al final b2 + c2 – a2.

Ahora si, veamos el programa:

#include
using namespace std;

int main()
{
    int a, b, c, A, B, C;
    cout <> a;
    cout <> b;
    cout <> c;
    A = (b*b+c*c-a*a);
    B = (a*a+c*c-b*b);
    C = (a*a+b*b-c*c);
    if(A == 0 || B == 0 || C == 0)
        cout < 0 && B > 0 && C > 0)
        cout << "El triangulo es acutangulo. ";
    if(A < 0 || B < 0 || C < 0)
        cout << "El triangulo es obtusangulo. ";

}

La única parte no explicada es la de las condiciones. Si en cualquiera de los tres formas de tomar el teorema nos resulta 0 es rectángulo, por lo tanto se usa ||. Para ser acutángulo, las tres formas del teorema deben ser mayores a 0, se usa &&. Con una sola forma del teorema que resulte menor a 0 es obtusángulo, se usa ||. Para mayor información de esos operadores leer esto: Operadores lógicos es C++.

¿Cómo ven el programita? Está sencillo ¿no? Tal vez después haga una modificación para que además te calcule los ángulos del triángulo.

Función delay() en C++

Una función a veces útil a veces no mucho es el delay(), sirve para hacer una pausa de ‘n’ segundos. En algunos compiladores Borland esta función se incluye en la librería conio.h pero como aquí estamos del lado del software libre vamos a hacer nosotros mismos esta función. Primero veamos cómo se usa:
delay(variable_tipo_int);
es decir:
int secs=10;
delay(secs);

o
delay(numero_entero);
es decir:
delay(12);
Y claro, la función es esta:
void delay(int secs) {
for(int i = (time(NULL) + secs); time(NULL) != i; time(NULL));
}

  1. La función time(NULL) nos devuelve el segundo exacto en que estamos.
  2. Si le sumamos cierta cantidad de segundos obtenemos una fecha en el futuro.
  3. En cada vuelta del ciclo se checa si esa fecha en el futuro es diferente a la fecha actual.
  4. En cuanto las dos fechas son iguales el ciclo acaba y el programa continúa.

Veamos como se usa en un programa en c++:

#include
#include
using namespace std;

void delay(int secs) {
  for(int i = (time(NULL) + secs); time(NULL) != i; time(NULL));
}

int main()
{
    int sec;
    cout <> sec;
    delay(sec);
}

Para poder usar la función delay de esta forma es necesario ponerla en todos los programas en donde necesitemos usarla (ahora me doy cuenta que no he escrito mucho sobre funciones) e incluir siempre la librería #include<time.h> o #include<ctime>.

Generar un string aleatorio en C++

No sé, es algo que se me ocurrió y que es muy fácil de hacer. Lo único que tenemos que hacer es ver a un string no como una frase, sino como un conjunto de caracteres; y además ver a los caracteres no como letras, sino números del código ASCII.

Teniendo esto claro, es muy fácil generar un números aleatorios (que representas letras) para llenar cada elemento del arreglo que es nuestro string. Veamos:

#include
#include
#include
using namespace std;

int main()
{
    char strrnd[10];
    srand(time(NULL));
    for(int i=0; i <= 9; i++)
        strrnd[i] = 33 + rand() % (126 - 33);
    cout << strrnd;
    cin.get();
}
  1. Primero declaramos un string de nombre strrnd.
  2. Luego inicializamos nuestro random.
  3. Con un ciclo recorremos cada elemento del string.
  4. Y cada elemento lo llenamos con un número aleatorio entre 33 y 126, que en el código ASCII representan todos las símbolos letras y números normales.
  5. Y listo, ya hemos creado un string aleatorio en c++.

Si tienen duda con los números aleatorios pueden checar este post: Obtener número aleatorios en c++. Aquí pueden ver el código ASCII.

Si quieren que muestre, por ejemplo, solo letras minúsculas, tendrían que modificar la fórmula del random para que generara números entre el 97 y 122.

Triángulo de Pascal en C++

¿Han escuchado eso de que en el triángulo de pascal cada número es la suma de los dos que están sobre él? ¡PUES LES HAN MENTIDO!, eso no es más que una coincidencia y la forma mas fácil de escribirlo en el pizarrón. En realidad el triángulo de pascal es una matriz donde cada elemento es el coeficiente binomial o combinación de sus coordenadas. Las pruebas.

El caso es que para obtener el triángulo de pascal en c++ hay muchas formas, pero la que está a continuación yo la considero especial porque está basada en su propia definición.

#include
using namespace std;

int factorial(int n)
{
    if(n<2)
        return 1;
    else
        return n * factorial(n-1);
}

int combinacion(int n, int r)
{
    if(r==1)
        return n;
    else
    {
        if(n==r)
            return 1;
        else
            return factorial(n) / (factorial(r) * factorial(n - r));
    }
}

int main()
{
    for(int i=0; i<=6; i++)
    {
        for(int ii=0; ii<=i; ii++)
            cout << combinacion(i, ii) << "  ";
        cout << endl;
    }
    return 0;
}

Vamos analizándolo:

1. La primera función es para obtener el factorial de forma recursiva.

2. La segunda es para obtener el coeficiente binomial o combinación de dos números, es en esencia esta fórmula:
C(n,r) = n! / r!(n-r)!
Mas información sobre coeficientes binomiales.

3. En el main hay dos ciclos que se encargan de armar una matriz para obtener el coeficiente binomial de cada uno de ellos.

  • La primera pareja de numeros es (0,0) y su combinación es 1. Nuestro primer numero del triangulo de pascal.
  • La siguiente es (1,0) y luego (1,1) cuyas combinaciones son 1 y 1. Segunda línea.
  • Luego tenemos (2,0) (2,1) y (2,2) cuyas combinaciones son 1, 2 y 1. Tercera linea
  • Y así seguimos obteniendo nuestras líneas.

Y pues así es, el que me diga que no tiene forma de triángulo está ciego, porque si es triángulo, lo que pasa es que no es isósceles.

Primo o no ¡SIN CICLOS! en C++

Me preguntaban en los comentarios de este post: Primo o no, que si habría alguna forma de hacer ese mismo programa pero sin ciclos. Mmmm…

Pues mi primera respuesta es no. Pero hay una forma muy burda de aproximarse a él. El siguiente programa es para calcular si un número es primo o no sin ciclos y es infalible hasta el 168, a partir de ahí puede que le atine o puede que no.

#include
using namespace std;

int main()
{
    int n;
    cout <> n;
    if(n!=2 & n%2==0)
        cout << "No es primo";
    else
    {
        if(n!=3 & n%3==0)
            cout << "No es primo";
        else
        {
            if(n!=5 & n%5==0)
                cout << "No es primo";
            else
            {
                if(n!=7 & n%7==0)
                    cout << "No es primo";
                else
                {
                    if(n!=11 & n%11==0)
                        cout << "No es primo";
                    else
                    {
                        cout << "Es primo";
                    }
                }
            }
        }
    }
}
  • Como vemos, primeramente checa si n es igual a 2; si no, checa si el residuo de n/2 es cero. Si si, no es primo; si no, sigue.
  • Luego checa si n es igual a 3; si no, checa si el residuo de n/3 es cero. Si si, no es primo; si no, sigue.
  • Lo mismo con el 5, el 7 y el 11.

Con eso obtenemos un buen número de números en los que estamos seguros que no fallaremos. Si agregamos el 13, agrandamos esa cantidad; y aún mas con el 17, el 19, … como en esta versión optimizada, que tiene su primer error con el 1681 (que no es primo)

#include
using namespace std;

int main()
{
    int n;
    cout <> n;
    if((n!=2 & n%2==0)||(n!=3 & n%3==0)||(n!=5 & n%5==0)||(n!=7 & n%7==0)||
       (n!=11 & n%11==0)||(n!=13 & n%13==0)||(n!=17 & n%17==0)||(n!=19 & n%19==0)||
       (n!=23 & n%23==0)||(n!=29 & n%29==0)||(n!=31 & n%31==0)||(n!=37 & n%37==0))
        cout << "No es primo";
    else
        cout << "Es primo";
}

Pero pues de eso no se trata, los ciclos son para evitar las cantidades interminables de ifs, así que usémoslos.

Ah y recuerden que si corren un programa y su compilador no se pausa solo, tienen que agregar cin.get();cin.get(); al final del programa, antes de la llave de cierre del main.

Si llegaste aquí buscando un programa para saber si un número es primo o no, sigue el link que está al principio del post.

Centrar texto automáticamente sin gotoxy

Pues si, en este post vamos a hacer un programa en c++ que lee una frase y luego la muestra centrada en la pantalla, todo eso ¡sin usar gotoxy! wow.

Bueno, usando gotoxy sería mas fácil, pero este blog promueve el no uso de la librería conio.h (Cómo dejar de usar conio.h) así que lo vamos a hacer como les dije.

#include
#include
using namespace std;

int main()
{
    char str[100];
    cout << "Una frase: "; cin.getline(str, 100, 'n');
    int numofch = strlen(str);
    for(int i=1; i<(40-(numofch/2)); i++)
        cout << " ";
    cout << str;
    cin.get();
    return 0;
}

A la consola le caben 80 caracteres a lo largo, su mitad son 40; enseguida tenemos que averiguar el numero de caracteres que tiene la frase que se acaba de introducir y dividirlo entre dos. Supongamos que la frase es “hola”:

  1. ‘Hola’ tiene 4 caracteres.
  2. La mitad de la consola es 40.
  3. Si a los 40 le restamos la mitad de los caracteres de la frase, obtenemos el punto en donde debe comenzar la frase para quedar centrada. 40 – (4/2) = 38
  4. Ahora con un ciclo damos 38 espacios y luego imprimimos la frase.

Si quieren utilizar gotoxy, el proceso es el mismo hasta el último paso, donde guardarían el valor obtenido en una variable y luego lo pondrían en el lugar adecuado de la función.

La función strlen está en la librería string.h y nos devuelve el número de caracteres que tiene una cadena, viene de string length.

A propósito me he dado cuenta que no he hablado casi nada de la librería string.h, voy a ver si hago unos cuantos posts sobre ella.

Factorial de forma sencilla en C++

Ya vimos como calcular el factorial de un número c++ en forma recursiva, sin embargo hay una forma mucho mas fácil de entender y de aplicar (pero menos eficiente). Vamos viendo:

Si el factorial de un número es la multiplicación de cada número desde 1 hasta ese número (por ejemplo factorial de 4 = 1*2*3*4 = 24), entonces es muy sencillo crear un ciclo de 1 hasta el número pedido en c++ para hacer el cálculo.

#include
using namespace std;

int main()
{
    int num,fact=1;
    cout << "::FACTORIAL::" << endl;
    cout <> num;
    for(int i=2; i<=num; i++)
    {
        fact = fact * i;
    }
    cout << "Su factorial es: " << fact;
    cin.get();cin.get();
    return 0;
}

¿Entonces porqué el ciclo empieza en 2? Si comenzara en 1, el proceso para el numero 3 (por poner un ejemplo) sería así:

  • fact = fact * i -> fact = 1 * 1 -> fact = 1
  • fact = fact * i -> fact = 1 * 2 -> fact = 2
  • fact = fact * i -> fact = 2 * 3 -> fact = 6

Como ven, el primer paso es totalmente innecesario.

Recursividad aplicada: Torres de Hanoi

Este juego matemático es clásico de los problemas de programación. Hoy vamos a ver cómo calcular el número de movimientos necesarios para resolver el juego según el número de discos, de forma recursiva en C++.

#include
int hanoi(int n)
{
    if(n==1)
        return 1;
    else
        return 2 * hanoi(n-1) + 1;
}
int main()
{
    int disc, mov;
    printf("::TORRES DE HANOI::n");
    printf("Numero de discos: ");scanf("%i",&disc);
    printf("tMovimientos necesarios: %in", hanoi(disc));
    return 0;
}

Otro algoritmo raro. Lo que sabemos es que si tenemos 1 disco el número de movimientos es 1 y que ese es nuestro caso base (si n==1 retorna 1), a partir de ahí el número de movimientos se puede calcular si multiplicamos por dos el número de movimientos para n-1 y le sumamos 1, o sea: 2 + hanoi(n-1) + 1

  • Si son 2 discos, entonces 2 * hanoi(1) + 1 = 2 * 1 + 1 = 3
  • Si son 3 discos, entonces 2 * hanoi(2) + 1 = 2 * 3 + 1 = 7
  • etc