Ejercicios de Programación

Si eres principiante y tienes alguna consulta entra en este foro.
Responder
Mensaje
Autor
Avatar de Usuario
leosan
Mensajes: 730
Registrado: 19/04/2012 8:35 am
Ubicación: GRAN CANARIA

#91 Mensaje por leosan » 26/09/2012 10:08 am

Ya. Listas enlazadas,doblemente enlazadas y árboles. ¡Es que aún no había llegado!
Saludos!

Avatar de Usuario
Sorancio
Mensajes: 1157
Registrado: 29/05/2009 12:42 pm
Ubicación: España
Contactar:

#92 Mensaje por Sorancio » 26/09/2012 12:27 pm

¡Hola!

No me he olvidado de vosotros, pero es que estaba hasta arriba de trabajo. De vez en cuando os echaba un vistazo no creáis.

No veo que problema puedes tener al usar las estructuras...

Código: Seleccionar todo

struct estructura { struct estructura * siguiente; };

struct estructura *a, *b;

a = malloc(sizeof(*a));
b = malloc(sizeof(*b));

a->siguiente = b;
Mi página web (en inglés): http://kmr.conscell.net/

Avatar de Usuario
leosan
Mensajes: 730
Registrado: 19/04/2012 8:35 am
Ubicación: GRAN CANARIA

#93 Mensaje por leosan » 26/09/2012 1:30 pm

UUUPPPSSS !!!, anodadado me has dejado. Mañana probaré.Gracias.

Anon
Mensajes: 15
Registrado: 07/03/2013 12:00 pm

Ejercicios de Programación

#94 Mensaje por Anon » 07/03/2013 12:21 pm

Aquí va mi aportación:

Soluciones propuestas

A

2. Se dice que un año es bisiesto cuando es divisible por 4 pero no es divisible por 100. Sabemos que los extraterrestres llegaron a la Tierra en 1491 en forma de humano con apellido de órgano.

¿Cuantos años bisiestos hay entre 1491 y 2012, el fin del mundo?

Código: Seleccionar todo

/* Se dice que un año es bisiesto cuando es divisible por 4 pero no es divisible por 100. 
 * Sabemos que los extraterrestres llegaron a la Tierra en 1491 en forma de humano con apellido de órgano.
 *
 * ¿Cuántos años bisiestos hay entre 1491 y 2012, el fin del mundo?
 */

#include <stdio.h>

int main()
{
	int i, j=0;
	for (i=1491; i<=2012; i++)
	{
		if ((i%4==0)&&(i%100!=0)||(i%400==0)) j++;
	}
	printf ("Los años bisiestos entre 1491 y 2012 son %i.\nCerrando programa . . .\n", j);
	return 0;
}
3. Una pera pesa alrededor de 150g. Tenemos un fichero en que cada línea tiene una número N entre 0 y 1000.

Para cada cantidad de peras tienes que calcular cuantos kilos (séase 1Kg = 1000g) pesaría la cesta.

Código: Seleccionar todo

/* Una pera pesa alrededor de 150g. Introduce un número N entre 0 y 1000, que será el número de líneas que leerá el programa.
 *
 * Calcular cuantos kilos (séase 1Kg = 1000g) pesaría la cesta.
 */

#include <stdio.h>

int main()
{
	int n, i, num_peras;
	printf ("Introduce el número de líneas que vas a introducir:\n");
	scanf ("%i", &n);
	for (i=0; i<n; i++)
	{
		printf ("Introduce número de peras: ");
		scanf ("%i", &num_peras);
		printf ("La cesta pesaría %f kg.\n", 0.150*num_peras);
	}
	printf ("Cerrando programa . . .\n");
	return 0;
}
Es correcto, ¿verdad?

Saludos.

Masakre
Mensajes: 249
Registrado: 06/06/2012 10:52 am

Re: Ejercicios de Programación

#95 Mensaje por Masakre » 18/03/2013 2:50 pm

Sorancio escribió:2. Tenemos un fichero CSV y usamos de separador de columnas la coma y de filas el salto de línea. Mediante un fichero de entrada que tendrá K líneas y cada línea tendrá una cantidad de números variable.

Encuentra de cada fila el mayor y el menor número, y luego del conjunto global procesando sólo una vez el fichero.
Bueno, acá cito mi avance :)

Código: Seleccionar todo

/* Tenemos un fichero CSV y usamos de separador de columnas el (;) y de filas el salto de línea.
Mediante un fichero de entrada que tendrá K líneas y cada línea tendrá una cantidad de números variable,
encuentre de cada fila el mayor y el menor número, y luego del conjunto global (procesando sólo una vez el fichero).
*/

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm> // Para uso de count()
#include <cstdlib> // Para uso de atoi()
using namespace std;

// Prototipos.
void procesar(string, unsigned);

// Vector global.
vector <int> mayor; // mayor[k]: mayor elemento de la fila k.
vector <int> menor; // menor[k]: menor elemento de la fila k.

int main()
{
    string linea; unsigned K = 0;
    ifstream archivoE("fichero.csv");

    // Evaluamos que se haya abierto correctamente !
    if(!archivoE.is_open()){
        cout<<"Error al intentar abrir fichero.csv !"<<endl
        <<"Verifique la existencia del archivo y vuelva a iniciar el programa.";
        return 1;
    }

    // Procesamos la info, línea tras línea.
    while(archivoE.good()){ // Método más general que eof()
        getline(archivoE, linea);
        procesar(linea, K); ++K;
    }
    archivoE.close(); // Cerramos el archivo CSV.

    // Encontramos mayor y menor global.
    int mayorG=mayor[0], menorG=menor[0];
    for(size_t i=0; i<K; ++i)
    {
        if(mayor[i]>mayorG) mayorG=mayor[i];
        if(menor[i]<menorG) menorG=menor[i];
    }

    cout<<"El mayor global es "<<mayorG<<" y el menor global es "<<menorG<<".";
    return 0;
}

void procesar(string linea, unsigned K)
{
    vector <int> elementos;
    size_t i=0; string s;

    // Almacenamos todos los elementos de la fila K.
    while(i<linea.size())
    {
        if(linea[i]==';')
        {
            elementos.push_back(atoi(s.c_str()));
            s.clear();
        }
        else if( isdigit(linea[i]) )
            s += linea[i];
        ++i;
    }

    // Buscamos el mayor y menor de la fila.
    mayor[K] = elementos[0];
    menor[K] = elementos[0];
    for(i=0; i<linea.size(); ++i)
        if(elementos[i] > mayor[K])
            mayor[K] = elementos[i];
        else if (elementos[i] < menor[K])
            menor[K] = elementos[i];
    if(mayor[K]==menor[K])
        cout<<"No existe ni mayor ni menor.";
    else
    {
        if(count(elementos.begin(), elementos.end(), mayor[K])>1)
            cout<<"No existe mayor, ";
        else cout<<"Mayor: "<<mayor[K]<<", ";
        if(count(elementos.begin(), elementos.end(), menor[K])>1)
            cout<<"No existe menor.";
        else cout<<"Menor: "<<menor[K]<<".";
    }
}
Al ejecutar me muestra "ProcesarCSV.exe dejó de funcionar".
Cuando uso la herramienta "Debug / Continue" (nunca antes lo hice), ejecuta el programa y se cierra, pero deja marcada la línea siguiente:

Código: Seleccionar todo

    mayor[K] = elementos[0];
Y además aparece lo siguiente en un cuadro:

Código: Seleccionar todo

#0 00401867	procesar(linea={static npos = 4294967295, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x3e292c "1;2;3;5;6 "}}, K=0) (E:\Developer Zone\Aplicaciones de escritorio\Proyectos C++\C++ en CodeBlocks\Ejercicios\Ficheros\ProcesarCSV\main.cpp:71)
#1 0040145A	main() (E:\Developer Zone\Aplicaciones de escritorio\Proyectos C++\C++ en CodeBlocks\Ejercicios\Ficheros\ProcesarCSV\main.cpp:36)
Estaría muy agradecido de que me ayuden a encontrar una solución a el problema.

Está en modo -Wall (Sorancio le decía modo pedántico y sangriento), pero ni así muestra errores, ni warnings. El error ocurre al momento de la ejecución.

Avatar de Usuario
rir3760
Mensajes: 7553
Registrado: 01/10/2004 11:00 pm
Ubicación: Mexico

#96 Mensaje por rir3760 » 18/03/2013 9:14 pm

La primera vez que se llama a esta función:

Código: Seleccionar todo

procesar(linea, K); // K == 0
Las sentencias:

Código: Seleccionar todo

// Buscamos el mayor y menor de la fila.
mayor[K] = elementos[0];
menor[K] = elementos[0];
Tratan de acceder al primer elemento de los vectores "mayor" y "menor", el problema es que los vectores inician sin elementos.

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

Masakre
Mensajes: 249
Registrado: 06/06/2012 10:52 am

#97 Mensaje por Masakre » 18/03/2013 10:07 pm

Muchas gracias rir3760.

Ahora sí conseguí que funcionara.

Entrada:

Código: Seleccionar todo

1;2;3;5;6
4;2;3
2;2;3
1;1;1
2;3;4;4;2
Salida:

Código: Seleccionar todo

Mayor: 6, Menor: 1.
Mayor: 4, Menor: 2.
Mayor: 3, No existe menor.
No existe ni mayor ni menor.
No existe mayor, No existe menor.
El mayor global es 6 y el menor global es 1.
Process returned 0 (0x0)   execution time : 0.032 s
Press any key to continue.
Código:

Código: Seleccionar todo

/* Tenemos un fichero CSV y usamos de separador de columnas el (;) y de filas el salto de línea.
Mediante un fichero de entrada que tendrá K líneas y cada línea tendrá una cantidad de números variable,
encuentre de cada fila el mayor y el menor número, y luego del conjunto global (procesando sólo una vez el fichero).
*/

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm> // Para uso de count()
#include <cstdlib> // Para uso de atoi()
using namespace std;

// Prototipos.
void procesar(string, unsigned);

// Vector global.
vector <int> mayor; // mayor[k]: mayor elemento de la fila k.
vector <int> menor; // menor[k]: menor elemento de la fila k.

int main()
{
    string linea; unsigned K = 0;
    ifstream archivoE("fichero.csv");

    // Evaluamos que se haya abierto correctamente !
    if(!archivoE.is_open()){
        cout<<"Error al intentar abrir fichero.csv !"<<endl
        <<"Verifique la existencia del archivo y vuelva a iniciar el programa.";
        return 1;
    }

    // Procesamos la info, línea tras línea.
    while(archivoE.good()){ // Método más general que eof()
        getline(archivoE, linea);
        procesar(linea, K); ++K;
    }
    archivoE.close(); // Cerramos el archivo CSV.

    // Encontramos mayor y menor global.
    int mayorG=mayor[0], menorG=menor[0];
    for(size_t i=0; i<K; ++i)
    {
        if(mayor[i]>mayorG) mayorG=mayor[i];
        if(menor[i]<menorG) menorG=menor[i];
    }

    cout<<"El mayor global es "<<mayorG<<" y el menor global es "<<menorG<<".";
    return 0;
}

void procesar(string linea, unsigned K)
{
    vector <int> elementos;
    size_t i=0; string s;

    // Almacenamos todos los elementos de la fila K.
    while(i<linea.size())
    {
        if(linea[i]==';') // Al detectar un ';' carga lo previamente leido.
        {
            elementos.push_back(atoi(s.c_str()));
            s.clear();
        }
        else if( isdigit(linea[i]) )
            s += linea[i];
        ++i;
    }
    if(s.size()!=0) // Por si la fila no acaba en ';'
        elementos.push_back(atoi(s.c_str()));

    // Buscamos el mayor y menor de la fila.
    mayor.push_back(elementos[0]);
    menor.push_back(elementos[0]);
    for(i=0; i<elementos.size(); ++i)
        if(elementos[i] > mayor[K])
            mayor[K] = elementos[i];
        else if (elementos[i] < menor[K])
            menor[K] = elementos[i];

    // Mostramos los datos de una forma peculiar.
    if(mayor[K]==menor[K])
        cout<<"No existe ni mayor ni menor.";
    else
    {
        if(count(elementos.begin(), elementos.end(), mayor[K])>1)
            cout<<"No existe mayor, ";
        else cout<<"Mayor: "<<mayor[K]<<", ";
        if(count(elementos.begin(), elementos.end(), menor[K])>1)
            cout<<"No existe menor.";
        else cout<<"Menor: "<<menor[K]<<".";
    } cout<<endl;
/*
    // Muestra datos de cada fila.
    cout<<"Size: "<<linea.size()<<endl;
    for(i=0; i<elementos.size(); ++i)
        cout<<elementos[i]<<";";
    cout<<endl<<endl;
*/
}

Masakre
Mensajes: 249
Registrado: 06/06/2012 10:52 am

Re: Ejercicios de Programación

#98 Mensaje por Masakre » 22/03/2013 1:44 pm

Sorancio escribió:1. Tenemos un fichero cuyo contenido son K líneas. Cada línea tiene una ecuación de la forma ax + by = c.

Encuentra todas las soluciones al sistema de K ecuaciones.
A continuación el avance que llevo del ejercicio:

Código: Seleccionar todo

/* Tenemos un fichero cuyo contenido son K líneas. Cada línea se corresponde con una ecuación de dos variables: X e Y.
Encontrar las posibles soluciones del sistema de K ecuaciones. */

#include <iostream>
#include <fstream>
#include <vector>
#include <cstdlib> // To use atoi()
using namespace std;


// Definimos Ecuacion como una estructura.
struct Ecuacion
{
        int coefX;
        int coefY;
        int cte;
};
vector <Ecuacion> Eq;

// Prototipos.
void SimplifyEq(Ecuacion);
unsigned procesarLinea(string, unsigned);

// Razones de fin instantáneo.
string razon[] = {
    "Se encontraron ecuaciones sin signos de igualdad.",
    "Existen ecuaciones que no tienen valores despues del signo igual.",
    "Se encontraron variables sin coeficiente.\nRecuerde escribir 1x en vez de solo x, análogamente con y.",
    "Se encontro algun caracter extrano.\nSolo se permiten numeros enteros, y los simbolos \'=\', \'+\' y \'-\' ..."
};

int main()
{
    ifstream FlujoE("ecuaciones.txt");

    // ¿Existe el archivo?
    if(!FlujoE.is_open())
    {
        cout<<"El archivo \'ecuaciones.txt\' no se ha podido cargar."
        "\nAsegurese de su existencia, y vuelva a iniciar el programa."<<endl;
        return 1;
    }

    // ¿Sí? Entonces lo procesamos.
    string linea; int K = 0, flag;
    while(FlujoE.good()) // Método más general que eof()
    {
        getline(FlujoE, linea);
        if( (flag=procesarLinea(linea, K)) != 0)
        // Si ocurrió algo inesperado. Mostrar razón y finalizar.
        {
            cout<<razon[flag-1];
            return 0;
        }
        ++K;
    }
    return 0;
}

void SimplifyEq(Ecuacion* Pointer)
{
    // Encontramos el menor.
    int menor = Pointer->coefX;
    if(Pointer->coefY < menor) menor = Pointer->coefY;
    if(Pointer->cte < menor) menor = Pointer->cte;

    // Usamos la variable menor como centinela.
    menor = menor/2; // Para evitar tanto proceso.
    while(menor>0)
    {
        if(Pointer->coefX%menor==0 && Pointer->coefY%menor==0 && Pointer->cte%menor==0)
        {
            Pointer->coefX /= menor;
            Pointer->coefY /= menor;
            Pointer->cte /= menor;
        } --menor;
    }
}

unsigned procesarLinea(string linea, unsigned K)
{
    Ecuacion EqTemp = {0,0,0};
    /* Las Eq pueden ser:
    3x+4y=7
    2x-6=0
    1y+2=0
    2y=6x+3
    1x=-3y+1
    */

    // Suprimimos todos los vacíos.
    while( linea.find(' ') != string::npos )
        linea.erase( linea.find(' ') );

    if( linea.find('=') == string::npos )
        return 1; // Falta signo de igualdad en la Eq.
    else if ( linea.find('=') == linea.size()-1 )
        return 2; // No hay nada después del igual.

    if( linea.find('x') == 0 || linea.find('y') == 0 )
        return 3; // Variables sin coeficiente antepuesto.

    for(size_t i=0; i<linea.size(); ++i)
    {
        if( !isdigit(linea[i]) && linea[i]!='=' && linea[i]!='+' && linea[i]!='-' && linea[i]!='x' && linea[i]!='y')
            return 4; // No es un número, ni símbolo aritmético.
    }

    // Encontramos el coeficiente de x:
    size_t pos = linea.find('x');
    string s;
    while( pos != string::npos ) // Si se encontró alguna x,
    { // obtenemos su coeficiente y borramos su rastro.
        --pos; // Retrocedemos una pos antes de 'x'.
        while(pos>=0 || isdigit(linea[pos]) || linea[pos]=='+' || linea[pos]=='-')
            s += linea[pos--];
        if( linea.find('x') < linea.find('=') )
            EqTemp.coefX += atoi(s.c_str());
        else EqTemp.coefX -= atoi(s.c_str());

        linea.erase(pos+1, linea.find('x')-pos);
        pos = linea.find('x');
    }
    cout<<"Coeficiente X de la ecuacion "<<K<<" :"<<EqTemp.coefX;
    return 0;
}
Aunque está incompleto, antes de seguir escribiendo código decidí probar si funcionaba momentáneamente.
Así como está debería encontrar el coeficiente X de las ecuaciones que aparezcan en el archivo ecuaciones.txt, pero el programa finaliza de manera inesperada.
Usando el debugger me resalta la línea 116:

Código: Seleccionar todo

            s += linea[pos--];
Gracias de antemano.

Avatar de Usuario
rir3760
Mensajes: 7553
Registrado: 01/10/2004 11:00 pm
Ubicación: Mexico

#99 Mensaje por rir3760 » 22/03/2013 8:41 pm

La parte importante es:

Código: Seleccionar todo

// Encontramos el coeficiente de x:
size_t pos = linea.find('x');

// ...

while (pos>=0 || isdigit(linea[pos]) || linea[pos]=='+' || linea[pos]=='-')
   s += linea[pos--];
Al utilizar el operador logico OR la condicion sera verdadera si cualquiera de las expresiones que la componen es verdadera:

Código: Seleccionar todo

pos >= 0
isdigit(linea[pos])
linea[pos] == '+'
linea[pos] == '-'
¿El problema? La variable pos es de tipo size_t y este es un tipo entero sin signo, nunca tomara un valor negativo (al decrementarla pasa de cero a su valor maximo).

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

Masakre
Mensajes: 249
Registrado: 06/06/2012 10:52 am

#100 Mensaje por Masakre » 23/03/2013 8:43 am

Gracias por la ayuda.

Ahora ha quedado así:

Código: Seleccionar todo

/* Tenemos un fichero cuyo contenido son K líneas. Cada línea se corresponde con una ecuación de dos variables: X e Y.
Encontrar las posibles soluciones del sistema de K ecuaciones. */

#include <iostream>
#include <fstream>
#include <vector>
#include <cstdlib> // To use atoi()
#include <algorithm> // To use count()
using namespace std;


// Definimos Ecuacion como una estructura.
struct Ecuacion
{
        int coefX;
        int coefY;
        int cte;
};
vector <Ecuacion> Eq;

// Prototipos.
void SimplifyEq(Ecuacion);
unsigned procesarLinea(string, unsigned);

// Razones de fin instantáneo.
string razon[] = {
    "Se encontraron ecuaciones sin signos de igualdad.",
    "Existen ecuaciones que no tienen valores despues del signo igual.",
    "Se encontraron variables sin coeficiente.\nRecuerde escribir 1x en vez de solo x, análogamente con y.",
    "Se encontro algun caracter extrano.\nSolo se permiten numeros enteros, y los simbolos \'=\', \'+\' y \'-\' ...",
    "Una de las ecuaciones presenta terminos X adheridos, sin algun signo de intermediario. Por ejemplo: c = axbx."
};

int main()
{
    ifstream FlujoE("ecuaciones.txt");

    // ¿Existe el archivo?
    if(!FlujoE.is_open())
    {
        cout<<"El archivo \'ecuaciones.txt\' no se ha podido cargar."
        "\nAsegurese de su existencia, y vuelva a iniciar el programa."<<endl;
        return 1;
    }

    // ¿Sí? Entonces lo procesamos.
    string linea; int K = 0, flag;
    while(FlujoE.good()) // Método más general que eof()
    {
        getline(FlujoE, linea);
        if( (flag=procesarLinea(linea, K)) != 0)
        // Si ocurrió algo inesperado. Mostrar razón y finalizar.
        {
            cout<<razon[flag-1];
            return 0;
        }
        ++K;
    }
    return 0;
}

void SimplifyEq(Ecuacion* Pointer)
{
    // Encontramos el menor.
    int menor = Pointer->coefX;
    if(Pointer->coefY < menor) menor = Pointer->coefY;
    if(Pointer->cte < menor) menor = Pointer->cte;

    // Usamos la variable menor como centinela.
    menor = menor/2; // Para evitar tanto proceso.
    while(menor>0)
    {
        if(Pointer->coefX%menor==0 && Pointer->coefY%menor==0 && Pointer->cte%menor==0)
        {
            Pointer->coefX /= menor;
            Pointer->coefY /= menor;
            Pointer->cte /= menor;
        } --menor;
    }
}

unsigned procesarLinea(string linea, unsigned K)
{
    Ecuacion EqTemp = {0,0,0};
    /* Las Eq pueden ser:
    3x+4y=7
    2x-6=0
    1y+2=0
    2y=6x+3
    1x=-3y+1
    */

    // Suprimimos todos los vacíos.
    while( linea.find(' ') != string::npos )
        linea.erase( linea.find(' ') );

    if( linea.find('=') == string::npos )
        return 1; // Falta signo de igualdad en la Eq.
    else if ( linea.find('=') == linea.size()-1 )
        return 2; // No hay nada después del igual.

    if( linea.find('x') == 0 || linea.find('y') == 0 )
        return 3; // Variables sin coeficiente antepuesto.

    for(size_t i=0; i<linea.size(); ++i)
    {
        if( !isdigit(linea[i]) && linea[i]!='=' && linea[i]!='+' && linea[i]!='-' && linea[i]!='x' && linea[i]!='y')
            return 4; // No es un número, ni símbolo aritmético.
    }
/*
    // Ec que continienen algo como "2x3x".
    string STRtempo = linea;
    for(size_t i=0; i<STRtempo.size(); ++i)
        if( isdigit(STRtempo[i]) )
            STRtempo.erase(i--);
    const size_t SZtempo = count(STRtempo.begin(), STRtempo.end(), 'x');
    size_t posicionesX[SZtempo];
    size_t SZ = SZtempo;
    for(size_t i=STRtempo.size(); i>=0; --i)
        if(STRtempo[i] == 'x')
        {
            posicionesX[SZ-1] = i;
            SZ--;
        }
    bool es_correcto = false;
    for(size_t i=0; i<SZ-1; ++i) // No es necesario evaluar la última.
        for(size_t j=i+1; j<SZ; ++i)
            for(size_t z=posicionesX[i]+1; z<posicionesX[j]-1; ++z)
                if(STRtempo[z]=='+'||STRtempo[z]=='-'||STRtempo[z]=='=')
                {
                    es_correcto = true;
                    goto fin_evaluacion;
                }
    fin_evaluacion:
    if(!es_correcto) return 5;
*/
    // Encontramos el coeficiente de x:
    short pos = linea.find('x');
    string s;
    while( pos != string::npos ) // Si se encontró alguna x,
    { // obtenemos su coeficiente y borramos su rastro.
        --pos; // Retrocedemos una pos antes de 'x'.
        while(pos>=0)
        {
            if( isdigit(linea[pos]) )
                s.insert(s.begin(), linea[pos--]);
            else if(linea[pos]=='+' || linea[pos]=='-')
            {
                s.insert(s.begin(), linea[pos--]);
                break;
            }
            else if(linea[pos]=='=') break;
        }

        cout<<"String de algun coefX de "<<K<<": "<<s<<endl;
        if( linea.find('x') < linea.find('=') )
            EqTemp.coefX += atoi(s.c_str());
        else EqTemp.coefX -= atoi(s.c_str());

        linea.erase(pos+1, linea.find('x')-pos);
        cout<<"Ecuacion recortada: "<<linea<<endl;
        pos = linea.find('x'); s.clear();
    }
    cout<<"Coeficiente X de la ecuacion "<<K<<":  "<<EqTemp.coefX<<endl<<endl;
    return 0;
}
Ya no tiene problemas de encontrar el coeficiente de X en cada ecuación.
Incluso si se ingresa 3+4+2x=3x-2x el coeficiente de x será admitido como 1. Esto es porque a toda ecuación que ingresa trato de darle la forma Ax+By+C=0.

Sin embargo, si ingreso 4x3x+5=5x6x lo va a considerar como 4x+3x+5=5x+6x. Entonces, hice un intento por determinar ese error en la entrada y advertirle al usuario.

Exactamente se refleja en esta parte que aparece /* toda comentada */ en el programa:

Código: Seleccionar todo

    // Ec que continienen algo como "2x3x".
    string STRtempo = linea;
    for(size_t i=0; i<STRtempo.size(); ++i)
        if( isdigit(STRtempo[i]) )
            STRtempo.erase(i--);
    const size_t SZtempo = count(STRtempo.begin(), STRtempo.end(), 'x');
    size_t posicionesX[SZtempo];
    size_t SZ = SZtempo;
    for(size_t i=STRtempo.size(); i>=0; --i)
        if(STRtempo[i] == 'x')
        {
            posicionesX[SZ-1] = i;
            SZ--;
        }
    bool es_correcto = false;
    for(size_t i=0; i<SZ-1; ++i) // No es necesario evaluar la última.
        for(size_t j=i+1; j<SZ; ++i)
            for(size_t z=posicionesX[i]+1; z<posicionesX[j]-1; ++z)
                if(STRtempo[z]=='+'||STRtempo[z]=='-'||STRtempo[z]=='=')
                {
                    es_correcto = true;
                    goto fin_evaluacion;
                }
    fin_evaluacion:
    if(!es_correcto) return 5;
El problema es que no sé si estoy haciendo instrucciones "ilegales".
La idea que he seguido es esta:
- Una ecuación que está almacenada como string se almacena en otro string temporal.
- A dicho string temporal se le desaparecen los números, quedando por ejemplo: x+=x+ o -x+x=-y
- Luego declaro una constante y le asigno el valor devuelto por count(). Donde count() cuenta todas las x en el nuevo string temporal.
- Como la variable que declaré es constante la puedo usar para declarar un array de elementos size_t, donde almacenare todas las posiciones de x.
- Luego usé la constante declarada y le asigne ese valor a una variable size_t (quise usar cons_cast<size_t>() pero me dijo que sólo es con punteros...).
- Aparen 3 fors anidados porque: los 2 primeros toman las posiciones de x almacenadas en el array posicionesX[]. Por ejemplo toma las posiciones 4 y 6, entonces el último for analiza las posiciones que están entre 4 y 6, es decir, sólo la posición 5 del string temporal sin números.
- Esas posiciones evaluadas deben contener al menos un caracter de los siguientes: '+', '-' o '='. Si no es así, quiere decir que hay alguna expresión de la forma "axbx" en la ecuación.

Es la primera vez que uso goto creyendo que es lo más conveniente.
Gracias nuevamente.

Avatar de Usuario
rir3760
Mensajes: 7553
Registrado: 01/10/2004 11:00 pm
Ubicación: Mexico

#101 Mensaje por rir3760 » 25/03/2013 9:49 am

Masakre escribió:El problema es que no sé si estoy haciendo instrucciones "ilegales".
Me temo que si.

En C++ estándar no puedes declarar un array de esta forma:

Código: Seleccionar todo

const size_t SZtempo = count(STRtempo.begin(), STRtempo.end(), 'x');
size_t posicionesX[SZtempo];
Debes revisar si tu compilador soporta esa característica como una extensión o bien utilizar un vector.

Otro error, similar al que ya te había mencionado en el tema:

Código: Seleccionar todo

for(size_t i=STRtempo.size(); i>=0; --i)
   if(STRtempo[i] == 'x'){
      posicionesX[SZ-1] = i;
      SZ--;
   }
Las variables sin signo son siempre igual o mayor que cero lo que resulta en un bucle infinito.

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

Masakre
Mensajes: 249
Registrado: 06/06/2012 10:52 am

#102 Mensaje por Masakre » 25/03/2013 12:03 pm

rir3760 escribió:En C++ estándar no puedes declarar un array de esta forma:

Código: Seleccionar todo

const size_t SZtempo = count(STRtempo.begin(), STRtempo.end(), 'x');
size_t posicionesX[SZtempo];
Debes revisar si tu compilador soporta esa característica como una extensión o bien utilizar un vector.
¿Sería de esta otra forma?

Código: Seleccionar todo

    size_t SZ = count(STRtempo.begin(), STRtempo.end(), 'x');
    vector <size_t> posicionesX (SZ, 0);
Para encontrar formas como "AxBx" mi idea era:
- Guardar las posiciones de todas las x en posicionesX[].
- Luego recorrer las posiciones entre posicionesX y posicionesX[i+1].
- En ese recorrido deberían de haberse registrado signos como '+', '-' o '='.
- Si en algún tramo no se encontraron esos signos había una forma "AxBx".

Pero ciertamente pudo hacerse así desde un inicio:
- Eliminar todos los números.
- Recorrer el string de la ecuación.
- Si una posición del string era 'x' y estaba seguida de otra 'x', presentaba la forma "AxBx".

Me estaba complicando demasiado para algo tan simple :)

Gracias nuevamente.
Y... es muy extraño no ver la participación de leosan !

Masakre
Mensajes: 249
Registrado: 06/06/2012 10:52 am

#103 Mensaje por Masakre » 28/03/2013 7:23 am

Y esta es mi solución para el ejercicio C1.

Código: Seleccionar todo

/* Tenemos un fichero cuyo contenido son K líneas. Cada línea se corresponde con una ecuación de dos variables: X e Y.
Encontrar las posibles soluciones del sistema de K ecuaciones. */

#include <iostream>
#include <fstream>
#include <vector>
#include <cstdlib> // To use atoi()
#include <algorithm> // To use count()
using namespace std;


// Definimos Ecuacion como una estructura.
struct Ecuacion
{
        int coefX;
        int coefY;
        int cte;
};
vector <Ecuacion> Eq;

// Prototipos.
void SimplifyEq(Ecuacion*);
unsigned procesarLinea(string, unsigned);
void printEq(Ecuacion);
bool EcEquivalentes(Ecuacion, Ecuacion);

// Razones de fin instantáneo.
string razon[] = {
    "Se encontraron ecuaciones sin signos de igualdad.",
    "Existen ecuaciones que no tienen valores despues del signo igual.",
    "Se encontraron variables sin coeficiente.\nRecuerde escribir 1x en vez de solo x, analogamente con y.",
    "Se encontro algun caracter extrano.\nSolo se permiten numeros enteros, y los simbolos \'=\', \'+\' y \'-\' ...",
    "Una de las ecuaciones presenta terminos X adheridos, sin algun signo de intermediario. Por ejemplo: c = axbx."
};

int main()
{
    ifstream FlujoE("ecuaciones.txt");

    // ¿Existe el archivo?
    if(!FlujoE.is_open())
    {
        cout<<"El archivo \'ecuaciones.txt\' no se ha podido cargar."
        "\nAsegurese de su existencia, y vuelva a iniciar el programa."<<endl;
        return 1;
    }

    // ¿Sí? Entonces lo procesamos.
    string linea; int K = 0, flag;
    while(FlujoE.good()) // Método más general que eof()
    {
        getline(FlujoE, linea);
        if( (flag=procesarLinea(linea, K)) != 0)
        // Si ocurrió algo inesperado. Mostrar razón y finalizar.
        {
            cout<<razon[flag-1];
            return 0;
        }
        ++K;
    }
    for(size_t i=0; i<Eq.size(); ++i)
    {
        if(Eq[i].coefX == Eq[i].coefY && Eq[i].coefY == 0)
        {
            if(Eq[i].cte != 0)
            {
                cout<<"El sistema de ecuaciones no presenta solucion alguna."<<endl
                <<"Esto es por la inconsistencia de una ecuacion de la forma:"<<endl
                <<"0x+0y+C=0 donde C es distinto de cero."<<endl;
                return 0;
            }
            else // Eliminamos la ecuación 0x+0y+0=0.
            {
                Eq.erase(Eq.begin() + i);
                --i; continue;
            }
        }
        SimplifyEq(&Eq[i]);
        //cout<<"Ecuacion "<<i<<" simplificada: ";
        //printEq(Eq[i]); cout<<endl;
    }

    // Buscamos Ec equivalentes y borramos repetidas.
    for(size_t i=0; i<Eq.size()-1; ++i)
        for(size_t j=i+1; j<Eq.size(); ++j)
            if(EcEquivalentes(Eq[i], Eq[j]))
            {
                Eq.erase(Eq.begin() + j);
                --j;
            }

    cout<<"El sistema es equivalente a ... "<<endl;
    for(size_t i=0; i<Eq.size(); ++i)
        printEq(Eq[i]);
    cout<<"... luego de haber simplificado las ecuaciones y eliminado las equivalentes."<<endl<<endl;

    // Si se registran más de 2 Ec únicas, no presenta sol el sistema.
    switch( Eq.size() )
    {
        case 0:
            cout<<"El sistema presenta infinitas soluciones (X e Y reciben cualquier valor)."<<endl; break;
        case 1:
            if(Eq[0].coefX==0)
                cout<<"Y = "<<-Eq[0].cte/Eq[0].coefY<<", X pertenece a los reales."<<endl;
            else if (Eq[0].coefY==0)
                cout<<"X = "<<-Eq[0].cte/Eq[0].coefX<<", Y pertenece a los reales."<<endl;
            else // Ax+By+C=0 donde A,B!=0
                cout<<"El sistema presenta infinitas soluciones, siempre que se satisfaga: "<<endl
                <<"Y = "<<-Eq[0].cte/Eq[0].coefY<<" "<<-Eq[0].coefX/Eq[0].coefY<<"X"<<endl;
            break;
        case 2:
        {
            bool sehizo = false;
            // Usamos variables más cortas.
            float A=Eq[0].coefX, B=Eq[0].coefY, C=Eq[0].cte; // Ax+By+C=0
            float D=Eq[1].coefX, E=Eq[1].coefY, F=Eq[1].cte; // Dx+Ey+F=0
            float X, Y; // Solución al sistema.

            if(A!=0 && B!=0 && D!=0 && E!=0)
            {
                Y = (C*D - A*F)/(A*E - D*B);
                X = (-B/A)*Y - C/A;
                cout<<"X = "<<X<<", Y = "<<Y<<"."<<endl;
            }

            coefNulo:
            if(A==0)
            {
                if(C==0) Y=0;
                else Y = -C/B;
                if(D==0)
                {
                    if(F==0)
                    {
                        if(Y!=0)
                            cout<<"Las ecuaciones son contradictorias. El sistema no presenta solucion."<<endl;
                        else cout<<"Y = "<<Y<<", X pertenece a los reales."<<endl; // "Y = 0"
                    }
                    else
                    {
                        if(Y!=-F/E)
                            cout<<"Las ecuaciones son contradictorias. El sistema no presenta solucion."<<endl;
                        else cout<<"Y = "<<-F/E<<", X pertenece a los reales."<<endl; // "Y = "<<Y
                    }
                }
                else // D!=0
                {
                    if(E==0)
                    {
                        if(F==0)
                            cout<<"Y = "<<Y<<", X = 0."<<endl;
                        else cout<<"Y = "<<Y<<", X = "<<-F/D<<"."<<endl;
                    }
                    else // E!=0
                    {
                        if(F==0)
                            cout<<"Y = "<<Y<<", X = "<<E*Y/D<<"."<<endl;
                        else cout<<"Y = "<<Y<<", X = "<<(-E*Y - F)/D<<"."<<endl;
                    }
                }
            }
            else // A!=0
            if(B==0)
            {
                if(C==0) X=0;
                else X=-C/A;

                if(D==0)
                {
                    if(F==0)
                        cout<<"Y = 0, X = "<<X<<"."<<endl;
                    else cout<<"Y = "<<-F/E<<", X = "<<X<<"."<<endl;
                }
                else // D!=0
                {
                    if(E==0)
                    {
                        if(F==0)
                            if(X!=0) cout<<"Las ecuaciones son contradictorias. El sistema no presenta solucion."<<endl;
                            else cout<<"X = 0, Y pertenece a los reales."<<endl;
                        else // F!=0
                            if(X!=-F/D) cout<<"Las ecuaciones son contradictorias. El sistema no presenta solucion."<<endl;
                            else cout<<"X = "<<-F/D<<", Y pertenece a los reales."<<endl;
                    }
                    else // E!=0
                    {
                        if(F==0) cout<<"X = "<<X<<", Y = "<<D*X/E<<"."<<endl;
                        else cout<<"X = "<<X<<", Y = "<<(-D*X - F)/E<<"."<<endl;
                    }
                }
            }else if(!sehizo){ // B!=0
                // Evaluamos lo mismo empezando por la otra Ec.
                float tempo;
                tempo=A; A=D; D=tempo;
                tempo=B; B=E; E=tempo;
                tempo=C; C=F; F=tempo;
                sehizo=true;
                goto coefNulo;
            }
        } // Necesario usar corchetes cuando se declaran variables dentro de un case.
            break;

        default: cout<<"El sistema presenta mas de 2 ecuaciones unicas, por lo tanto no tiene solucion."<<endl;
    }
    return 0;
}

void SimplifyEq(Ecuacion *Ec)
{
    // Encontramos el menor. Pero si es 0, considerar el siguiente menor.
    int coefX = Ec->coefX; if(coefX<0) coefX*=-1;
    int coefY = Ec->coefY; if(coefY<0) coefY*=-1;
    int cte = Ec->cte; if(cte<0) cte*=-1;

    if(coefX==coefY && coefY==cte)
    {
        // No es necesario verificar que cte!=0. Ello se evalúa antes de intentar simplificarla.
        Ec->coefX/=cte;
        Ec->coefY/=cte;
        Ec->cte/=cte;
        return;
    }

    int menor; // Su valor depende de la forma de la Ec (8 casos: 2x2x2). Ya que son 3 variables que pueden ser o no nulas.
    // Los casos 0,0,0 y 0,0,N ya se descartaron antes.
    if(cte==0)
    {
        if(coefX == 0) return; // 0x+By+0=0 => y=0
        if(coefY == 0) return; // Ax+0y+0=0 => x=0
        // En este pto, la Ec es Ax+By=0
        menor = coefX<coefY ? coefX : coefY;
    }
    else
    {
        if(coefX==0) // By+C=0
            menor = coefY<cte ? coefY : cte;
        else if (coefY==0) // Ax+C=0
            menor = coefX<cte ? coefX : cte;
        else // Necesariamente Ax+By+C=0 donde A,B,C !=0
        {
            menor = coefX;
            if(coefY<menor) menor=coefY;
            if(cte<menor) menor=cte;
        }
    }

    // Usamos la variable menor como centinela.
    if(menor!=2 && menor%2==0) menor/=2; // Para evitar tanto proceso.
    while(menor>1)
    {
        while(Ec->coefX%menor==0 && Ec->coefY%menor==0 && Ec->cte%menor==0)
        {
            //cout<<"Se dividio entre "<<menor<<endl;
            Ec->coefX /= menor;
            Ec->coefY /= menor;
            Ec->cte /= menor;
        } --menor;
    }
}

unsigned procesarLinea(string linea, unsigned K)
{
    Ecuacion EqTemp = {0,0,0};
    /* Las Eq pueden ser:
    3x+4y=7
    2x-6=0
    1y+2=0
    2y=6x+3
    1x=-3y+1
    */

    // Suprimimos todos los vacíos.
    while( linea.find(' ') != string::npos )
        linea.erase( linea.find(' ') );

    if( linea.find('=') == string::npos )
        return 1; // Falta signo de igualdad en la Eq.
    else if ( linea.find('=') == linea.size()-1 )
        return 2; // No hay nada después del igual.

    if( linea.find('x') == 0 || linea.find('y') == 0 )
        return 3; // Variables sin coeficiente antepuesto.

    for(size_t i=0; i<linea.size(); ++i)
    {
        if( !isdigit(linea[i]) && linea[i]!='=' && linea[i]!='+' && linea[i]!='-' && linea[i]!='x' && linea[i]!='y')
            return 4; // No es un número, ni símbolo aritmético.
    }

    // Ec que continienen algo como "2x3x" o "42y10y".
    string STRtempo = linea;
    for(short i=0; i<STRtempo.size(); ++i)
        if( isdigit(STRtempo[i]) )
            STRtempo.erase(i--, 1);

    for(size_t i=0; i<STRtempo.size()-1; ++i)
        if( (STRtempo[i]=='x' && STRtempo[i+1]=='x') || (STRtempo[i]=='y' && STRtempo[i+1]=='y') )
            return 5;

    // Encontramos el coeficiente de x:
    short pos = linea.find('x');
    string s;
    while( pos != string::npos ) // Si se encontró alguna x,
    { // obtenemos su coeficiente y borramos su rastro.
        --pos; // Retrocedemos una pos antes de 'x'.
        while(pos>=0)
        {
            if( isdigit(linea[pos]) )
                s.insert(s.begin(), linea[pos--]);
            else if(linea[pos]=='+' || linea[pos]=='-')
            {
                s.insert(s.begin(), linea[pos--]);
                break;
            }
            else if(linea[pos]=='=') break;
        }

        //cout<<"String de algun coefX de "<<K<<": "<<s<<endl;
        if( linea.find('x') < linea.find('=') )
            EqTemp.coefX += atoi(s.c_str());
        else EqTemp.coefX -= atoi(s.c_str());

        linea.erase(pos+1, linea.find('x')-pos);
        //cout<<"Ecuacion recortada: "<<linea<<endl;
        pos = linea.find('x'); s.clear();
    }

    // Ahora el coeficiente de y:
    pos = linea.find('y');
    while( pos != string::npos ) // Si se encontró alguna y,
    { // obtenemos su coeficiente y borramos su rastro.
        --pos; // Retrocedemos una pos antes de 'y'.
        while(pos>=0)
        {
            if( isdigit(linea[pos]) )
                s.insert(s.begin(), linea[pos--]);
            else if(linea[pos]=='+' || linea[pos]=='-')
            {
                s.insert(s.begin(), linea[pos--]);
                break;
            }
            else if(linea[pos]=='=') break;
        }

        if( linea.find('y') < linea.find('=') )
            EqTemp.coefY += atoi(s.c_str());
        else EqTemp.coefY -= atoi(s.c_str());

        linea.erase(pos+1, linea.find('y')-pos);
        pos = linea.find('y'); s.clear();
    }
    // Ahora la constante de la ecuacion:
    pos = linea.size()-1;
    while(pos>0)
    {
        if( isdigit(linea[pos]) )
            s.insert(s.begin(), linea[pos--]);
        else if(linea[pos]=='+' || linea[pos]=='-')
            {
                s.insert(s.begin(), linea[pos--]);
                if( pos >= linea.find('=') )
                    EqTemp.cte -= atoi(s.c_str());
                else EqTemp.cte += atoi(s.c_str());
                s.clear();
            }
            else // Obligatoriamente será '='
            {
                --pos;
                if(s.size()>0)
                {
                    EqTemp.cte -= atoi(s.c_str());
                    s.clear();
                }
            }
    }

    // pos es 0.
    if(s.size()>0)
    {
        if(linea[0]=='=')
            EqTemp.cte -= atoi(s.c_str());
        else EqTemp.cte += atoi(s.c_str());
        s.clear();
    }

    Eq.push_back(EqTemp);
    return 0;
}

void printEq(Ecuacion Ec)
{
    if(Ec.coefX!=0)
        cout<<Ec.coefX<<"X ";

    if(Ec.coefY>0)
        cout<<"+ "<<Ec.coefY<<"Y ";
    else if(Ec.coefY<0)
        cout<<Ec.coefY<<"Y ";

    if(Ec.cte>0)
        cout<<"+ "<<Ec.cte;
    else if(Ec.cte<0)
        cout<<Ec.cte;

    cout<<" = 0"<<endl;
}

bool EcEquivalentes(Ecuacion A, Ecuacion B)
{
    if(A.coefX==B.coefX && A.coefY==B.coefY && A.cte==B.cte)
        return true;
    else return false;
}
He tratado de cubrir todos los vacíos posibles.
Sin embargo, sigo pensando que es una solución un poco extraña.
(No imaginé que me fuera a extender tanto con este enunciado...)

Un ejemplo de más o menos cómo funciona (si la entrada no tiene errores, ya que en esos casos debería advertir):

Entrada.
2x+1y=2x+1y
2x+2y=4
2y=-5+2-1y
Salida.
El sistema es equivalente a ...
1X + 1Y -2 = 0
+ 1Y + 1 = 0
... luego de haber simplificado las ecuaciones y eliminado las equivalentes.

Y = -1, X = 3.

Process returned 0 (0x0) execution time : 0.010 s
Press any key to continue.
Si alguien encuentra errores me lo hacen saber... y pues, si tienen sugerencias también :wink:

Nuwanda11
Mensajes: 3
Registrado: 16/12/2016 9:51 am

Re: Ejercicios de Programación

#104 Mensaje por Nuwanda11 » 16/12/2016 10:08 am

Enunciado: Dada una secuencia de manejo de una caja fuerte, expresada como movimientos a la izquierda (representados
por el caracter ‘I’), a la derecha (‘D’) y terminadas por la orden de apertura (‘A’), como por ejemplo:
‘D’ ‘D’ ‘D’ ‘I’ ‘D’ ‘D’ ‘I’ ‘I’ ‘D’ ‘A’
Escribir un programa que detecte si la secuencia de apertura de la caja, que será ‘D’ ‘I’ ‘D’ ‘I’, está presente en una
secuencia cualquiera introducida.

Entrada: DDDIDDIIDA
Salida: NO SE ABRE
Entrada: DDDIDIIDA
Salida: SI SE ABRE

Estoy haciendo este ejercicio en C++ pero no doy con la tecla, lo único que puedo utilizar son bucles, if y booleanos. Algun alma caritativa que me eche una mano?
Muchas Gracias!!!

Responder

¿Quién está conectado?

Usuarios navegando por este Foro: Bing [Bot] y 6 invitados