#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>

#define PI 3.141516


struct DATOS {
   char funcion[50];
} Datos; 

double operacion(int, int);
double variable (int, int, int, int);
void replace (int, int, char [50]);
double Sgn(double);

void main ()
{
	char buffer[3], tempo[50];
	double var, res, pot;
	int i, p1, pc, pa[50], inc;
	bool fin;

	p1=1;
	i=1;
	pc=0;
	pa[0]=0;
	fin=false;

	/* Aqui copio la funcion a la viariable char*/
	strcpy(Datos.funcion, "(45*95+36)"); 

	do
	{
		/*Busca el segundo parentesis abierto*/
		if(Datos.funcion[i]=='('){
			pa[p1]=i;
			p1++;
		}
		
		else
		{

			/*Busca el primer parentesis cerrado*/
			if(Datos.funcion[i]==')'){

				/*llama a la funcion que dara el resultado entre los parentesis encontrados*/
 				var=operacion(pa[p1-1], i);

				sprintf(buffer, "%.4lf", var);


				do{
					pc++;
				}while(Datos.funcion[pc] != ')');

				/*Se coloca fuera del parentesis abierto para saber si hay una funcion trigonometrica*/
				/*Busca cada letra para saber si es seno, cos, etc*/
				if(Datos.funcion[pa[p1-1]-1]=='h'){
					if(Datos.funcion[pa[p1-1]-2]=='n'){
						if(Datos.funcion[pa[p1-1]-3]=='i'){ //debido a que encontro inh, le corresponde sinh
							res=sinh((var*PI)/180);
							
							sprintf(tempo, "%0.4f", res);

							/*la funcion replace, reemplaza desde un parentesis abierto a uno cerrado con una
							variable solo numerica */
							replace(pa[p1-1]-4, pc, tempo); 

							i=0;
							p1--;
						}
						else
						{
							res=tanh((var*PI)/180);
							
							sprintf(tempo, "%.4lf", res);
							
							replace(pa[p1-1]-4, pc, tempo);

							i=0;
							p1--;
						}
					}
					else //Como no fue inh, es onh, por lo tanto es cosh
					{
							res=cosh((var*PI)/180);
							
							sprintf(tempo, "%.4lf", res);

							replace(pa[p1-1]-4, pc, tempo);

							i=0;
							p1--;
					}
				}
				else	
				{
					if(Datos.funcion[pa[p1-1]-1]=='n'){
						if(Datos.funcion[pa[p1-1]-2]=='i'){
							res=sin((var*PI)/180);
							
							sprintf(tempo, "%.4lf", res);

							replace(pa[p1-1]-3, pc, tempo);

							i=0;
							p1--;
						}
						else
						{
							if(Datos.funcion[pa[p1-1]-2]=='a'){
								res=tan((var*PI)/180);
							
								sprintf(tempo, "%.4lf", res);

								replace(pa[p1-1]-3, pc, tempo);

								i=0;
								p1--;
							}
							
							else
							{
								if(Datos.funcion[pa[p1-1]-2]=='l'){
									res=log(var);	
							
									sprintf(tempo, "%.4lf", res);

									replace(pa[p1-1]-2, pc, tempo);

									i=0;
									p1--;
								}
								else
								{
									res=Sgn(var);
							
									sprintf(tempo, "%.4lf", res);

									replace(pa[p1-1]-3, pc, tempo);

									i=0;
									p1--;
								}
							}
						}

					}
					else
					{
						if(Datos.funcion[pa[p1-1]-1]=='s'){
							if(Datos.funcion[pa[p1-1]-2]=='o'){
								res=cos((var*PI)/180);
							
								sprintf(tempo, "%.4lf", res);

								replace(pa[p1-1]-3, pc, tempo);

								i=0;
								p1--;
							}
							else
							{
								res=abs(var);
							
								sprintf(tempo, "%.4lf", res);

								replace(pa[p1-1]-3, pc, tempo);
								
								i=0;
								p1--;
							}
						}

						else
						{
							if(Datos.funcion[pa[p1-1]-1]=='p'){
								res=exp(var);
							
								sprintf(tempo, "%.4lf", res);
							
								replace(pa[p1-1]-3, pc, tempo);

								i=0;
								p1--;
								
							}
							
							else
							{
								if(Datos.funcion[pa[p1-1]-1]=='g'){
									res=log10(var);
							
									sprintf(tempo, "%.4lf", res);

									replace(pa[p1-1]-3, pc, tempo);

									i=0;
									p1--;
								}
								else
								{
									if(Datos.funcion[pa[p1-1]-1]=='t'){
										res=sqrt(var);
							
										sprintf(tempo, "%.4lf", res);

										replace(pa[p1-1]-4, pc, tempo);

										i=0;
										p1--;
									}
									
									else
									{
										if(Datos.funcion[pc+1]=='^'){
											pot=variable(pc+2,2,pc+2,pc+4);
											
											res=pow(var, pot);
											
											itoa(pot, buffer, 10);

											inc=strlen(buffer);
											
											sprintf(tempo, "%.4lf", res);
											
											replace(pa[p1-1], pc+inc+1, tempo);

											i=0;
											p1--;
										}
										else
										{
											res= var;
											
											sprintf(tempo, "%.4lf", res);

											replace(pa[p1-1], pc, tempo);

											i=0;
											p1--;

										}
									}
								}
							}
							
						}
					}
				}
				
			}
		}


			
			i++;
			if(p1==0)
				fin=true;
	}while(fin == false);
	//while(Datos.funcion[i] != '\0');
	
	printf("%lf",res);
	
	return;

}
				
		
			
double operacion(int inicial, int final) 
{
	int i, v;
	double var[10], res;
	char tempo[50];
	bool resta;

	v=0;
	i=inicial;
	resta=false;

	do
	{
		/*Como prioridad primero busca dentro del parentesis los exponentes*/
		if(Datos.funcion[i]=='^'){
			/*Una vez localizado se mueve dentro de funcion una posicion atras
			y a partir de ahi sin salirse del parentesis buscara el numero a elevar*/
			var[v]=variable(i-1,1,inicial, final);
			i=inicial;
			do{
				if(Datos.funcion[i]=='^'){
					/*La funcion variable buscara un numero a partir de la posicion del operador*/
					var[v+1]=variable(i+1,2, inicial, final); //el numero 2 es para decirle a la funcion que busque a la derecha
					/*Una vez conseguidas las variables se realiza la operacion*/
					res=pow(var[v],var[v+1]); 
					sprintf(tempo, "%.4lf", res);
					replace(i-1, i+1, tempo);
					break;
				}
				else
				{
					i++;
				}
			}while(Datos.funcion[i] != ')');
		}
		i++;
	}while(Datos.funcion[i] != ')');

	v=0;
	i=inicial;
	do
	{
		/*Hace el mismo proceso que el anterior pero ahora con la multiplicacion*/
		if(Datos.funcion[i]=='*'){
			var[v]=variable(i-1,1,inicial, final);
			
			i=inicial;

			do{
				if(Datos.funcion[i]=='*'){
					var[v+1]=variable(i+1,2, inicial, final);
					res=var[v]*var[v+1];
					sprintf(tempo, "%.4lf", res);
					replace(i-1, i+1, tempo);
					break;
				}
				else
				{
					i++;
				}
			}while(Datos.funcion[i] != ')');
		}
		i++;
	}while(Datos.funcion[i] != ')');

	v=0;
	i=inicial;
	
	do
	{
		if(Datos.funcion[i]=='/'){
			var[v]=variable(i-1,1,inicial, final);
			i=inicial;

			do{
				if(Datos.funcion[i]=='/'){
					var[v+1]=variable(i+1,2, inicial, final);
					res=var[v]/var[v+1];
					sprintf(tempo, "%.4lf", res);
					replace(i-1, i+1, tempo);
					break;
				}
				else
				{
					i++;
				}
			}while(Datos.funcion[i] != ')');
		}
		i++;
	}while(Datos.funcion[i] != ')');

	v=0;
	i=inicial;

	do
	{
		if(Datos.funcion[i]=='+'){
			var[v]=variable(i-1,1,inicial, final);
			i=inicial;
			
			do{
				if(Datos.funcion[i]=='+'){
					var[v+1]=variable(i+1,2, inicial, final);
					res=var[v]+var[v+1];
					sprintf(tempo, "%.4lf", res);
					replace(i-1, i+1, tempo);
					break;
				}
				else
				{
					i++;
				}
			}while(Datos.funcion[i] != ')');
		}
		i++;
	}while(Datos.funcion[i] != ')');
	
	v=0;
	i=inicial;

	do
	{		
		if(Datos.funcion[i]=='-'){
			var[v]=variable(i-1,1,inicial, final);
			i=inicial;

			do{
				if(Datos.funcion[i]=='-'){
					var[v+1]=variable(i+1,2, inicial, final);
					if(var[v]==0){
						res=-1*var[v+1];
						sprintf(tempo, "%.4lf", res);
						replace(i, i+1, tempo);
						resta=true;
						break;
					}
					else{

						res=var[v]-var[v+1];
						sprintf(tempo, "%.4lf", res);
						replace(i-1, i+1, tempo);
						break;
					}
				}
				else
				{
					i++;
				}
			}while(Datos.funcion[i] != ')');
		}
		i++;
	}while(Datos.funcion[i] != ')');


	/* Si la operacion fue de resta se regresa el resultado*/
	if(resta==true){ 
		return res;
	}

	/*De otro modo en caso de que no se haya encontrado operacion
	entonces quiere decir que dentro del parentesis hay una constante*/
	else{

		if(res<0){
			/* Las constantes pueden ser qp, qd o qt que son variables que se usaran despues*/
			if(Datos.funcion[inicial+1]=='q'){
				if(Datos.funcion[inicial+2]=='p'){
					res=90; // de momento se reemplaza qp con 90
				}
				else
					res=40;
			}
			else
			{
				if(Datos.funcion[i]=='p'){
					res=3.1416;
				}
				else
				{		
					res=variable(inicial+1,2,inicial,final);
				}
			}
		}
	}
	
		return res;
}


double variable (int partida, int pos, int inicial, int final)
{
	int v, j, i, k;
	char var[50], tempo[50], tempo2[50];
	double res, compa;
	bool punto;
	bool neg;

	v=0;
	k=0;
	neg=false;
	punto=false;
	strcpy(tempo, "");
	strcpy(var, "");

	
	/* 1 indica que la busqueda es a la izquiera y 2 que es a la derecha*/
	if(pos==1){ 
		
		for (i=partida; i>= inicial; i--){

			compa=isdigit(Datos.funcion[i]); //busca enteros

			if(compa != NULL){
				var[v]=Datos.funcion[i];
				v++;
			}
			else{
				if(Datos.funcion[i]=='.'){ //con decimal
					var[v]='.';
					v++;
				}
				else
				{
					/* Se buscan constantes que pueden ser PI, qp, qd o qt*/
					if(Datos.funcion[i]=='i'){ 
						res =3.1416;
						return res;	
					}
					else
					{
						if(Datos.funcion[i]=='p'){
							strcpy(var, "qp");
						}
						else
						{
							if(Datos.funcion[i]=='t'){
								strcpy(var, "qt");
							}
							else
							{
								if(Datos.funcion[i]=='-'){  //en caso de ser negativo el numero lo marca
									compa=isdigit(Datos.funcion[i-1]);
									if(compa != NULL){
										neg=false;
										break;
									}
									else{
										neg=true;
										break;
									}
								}
								else
									break;
							}
						}
					}
				}
			}
		}
			
		if(v==0){
			return NULL;
		}
		else
		{
			for(j=v-1; j>=0; j--){ //Como el numero se guardo de derecha a izq. lo regresa a como debe
				tempo[j]=var[k];
				k++;
			}
		
			strcpy(tempo2, "v");
			replace(partida+1-v, partida, tempo2); //Reemplaza el resultado obtenido
		}

	}

	if(pos==2){
		for (i=partida; i<= final; i++){

			compa=isdigit(Datos.funcion[i]);

			if(compa != NULL){
				tempo[v]=Datos.funcion[i];
				v++;
			}
			else
			{
				if(Datos.funcion[i]=='.'){
					tempo[v]='.';
					v++;
				}

				else
				{
					if(Datos.funcion[i]=='p'){
						res =3.1416;
						return res;	
					}

					else
					{
						if(Datos.funcion[i]=='q'){
							if(Datos.funcion[i+1]=='p')
								strcpy(var, "qp");
							else
								strcpy(var, "qt");
						}
						else
							break;
					}
				}
			}
		}
			
		strcpy(tempo2, "v");
		replace(partida, partida+v-1, tempo2);
	}
		
	if(neg==true){
		res = atof(tempo);
		res= -1*res;
		
	}
	else
	{
		res = atof(tempo);
	}
	
	return res;
}


void replace (int pos, int parfin, char reemplazo[60])
{
	int i, k;
	char tempo[50];

	i=parfin+1;
	k=0;

	do
	{
		tempo[k]=Datos.funcion[i];
		i++;
		k++;
	}while(Datos.funcion[i-1] != '\0');

	i=pos;
	k=0;

	do
	{
		Datos.funcion[i]=reemplazo[k];
		k++;
		i++;
	
	}while(reemplazo[k] != '\0');

	i=pos+k;
	k=0;

	do{
		Datos.funcion[i]=tempo[k];
		i++;
		k++;
	}while(tempo[k-1] != '\0');

}

double Sgn(double var)
{
	if(var > 0)
		return (1);
	else
		if(var == 0)
			return (0);
		else
				return (-1);
}


