[ Foro de Pascal ]
buenas tardes profesor Nacho cabanes y compañeros.
necesito evaluar una expresion que inicialmente contendra variables con valores del 1 al 26 segun corresponda la letra del abecedario(a=1;b=2,c=3,...z=26), cada variable solo aparecera una vez en la expresion.
porejemplo:
a+c-d+b=(1+3-4+2)=2
espero su ayuda y orientacion y ojala este link no quede en el vacio como varios link ya de los cuales he planteado y se han quedado ahi al vacio ..., agradezco si me pueden ayudar.gracias.
Hola Óscar.
O sea, digamos que tenemos un array de 26 campos (del 1 al 26) que contienen las letras en orden, ¿no? (Si lo he entendido bien...).
Sea, además, una variable de tipo string, que es la que imputa el usuario (por ejemplo "a+c-d+b").
Entonces tú tendrías que ir leyendo carácter a carácter y:
- si te encuentras un signo, pones una variable (que podríamos llamar "signo" a 1 o -1.
- si te encuentras una letra, la buscas en el array y la operas a lo acumulado teniendo en cuenta el signo.
Luego hay algunos otros pequeños detalles, pero la idea básica es esa.
Espero haberte dado algún enfoque.
Ciao.
Pero, ¿cómo se realizan las operaciones?. Saludos.
Gracias Antonio y luis por permitirme su orientacion y ayuda.
Antonio y como asigno a ese array de 26 campos de letras cada valor, es decir, para que a la letra 'a' le corresponda el 1 (a=1),a la letra 'b' el 2 (b=2),..a la letra 'c' el 3(c=3),...a la letra 'z' el 26( z=26).
para llenar el array con caracteres yo se que puedo hacer:
...
i:integer;
alfabeto:array[1..26] of char;
...
for i:=1 to 26 do
alfabeto[i]:=chr(i+96);
de tal forma que alfabeto contendria en este momento:
alfabeto = a b c d e f .... z
pero como hago como te comente al inicio para que a cada letra le corresponda los valores numericos 1, 2, 3, 4, ..26 y poder luego de esta forma hacer las operaciones???
se que la funcion ORD( unCaracter ) devuelve la representación numérica en el código ASCII del caracter unCaracter.
mil gracias por su ayuda .
Hola,
¡Ah! Ya se me había olvidado la función "ord()".
Pues ni con array, olvídate de eso; es más sencillo. En vez de un array yo utilizaría esa función.
Imagina que ya tengo la cadena de texto "cadena_texto". Además se sabe que en la posición 0 de un string se almacena su longitud, en forma de letra.
Por otro lado, tenemos una variable, a la que llamaré "suma" y que se arranca en 0.
La idea, más o menos:
********************************************
signo = 1;
suma = 0;
for i:=1 to ord(cadena_texto[0]) do
si cadena_texto[i] not in ('-','+') entonces
suma:= suma + signo*( ord(cadena_texto[i]) - 38 );
else
if cadena_texto[i] = '+' entonces
signo = 1
else
signo = -1;
*******************************************
Vale, ahora las notas:
- Lo que he escrito arriba es una chapuza (hay errores varios y mexcla entre código y pseudocódigo...) Blaj! Lo siento no tengo mucho tiempo.
- Lo del 38 no es una invención mía, pero a lo mejor no es correcto. Hay que ver qué valor numérico le corresponde a la letra 'a'. Creo que era 39, así que si le restas 38, te da 1.
- Asumimos que en la cadena solo hay letras de la 'a' a la 'z' y los signos.
- ¿Dudas?
- Ya que casi está resuelto (a no ser que Nacho diga lo contrario, claro), inténtalo incluyendo, además, letras mayúsculas (para ello puedes diseñar una función que te convierta una mayúscula en minúscula y aplicarla, o a lo mejor ya existe una función en Pascal).
¡Ciao!
gracias antonio por que tu siempre estas pendiente de ayudarnos y con frecuencia lo haces , mil gracias para ti.
antonio dos dudas al respecto:
- cuando haces:
si cadena_texto[i] not in ('-','+') entonces
suma:= suma + signo*( ord(cadena_texto[i]) - 38 );
si el caracter de cadena_texto no esta en el conjunto ['-','+']
que almacena suma? pues me imagino que suma es un integer y supongo que estarias porejemplo para la expresion 'a+b' escogiendo el valor para a inicialmente verdad? luego entraria al
else
if cadena_texto[i] = '+' entonces
signo = 1
y despues tomaria el valor para b?
si es asi , que pasaria en el caso que porejemplo se tuviera una expresion como:
'++a-b++? que cambios deberian hacerse en tu esquema inicial antonio?
mil gracias por tu ayuda y amabilidad y por que siempre respondes a nuestros hilos...
cordial saludo antonio, gracias por tu explicacion , sin embargo queria preguntar respecto a como seria en el caso real de ese tipo de expresiones donde logicamente cada variable aparezca una vez en la expresion ( asi que a-bc no seria correcto para una expresion a evaluar), donde sabemos que cuando el operador ++ aparece antes de una variable, el valor de esa variable debe incrementarse en uno, antes de que sea usada la variable dentro de la expresion completa, asi porejemplo si tenemos la expresion:
++c-b seria 2 por que c se incrementa a 4 antes de evaluar la expresion entera , asi tambien si el operador ++ aparece despues de la variable, el valor de esta variable debe ser incrementado en uno despues de que su valor sea utilizado para la evaluacion de la expresion asi porejemplo c++-b seria igaul a 1, de igual forma si fuese el caso del operador -- antes o despues.
asi porejemplo en resumen como podria ser el programa para ese tipo de variante que te consulto en este hilo?
ejemplos:
a+b =3
b-z = 24 ( 2-26 )
a+b--+c++= 6
f--+c--+d-++e= 7
ojala puedas ayudarme con esto y que el prefesor nacho cabanes nos de su toque brillante e impecable como siempre para poder encontrar la forma de solucionar este tipo de expresiones y que no se olvide de ayudarme u orientarme como siempre ha sido mi intencion. de hecho he podido solucionar muchisimos ejercicios por este foro con algunas indicaciones o a veces con sus valiosas soluciones.
gracias.
Hola,
En ese caso deberías de utilizar dos variables más:
- Una que indique el valor de la letra anterior. (anterior)
- Otra que acumule el valor del modificador a la variable. (moodificador).
Así podrías ir jugando con esas dos variables y las anteriores.
De todas maneras, hay otra estrategia, que se basa en que solo nos interesa el resultado final: ir sumando o restando según me encuentre un valor de signo, y luego corregir la variable.
Es decir, tengo: ++c-.
Pues haría: 1, 1, 2, -1.
Es decir, lo único que hay que hacer es sumarle el "signo" (cuyo valor será (1 ó -1) a la variable "suma" y en la operación en la que se utilizaba la función ord(), restarle una unidad más a la variable. Copio, pego y modifico:
********************************************
signo = 1;
suma = 0;
for i:=1 to ord(cadena_texto[0]) do
si cadena_texto[i] not in ('-','+') entonces
suma:= suma + signo*( ord(cadena_texto[i]) - 39 );
else begin
if cadena_texto[i] = '+' then
signo = 1;
else
signo = -1;
suma:= suma + signo;
end;
*******************************************
Prueba así a ver si te funciona.
Nacho, ¿tú qué opinas?
Adiós.
Veamos...
Veo algunas ideas que están bien, pero también otras "peligrosas". De momento, me voy a saltar el caso de expresiones con "--" y "++", para que la forma de analizar sea un poco más simple, de modo que (todavía) no funcionará con cosas como:
f--+c--+d-++e= 7
pero sí con expresiones sencillas como:
a+c-d+b
Un par de consideraciones:
- Para calcular el valor de cada variable a partir de la letra, la "a" (a minúscula) tiene el código ASCII 97, así que la expresión sería "ord(letra)-96". Aun así, por legibilidad y por mantenibilidad, yo no pondría esa expresión directamente en los cálculos, sino que usaría una función auxiliar.
- En cuanto a las expresiones en sí, lo natural es hacerlo con "while": "mientras queden símbolos, leo el operador y la siguiente variable", añadiendo el caso excepcional de que si el segundo símbolo ha resultado ser también un operador, se trataría de un "++" o un "--". Si damos por sentado que (todavía) no existen estos dos símbolos, se podría leer incluso con un "for": se calcula cuantos "pares" hay, y se se van leyendo y calculando uno a uno.
- Esto sólo funciona si los operadores son + y -, que tienen la misma prioridad, de modo que se puede analizar de izquierda a derecha. Si hubiera *, /, potencias o símbolos de negación, que tienen distintas prioridades, el planteamiento debería ser totalmente distinto.
En un ratito os preparo un ejemplo completo...
Allá va...
program analizarExpresiones1;
(* Calcula el valor de una variable; en este caso,
será su posición en el alfabeto *)
function valorVariable(letra: char): integer;
begin
valorVariable := ord(letra)-96;
end;
(* Analiza una expresión del tipo a+c-d+b *)
function analizar(expresion: string): integer;
var
primeraVariable, operador, siguienteVariable: char;
cantidadExpresiones: integer;
posicion: integer;
resultado: integer;
begin
cantidadExpresiones := (length(expresion)-1) div 2;
primeraVariable := expresion[1];
resultado := valorVariable( primeraVariable );
for posicion := 1 to cantidadExpresiones do
begin
operador := expresion[posicion*2];
siguienteVariable := expresion[posicion*2+1];
if operador = '+' then
resultado := resultado + valorVariable( siguienteVariable )
else if operador = '-' then
resultado := resultado - valorVariable( siguienteVariable );
(* else... mostrar mensaje de error *)
end;
analizar := resultado;
end;
(* Cuerpo del programa: casos de prueba *)
begin
Write( analizar('a+c-d+b') );
end.
Cordial saludo profesor Nacho Cabanes, impecable tu explicacion y tu solucion mas clara, y facil de entender aun muchisimo mejor, mil gracias de verdad, sin dejar de serlo extensivo para Antonio, luis, fulanito etc....
profesor en el caso que comentamos con Antonio para expresiones:
f--+c--+d-++e= 7,
cual seria la estrategia a seguir o por lo menos la que tu propongas para hacer que cada variable segun sea que la anteceda o prrecedan operadores del tipo ++ y --, para aumentar ( o disminuir) en uno el valor de la variable antes de que sea usada la variable dentro de la expresion completa ( para casos en que el operador ++ anteceda a la variable), o en el caso de que debe ser incrementado en uno despues de que su valor sea utilizado( para casos en que el operador ++ preceda a la variable), ojala puedas ayudarnos por que se que para mas de un compañero este ejercicio es de bastante enriquecimiento para no olvidar o dejar de practicar la programacion, en mi caso lo propuse por que me motiva muchisimo el aprender y APROVECHAR de la mejor manera tus excelentes orientaciones y ayudas que nunca dejas de darnos y se que conmigo estaran todos los compañeros de acuerdo que son explicaciones de alto nivel y todo un privilegio al venir de un excelente profesor como tu... que afortunados sois quienes son tus alumnos.gracias por tu vocacion de brindaros siempre una mano y tenernos paciencia.
mil gracias y en espera ansiosa de tu conocimiento para de el al menos asimilar un poquito poco a poco.
Excelente explicación y maravillosa la manera de codificarlo. Todo se entiende con poco esfuerzo. Muy bien pensado, porque todo encaja. Me muero por ver la parte en la que aparecen los operadores ++ y --. Muchos saludos.
(No se puede continuar esta discusión porque tiene más de dos meses de antigüedad. Si tienes dudas parecidas, abre un nuevo hilo.)