Hacer un algoritmo no es programar. Sin embargo, hacer un pseudocódigo algorítmico ya es una buena aproximación. Pensar en un algoritmo es pensar en una estrategia de solución. Pensar en un pseudocódigo es aproximarse a las tácticas. Esto es, cuando hacemos pseudocódigo ya estamos diseñando una solución computacional. Debido a ello, es indispensable pensar de forma general en algunos conceptos previos a la programación, y uno de ellos es la forma en que representamos los datos dentro de nuestros algoritmos.
Hacer un buen manejo de tipos de datos en programación se da por sentado cuando se hace software de buena calidad. Sin embargo, cuando un neófito está comenzando a programar, muchas veces es el primer tema que deja de lado, y más aún hoy, cuando tiene a disposición lenguajes que manejan los tipos de los datos de forma dinámica con base en el contexto del código fuente. Desafortunadamente, el resultado de no entender los tipos de datos podría llegar a significar problemas de rendimiento del software, o fallas inesperadas que no serían necesariamente fáciles de diagnosticar. Por lo tanto, y sin más justificación, le ruego al lector considere los tipos de datos una piedra angular de la tarea de programar.
Hay lenguajes de programación que hacen gran hincapié en los tipos, y obligan a que toda variable u objeto se declare con un tipo de dato explícito, y se les conoce como lenguajes de tipos estáticos, lo que es muy común en lenguajes compilados. Otros lenguajes solo sabrán de tipos durante su ejecución, y se les conoce como lenguajes de tipificación dinámica.
Los lenguajes de ‘scripting’ (en este libro dedicamos un capítulo entero denominado 'workshop de python básico 'a entender un poco el lenguaje interpretado Python), caen en la categoría del dinamismo, y es esa precisamente la categoría que prefieren muchas personas que buscan aprender a programar, pues implica menos en qué pensar, o al menos será un tema poco obligado, implicando que se programa más fácil.
Hoy también hay muchos lenguajes que adoptan una postura intermedia, y te permiten un buen manejo de tipos, y a su vez permiten inferir los tipos desde las expresiones, lo que redunda en un ganar-ganar. Esto es, no caemos en el extremo de tener que hacer explícito el tipo de cada elemento, y tampoco caemos en el otro extremo de no hacerlo nunca.
A pesar de las posibilidades anteriores, tener conciencia de los tipos es fundamental al momento de programar, ya que muchos aspectos de la programación se relacionan con la forma en que los datos son representados y guardados en la memoria de un computador y cómo los lenguajes hacen uso de estos datos.
Hacer un buen manejo de tipos de datos en programación se da por sentado cuando se hace software de buena calidad. Sin embargo, cuando un neófito está comenzando a programar, muchas veces es el primer tema que deja de lado, y más aún hoy, cuando tiene a disposición lenguajes que manejan los tipos de los datos de forma dinámica con base en el contexto del código fuente. Desafortunadamente, el resultado de no entender los tipos de datos podría llegar a significar problemas de rendimiento del software, o fallas inesperadas que no serían necesariamente fáciles de diagnosticar. Por lo tanto, y sin más justificación, le ruego al lector considere los tipos de datos una piedra angular de la tarea de programar.
Hay lenguajes de programación que hacen gran hincapié en los tipos, y obligan a que toda variable u objeto se declare con un tipo de dato explícito, y se les conoce como lenguajes de tipos estáticos, lo que es muy común en lenguajes compilados. Otros lenguajes solo sabrán de tipos durante su ejecución, y se les conoce como lenguajes de tipificación dinámica.
Los lenguajes de ‘scripting’ (en este libro dedicamos un capítulo entero denominado 'workshop de python básico 'a entender un poco el lenguaje interpretado Python), caen en la categoría del dinamismo, y es esa precisamente la categoría que prefieren muchas personas que buscan aprender a programar, pues implica menos en qué pensar, o al menos será un tema poco obligado, implicando que se programa más fácil.
Hoy también hay muchos lenguajes que adoptan una postura intermedia, y te permiten un buen manejo de tipos, y a su vez permiten inferir los tipos desde las expresiones, lo que redunda en un ganar-ganar. Esto es, no caemos en el extremo de tener que hacer explícito el tipo de cada elemento, y tampoco caemos en el otro extremo de no hacerlo nunca.
A pesar de las posibilidades anteriores, tener conciencia de los tipos es fundamental al momento de programar, ya que muchos aspectos de la programación se relacionan con la forma en que los datos son representados y guardados en la memoria de un computador y cómo los lenguajes hacen uso de estos datos.
TIPOS EN PSEUDOCÓDIGOS
Hablar de tipos es referirse al dominio de los datos. Un dominio de datos es el conjunto de posibles valores que una variable puede tomar. Por ejemplo, un valor podrá ser un número real, digamos 8.7, o un número entero, como -9, o como +128; si el programador es explícito sobre ese hecho, ya hay una ganancia.
Otros tipos bastante comunes son los caracteres, siendo un caracter una letra en cualquier alfabeto de cualquier idioma (aquí la palabra no es caracter con tilde), o cualquier símbolo estándar universal que se use para escribir, incluyendo símbolos muy usados hoy en los chats (caritas, banderas, símbolos, etc.).
En el caso de un chat, la representación puede hacerse con un solo caracter, o como un conjunto de caracteres (textos denominados también ‘strings’ de caracteres). También a veces queremos decir que un valor es falso, o verdadero, y hablamos de valores lógicos o booleanos, un tipo totalmente fundamental en el contexto algorítmico. Otros lenguajes van más allá, y representan dominios especializados, como los números racionales, y los números complejos.
Durante nuestros pseudocódigos, debemos tener en cuenta quién lo va a leer (libro, publicación, sólo personal, equipo de trabajo), y ser juiciosamente explícitos si queremos lograr el objetivo de lograr código más robusto y respetable.
Podríamos generalizar diciendo que no conocemos el tipo del dato de un objeto o variable y que el tipo debe ser deducido del contexto, pero también podríamos declarar explícitamente que ese dato informático es de tipo real, o es entero, o es un caracter, o una cadena de caracteres o ‘string’, o algún otro tipo de dato diferente como los naturales, reales positivos o negativos, racionales, imaginarios y complejos, o algún conjunto muy especial.
Con todo eso será suficiente para expresar todos nuestros datos, a menos que se necesite ser mucho más concreto. En ese orden de ideas, es claro que un dato debe estar asociado a un solo tipo y no a varios.
De ahora en adelante, cada que queramos referirnos a un tipo, lo haremos anteponiendo la secuencia ‘::’ (dos veces dos puntos – doble ‘colon’ en inglés), que indica que a continuación se especifica un tipo de dato. Por ejemplo, para especificar que una variable w es de tipo entero, diremos w :: T, donde T es alguno de los tipos que veremos a continuación.
Otros tipos bastante comunes son los caracteres, siendo un caracter una letra en cualquier alfabeto de cualquier idioma (aquí la palabra no es caracter con tilde), o cualquier símbolo estándar universal que se use para escribir, incluyendo símbolos muy usados hoy en los chats (caritas, banderas, símbolos, etc.).
En el caso de un chat, la representación puede hacerse con un solo caracter, o como un conjunto de caracteres (textos denominados también ‘strings’ de caracteres). También a veces queremos decir que un valor es falso, o verdadero, y hablamos de valores lógicos o booleanos, un tipo totalmente fundamental en el contexto algorítmico. Otros lenguajes van más allá, y representan dominios especializados, como los números racionales, y los números complejos.
Durante nuestros pseudocódigos, debemos tener en cuenta quién lo va a leer (libro, publicación, sólo personal, equipo de trabajo), y ser juiciosamente explícitos si queremos lograr el objetivo de lograr código más robusto y respetable.
Podríamos generalizar diciendo que no conocemos el tipo del dato de un objeto o variable y que el tipo debe ser deducido del contexto, pero también podríamos declarar explícitamente que ese dato informático es de tipo real, o es entero, o es un caracter, o una cadena de caracteres o ‘string’, o algún otro tipo de dato diferente como los naturales, reales positivos o negativos, racionales, imaginarios y complejos, o algún conjunto muy especial.
Con todo eso será suficiente para expresar todos nuestros datos, a menos que se necesite ser mucho más concreto. En ese orden de ideas, es claro que un dato debe estar asociado a un solo tipo y no a varios.
De ahora en adelante, cada que queramos referirnos a un tipo, lo haremos anteponiendo la secuencia ‘::’ (dos veces dos puntos – doble ‘colon’ en inglés), que indica que a continuación se especifica un tipo de dato. Por ejemplo, para especificar que una variable w es de tipo entero, diremos w :: T, donde T es alguno de los tipos que veremos a continuación.
Declaración de tipos en pseudocódigo
La forma anteriormente planteada para declarar una variable será la forma preferida en este texto cuando se trabaje con pseudocódigo, pero una forma alternativa de hacerlo será escribir alguna frase en lenguaje natural que exprese que la variable w será de un tipo concreto o abstracto.
Esto es posible porque nuestros pseudocódigos no estarán escritos para un lenguaje de programación concreto.
Siguiendo con nuestro ejemplo de declarar la variable w de un tipo, podríamos preferir hacerlo en un lenguaje más natural y escribir
w of type T
declare w of type T
Por supuesto, podríamos usar otro idioma como español, alemán, mandarín, o ruso, pero el inglés es preferible, ya que es más universal. De hecho, casi todo lenguaje de programación, sin importar quién programe con él o en qué plataforma lo haga, tendrá sintaxis en inglés.
En pseudocódigo, es preferible simplificar la lectura, y a veces los principiantes podrían no usar una frase adecuada, por lo que para efectos de declarar el tipo de una variable, se sugiere usar la forma
w :: T
Esto es posible porque nuestros pseudocódigos no estarán escritos para un lenguaje de programación concreto.
Siguiendo con nuestro ejemplo de declarar la variable w de un tipo, podríamos preferir hacerlo en un lenguaje más natural y escribir
w of type T
declare w of type T
Por supuesto, podríamos usar otro idioma como español, alemán, mandarín, o ruso, pero el inglés es preferible, ya que es más universal. De hecho, casi todo lenguaje de programación, sin importar quién programe con él o en qué plataforma lo haga, tendrá sintaxis en inglés.
En pseudocódigo, es preferible simplificar la lectura, y a veces los principiantes podrían no usar una frase adecuada, por lo que para efectos de declarar el tipo de una variable, se sugiere usar la forma
w :: T
Tipo Entero
Un tipo de dato entero define un dominio de números enteros positivos o negativos incluido el cero. En lo que sigue, los tipos (::Z, ::Int, ::Integer), son el mismo.
Para efectos de pseudocódigo, el tipo de dato entero se asocia a un dato numérico no real. Por ejemplo, el número 4 pertenece al dominio de los números enteros positivos ::Z+. Otro ejemplo: el número -8 pertenece a los números enteros negativos ::Z-.
En el caso que se desee especificar solo los números enteros positivos, puede escribir ::Z+≠0 o ::Z+ - {0}; a este conjunto se le conoce como los números naturales, aunque algunos matemáticos prefieren incluir el cero dentro de los naturales, y en ese orden de ideas, podríamos decir también que los números naturales con los enteros positivos ::Z+.
Para efecto de nuestros pseudocódigos, podremos escribir también si el dominio de los datos se restringe solo a valores negativos ::Z-, que no incluyen el cero.
Para efectos de pseudocódigo, el tipo de dato entero se asocia a un dato numérico no real. Por ejemplo, el número 4 pertenece al dominio de los números enteros positivos ::Z+. Otro ejemplo: el número -8 pertenece a los números enteros negativos ::Z-.
En el caso que se desee especificar solo los números enteros positivos, puede escribir ::Z+≠0 o ::Z+ - {0}; a este conjunto se le conoce como los números naturales, aunque algunos matemáticos prefieren incluir el cero dentro de los naturales, y en ese orden de ideas, podríamos decir también que los números naturales con los enteros positivos ::Z+.
Para efecto de nuestros pseudocódigos, podremos escribir también si el dominio de los datos se restringe solo a valores negativos ::Z-, que no incluyen el cero.
Tipo Natural
También, si lo prefiere, puede hablar del tipo de dato entero natural (::N o ::Natural), equivalente al tipo ::Z+.
Para evitar ambigüedades frente a la pertenencia del número cero a los números naturales, definiremos aquí que los números naturales ::N son los números enteros positivos incluyendo el cero, y escribiremos ::N, ::Natural, o de forma más precisa matemáticamente, ::N0 o ::Natural0.
Cuando se quiere indicar que los números naturales no incluyen el cero, en pseudocódigo se usará ::N+ o ::N* o ::Z > 0.
Si por el contrario se quiere especificar que se trabaja con números naturales incluyendo el cero, se usará alguna entre ::N, ::Natural, ::N0 o ::Natural0.
Dado que el conjunto de los números naturales ::N es un subconjunto de los números enteros ::Z, podemos escribir que ::N ⊂ ::Z.
Para evitar ambigüedades frente a la pertenencia del número cero a los números naturales, definiremos aquí que los números naturales ::N son los números enteros positivos incluyendo el cero, y escribiremos ::N, ::Natural, o de forma más precisa matemáticamente, ::N0 o ::Natural0.
Cuando se quiere indicar que los números naturales no incluyen el cero, en pseudocódigo se usará ::N+ o ::N* o ::Z > 0.
Si por el contrario se quiere especificar que se trabaja con números naturales incluyendo el cero, se usará alguna entre ::N, ::Natural, ::N0 o ::Natural0.
Dado que el conjunto de los números naturales ::N es un subconjunto de los números enteros ::Z, podemos escribir que ::N ⊂ ::Z.
Tipo Real
Un tipo de dato real define un dominio de números reales positivos o negativos incluido el cero. Los números reales contienen una parte entera y una fraccionaria.
El número pi, cuyo valor es 3.14159265358… es un número que pertenece al dominio de los números reales positivos ::R+, mientras que el número -123.8 pertenece al dominio de los números reales negativos ::R-.
La unificación de los conjuntos de números ::R+ y ::R- se les conoce como ::R, y contiene cualquier número entre -∞(infinito negativo) y +∞ (infinito positivo), o sea, todos los números.
El símbolo ∞ se llama lemniscate, pero se le conoce en algunos lenguajes de programación simplemente como infinito.
Se asume que aquí, en los pseudocódigos, referiremos estos números con cualquiera de las formas ::R, ::Real, ::Float o ::F y podremos adicionar los signos y menos (+, -) para referirnos a un subconjunto de números más concreto, como los reales positivos o los reales negativos.
El número infinito negativo lo llamaremos -∞, -.infinity., -.Inf., y el número infinito positivo lo llamaremos +∞ , +.infinity., +.Inf.
Debemos tener en cuenta que, en computación, un número real es diferente de un número entero, así matemáticamente se trate del mismo número. Eso se debe a que, en computación, la representación interna de un número entero y un número real es diferente. Por tal motivo, debemos tener claridad de cuál tipo usar en un dato específico que se presente al resolver un problema usando algoritmos. En pseudocódigo, esta diferenciación no es tan estricta como veremos.
El número pi, cuyo valor es 3.14159265358… es un número que pertenece al dominio de los números reales positivos ::R+, mientras que el número -123.8 pertenece al dominio de los números reales negativos ::R-.
La unificación de los conjuntos de números ::R+ y ::R- se les conoce como ::R, y contiene cualquier número entre -∞(infinito negativo) y +∞ (infinito positivo), o sea, todos los números.
El símbolo ∞ se llama lemniscate, pero se le conoce en algunos lenguajes de programación simplemente como infinito.
Se asume que aquí, en los pseudocódigos, referiremos estos números con cualquiera de las formas ::R, ::Real, ::Float o ::F y podremos adicionar los signos y menos (+, -) para referirnos a un subconjunto de números más concreto, como los reales positivos o los reales negativos.
El número infinito negativo lo llamaremos -∞, -.infinity., -.Inf., y el número infinito positivo lo llamaremos +∞ , +.infinity., +.Inf.
Debemos tener en cuenta que, en computación, un número real es diferente de un número entero, así matemáticamente se trate del mismo número. Eso se debe a que, en computación, la representación interna de un número entero y un número real es diferente. Por tal motivo, debemos tener claridad de cuál tipo usar en un dato específico que se presente al resolver un problema usando algoritmos. En pseudocódigo, esta diferenciación no es tan estricta como veremos.
Tipo Racional
Otro dato numérico es, por ejemplo, 1/4, que es un número cuyo resultado es 0.25. Todo número ::R que pueda ser representado como una relación entre dos números enteros (::Z / ::Z), se les conoce como número racional.
Por ejemplo,
7/7 da 1, de modo que 1 es un número racional.
1/3 es un número inexacto (0.33333333...), y dado que la secuencia de decimales se repite de forma indefinida, entonces 0.33333333... es un número racional ::Q [1].
Los números racionales también pueden ser definidos con signo para referirse a un conjunto más reducido, como los racionales positivos ::Q+, o los racionales negativos ::Q-.
También, el tipo de dato racional, se podrá representar con cualquiera de las formas ::Q, ::Ratio, ::Rational.
Ahora suponga que tiene un número real con una parte fraccionaria infinita no repetitiva y que no tiene fin; entonces el número no puede ser expresado como la relación de dos números enteros y a estos números se les conoce como irracionales. Entre los irracionales más conocidos tenemos √2, π, e y φ.
Los números irracionales no representan una división exacta, y por tal motivo, tienen un número infinito de cifras decimales. Cuando se analizan las secuencias de decimales de estos números irracionales, no es posible encontrar patrones repetitivos distintos a las apariciones casuales aleatorias entre sus dígitos.
Los números del tipo ::Q vistos como conjunto, son un subconjunto de los números ::R, lo que podemos escribir como ::Q ⊂ ::R.
[1] https://en.wikipedia.org/wiki/Rational_number
Por ejemplo,
7/7 da 1, de modo que 1 es un número racional.
1/3 es un número inexacto (0.33333333...), y dado que la secuencia de decimales se repite de forma indefinida, entonces 0.33333333... es un número racional ::Q [1].
Los números racionales también pueden ser definidos con signo para referirse a un conjunto más reducido, como los racionales positivos ::Q+, o los racionales negativos ::Q-.
También, el tipo de dato racional, se podrá representar con cualquiera de las formas ::Q, ::Ratio, ::Rational.
Ahora suponga que tiene un número real con una parte fraccionaria infinita no repetitiva y que no tiene fin; entonces el número no puede ser expresado como la relación de dos números enteros y a estos números se les conoce como irracionales. Entre los irracionales más conocidos tenemos √2, π, e y φ.
Los números irracionales no representan una división exacta, y por tal motivo, tienen un número infinito de cifras decimales. Cuando se analizan las secuencias de decimales de estos números irracionales, no es posible encontrar patrones repetitivos distintos a las apariciones casuales aleatorias entre sus dígitos.
Los números del tipo ::Q vistos como conjunto, son un subconjunto de los números ::R, lo que podemos escribir como ::Q ⊂ ::R.
[1] https://en.wikipedia.org/wiki/Rational_number
Tipo Complejo
Un número complejo se compone de una parte real, y una parte imaginaria. Por ejemplo, un número complejo sería -8.79 + 6.72im.
La parte imaginaria se compone de un número real y la letra i, o im.
Los números complejos ::C, ::Cplx o ::Complex, son otro tipo de dato que pondremos a disposición en nuestros pseudocódigos para evitar tener que construir estructuras alternativas para representar este tipo de dato, y así hacer la escritura más natural.
La parte imaginaria se compone de un número real y la letra i, o im.
Los números complejos ::C, ::Cplx o ::Complex, son otro tipo de dato que pondremos a disposición en nuestros pseudocódigos para evitar tener que construir estructuras alternativas para representar este tipo de dato, y así hacer la escritura más natural.
Tipo Número
Todos los datos numéricos anteriormente mencionados son específicos, pues se define claramente el tipo del dato sin ambigüedad. Pero a veces queremos generalizar el tipo, y en los pseudocódigos se podrá abstraer el tipo de los números simplemente al uno más general denominado ::Num, ::Number o ::Numeric.
Este tipo abstracto está habilitado para referirse a valores ::N, ::Z, ::Q, ::R, ::C, por lo que, durante las fases de aprendizaje, es muy útil. También es útil cuando queremos afirmar que el tipo al que hace alusión una variable es uno de ellos.
Este tipo abstracto está habilitado para referirse a valores ::N, ::Z, ::Q, ::R, ::C, por lo que, durante las fases de aprendizaje, es muy útil. También es útil cuando queremos afirmar que el tipo al que hace alusión una variable es uno de ellos.
Tipo Caracter
Pero en computación no solo trabajamos con números. Todos hemos visto letras o símbolos. Por ejemplo, podríamos querer escribir un texto, como ”שלום” en hebreo, o como “Hola” en español, o “Χαίρετε” en griego, “Здравствуйте” en ruso, “你好” chino, “नमस्ते” en indi, “ مرحبا” en árabe, etc.
Todas estas palabras en distintos idiomas están compuestas de símbolos en su respectivo idioma. Pero para un computador, estas colecciones de símbolos no tienen ningún significado; por tal motivo, a cada letra o símbolo se le asigna un código numérico diferente.
Hay muchas tablas de códigos para poder hablar de símbolos, pero actualmente la tabla de códigos más popular es la Unicode [1], que permite trabajar con prácticamente cualquier símbolo de escritura de cualquier lenguaje conocido.
Por ejemplo, asignamos el número 65 a la letra ‘A’, asignamos el número 66 a la letra ‘B’, el código 1488 corresponde al caracter israelí ’א’, etc. En total, la tabla Unicode puede representar hasta 1114112 caracteres. Note que delimitamos entre apóstrofes (‘ ’) el caracter especifico.
Los dígitos numéricos exigen también una representación visual y poseen un caracter asociado; por lo tanto, también necesitan un código; por ejemplo, el caracter ‘0’ tiene código Unicode 48, el ‘1’ tiene el código Unicode 49, el ‘2’ tiene el código Unicode 50, y así sucesivamente. Una de las tablas más viejas aún es la tabla de códigos ASCII, que solo tenía capacidad para 255 caracteres, que se lograban representar con un solo byte de 8 bits. Aún se usa por compatibilidad.
Dicho lo anterior, ¿qué tipo de dato es éste que no es un número sino un caracter con código numérico? Lo llamaremos tipo de dato ::Character , ::Char, o ::Chr. Un caracter representa un símbolo útil para representar información, y siempre tiene un código Unicode asociado.
Existen otros caracteres que no tienen una representación gráfica, y se les conoce como caracteres de control, con significados concretos dependiendo del contexto, y también tienen su código respectivo en la tabla Unicode que permite representarlos. Un ejemplo es, por ejemplo, el salto de línea. El salto de línea no tiene una representación gráfica. Note qus usted no lo ve, pero sí ve su efecto cuando ve lo párrafos de este texto separados.
[1] https://unicode-table.com/
Todas estas palabras en distintos idiomas están compuestas de símbolos en su respectivo idioma. Pero para un computador, estas colecciones de símbolos no tienen ningún significado; por tal motivo, a cada letra o símbolo se le asigna un código numérico diferente.
Hay muchas tablas de códigos para poder hablar de símbolos, pero actualmente la tabla de códigos más popular es la Unicode [1], que permite trabajar con prácticamente cualquier símbolo de escritura de cualquier lenguaje conocido.
Por ejemplo, asignamos el número 65 a la letra ‘A’, asignamos el número 66 a la letra ‘B’, el código 1488 corresponde al caracter israelí ’א’, etc. En total, la tabla Unicode puede representar hasta 1114112 caracteres. Note que delimitamos entre apóstrofes (‘ ’) el caracter especifico.
Los dígitos numéricos exigen también una representación visual y poseen un caracter asociado; por lo tanto, también necesitan un código; por ejemplo, el caracter ‘0’ tiene código Unicode 48, el ‘1’ tiene el código Unicode 49, el ‘2’ tiene el código Unicode 50, y así sucesivamente. Una de las tablas más viejas aún es la tabla de códigos ASCII, que solo tenía capacidad para 255 caracteres, que se lograban representar con un solo byte de 8 bits. Aún se usa por compatibilidad.
Dicho lo anterior, ¿qué tipo de dato es éste que no es un número sino un caracter con código numérico? Lo llamaremos tipo de dato ::Character , ::Char, o ::Chr. Un caracter representa un símbolo útil para representar información, y siempre tiene un código Unicode asociado.
Existen otros caracteres que no tienen una representación gráfica, y se les conoce como caracteres de control, con significados concretos dependiendo del contexto, y también tienen su código respectivo en la tabla Unicode que permite representarlos. Un ejemplo es, por ejemplo, el salto de línea. El salto de línea no tiene una representación gráfica. Note qus usted no lo ve, pero sí ve su efecto cuando ve lo párrafos de este texto separados.
[1] https://unicode-table.com/
Tipo Cadena de Caracteres
Un conjunto de caracteres es posible expresarlo con un tipo de dato que llamaremos ‘string’ o ‘cadena de caracteres’, y que tipificaremos como ::S, ::String o ::Str.
Dado que un caracter siempre tiene un código asociado que es un número entero positivo, una cadena de caracteres se reduce a un conjunto de códigos numéricos consecutivos.
Por ejemplo, la cadena de caracteres “Здравствуйте” (hola en ruso), realmente para el computador es la lista de números 1047 1076 1088 1072 1074 1089 1090 1074 1091 1081 1090 1077 (de la tabla Unicode). Note que una cadena la delimitamos entre comillas dobles (“”), y eso es distinto al delimitador de apóstrofes que usamos para caracteres.
Esto también es verdad para muchos lenguajes de programación, pero no para todos[1]. En nuestros speudocódigos, usaremos esta distinción de comilla simple para caracteres, y comilla doble par cadenas.
[1] El lenguaje de programación Python no distingue entre comillas dobles y simples. De hecho, no existe un tipo de dato caracter como en muchos otros lenguajes de programación.
Dado que un caracter siempre tiene un código asociado que es un número entero positivo, una cadena de caracteres se reduce a un conjunto de códigos numéricos consecutivos.
Por ejemplo, la cadena de caracteres “Здравствуйте” (hola en ruso), realmente para el computador es la lista de números 1047 1076 1088 1072 1074 1089 1090 1074 1091 1081 1090 1077 (de la tabla Unicode). Note que una cadena la delimitamos entre comillas dobles (“”), y eso es distinto al delimitador de apóstrofes que usamos para caracteres.
Esto también es verdad para muchos lenguajes de programación, pero no para todos[1]. En nuestros speudocódigos, usaremos esta distinción de comilla simple para caracteres, y comilla doble par cadenas.
[1] El lenguaje de programación Python no distingue entre comillas dobles y simples. De hecho, no existe un tipo de dato caracter como en muchos otros lenguajes de programación.
Tipo Booleano
Para finalizar, debemos mencionar otro tipo de dato muy importante, y es el conocido valor Booleano, que denotaremos como ::B, ::Bool, ::Boolean o ::Logic. Un valor booleano es aquel que es falso (.f.) o verdadero (.t.).
Un valor verdadero .t. se define como la negación de un valor falso .f.
Un valor falso .f. se define como la negación de un valor verdadero .t.
El tipo de dato lógico solo tiene esos dos posibles valores.
En pseudocódigo papercode podremos escribir
.false. o .true., .f. o .t.
o cualquier otra alternativa en otro idioma que garantice legibilidad y claridad, y siempre el valor entre dos puntos.
Esto tipo es fundamental para al momento de trabajar condiciones que bifurcan distintas rutas de pseudocódigo (o código) en los algoritmos, y para representar tipos de datos que solo pueden tomar esos dos valores.
Dejaremos para la sección de expresiones, el uso de dicho tipo.
Un valor verdadero .t. se define como la negación de un valor falso .f.
Un valor falso .f. se define como la negación de un valor verdadero .t.
El tipo de dato lógico solo tiene esos dos posibles valores.
En pseudocódigo papercode podremos escribir
.false. o .true., .f. o .t.
o cualquier otra alternativa en otro idioma que garantice legibilidad y claridad, y siempre el valor entre dos puntos.
Esto tipo es fundamental para al momento de trabajar condiciones que bifurcan distintas rutas de pseudocódigo (o código) en los algoritmos, y para representar tipos de datos que solo pueden tomar esos dos valores.
Dejaremos para la sección de expresiones, el uso de dicho tipo.
DATOS EN MEMORIA: VARIABLES
Dado que ya sabemos qué tipos usaremos, estamos preparados para comenzar a relacionar datos que ocupan espacio en memoria con variables que puede usarse dentro de expresiones en su pseudocódigo.
En un algoritmo y, en particular, en un pseudocódigo, poder recordar un valor previo que se encuentre en memoria, forma parte del estado de nuestro algoritmo.
Esto es, a medida que guardamos valores en memoria durante los pasos del flujo algorítmico, cambia el estado de la solución, y esos cambios son los que permiten resolver el problema. Del estado final del algoritmo obtenemos nuestra solución.
Estos datos pueden ser atómicos, esto es, referencian un único valor de algún tipo, o pueden ser compuestos y ordenados en una estructura con varios valores atómicos.
En un algoritmo y, en particular, en un pseudocódigo, poder recordar un valor previo que se encuentre en memoria, forma parte del estado de nuestro algoritmo.
Esto es, a medida que guardamos valores en memoria durante los pasos del flujo algorítmico, cambia el estado de la solución, y esos cambios son los que permiten resolver el problema. Del estado final del algoritmo obtenemos nuestra solución.
Estos datos pueden ser atómicos, esto es, referencian un único valor de algún tipo, o pueden ser compuestos y ordenados en una estructura con varios valores atómicos.
Datos atómicos irreducibles
Diremos que un dato es atómico, si es irreducible. Esto es, como dato no puede ser simplificado: se trata de una expresión en su mínimo estado de representación, y no es, per se, una expresión simbólica que permita derivar un nuevo valor a partir de ella.
Todo valor en memoria está en su estado mínimo de representación. Por ejemplo, supongamos que la variable w::R se asocia al valor 9.8. El valor 9.8 no es simplificable en si mismo, ya que no es una expresión que al ser valorada, derive en un valor diferente. Por lo tanto, es atómico e irreducible.
Todo valor en memoria está en su estado mínimo de representación. Por ejemplo, supongamos que la variable w::R se asocia al valor 9.8. El valor 9.8 no es simplificable en si mismo, ya que no es una expresión que al ser valorada, derive en un valor diferente. Por lo tanto, es atómico e irreducible.
Datos atómicos numéricos
Tomemos como ejemplo el valor numérico real 100, el cual podríamos referenciar con una variable para ponerlo a disposición de operaciones posteriores dentro de uno de nuestros algoritmos.
Crearemos una variable que llamaremos x, e indicaremos de forma general que se trata de un número, y que no nos importa mucho el tipo de dato concreto; esto lo haremos por medio del tipo abstracto ::Num o ::Number.
A esta acción se le conoce como declaración de la variable.
Durante una declaración, se puede especificar un valor de iniciaización de la variable declarada, y el valor 100 lo asociaremos usando el símbolo ‘<-’ (flecha hacia la izquierda), que es el operador de asociación.
Tratándose de pseudocódigo, las siguientes posibles formas son válidas para escribir que se declara una variable con un valor inicial
x::Number <- 100
store 100 in x::Number
declare w type Number <- 100
declare w of type Number initialized with 100
Por supuesto, tenemos que buscar frases que sean fáciles de entender durante la lectura de los pseudicódigos, y se deja a criterio de quien escribe el pseudocódigo, siempre teniendo en cuenta el lector objetivo del pseudocódigo.
Este libro prefiere las más próximas a los lenguajes de programación, como es el caso de la primera que se plantea.
Especificar el tipo ::Number es opcional en nuestros pseudocódigos. Esto se debe a que el tipo se toma de la expresión, por lo que también es válida la expresión sin la especificación del tipo:
x <- 100 ó store 100 in x
En la expresión dada, la variable x es de tipo abstracto ::Number, así como también de tipo concreto ::R.
La idea de si se usa el tipo ::Number abstracto de forma explícita, o si se usa el tipo ::R de forma explícita, dependerá de si necesita o no poder cambiar el tipo concreto de la variable.
Se debe recordar de lo visto de tipos, que el tipo de dato ::Number es abstracto, esto es, está habilitado para almacenar cualquiera de los tipos ::N, ::Z, :Q, ::R, ::C, ::I, o subconjunto de alguno de ellos.
En el ejemplo de asociar el valor 3.5 a la variable x, note que la flecha (<-) va de derecha a izquierda, y, en general, la gran mayoría de los lenguajes de programación se asumen este tipo de dirección en sus operaciones de asociación, y por lo tanto, a esta flecha la denominamos operador de asociación (Como veremos más adelante, en nuestros pseudocódigos la flecha puede invertirse para expresar la operación de tal modo que a la izquierda vaya el valor y a la derecha la variable, algo que se verá más adelante).
Cuando se usa el operador de asignación (<-), el valor de la derecha se “deja” disponible para ser usado a su izquierda: si a la izquierda hay una variable, indicamos que el valor se asocia a la variable, y el valor queda disponible para ser reusado.
De hecho, luego de que a una variable se le ha asociado un valor, ese mismo valor se deja disponible para ser usado a su izquierda, y así sucesivamente, por lo que, en nuestro pseudocódigo, así como en muchos lenguajes de programación, las cadenas de asociación son posibles.
Por ejemplo
n <- k <- x <- 3.5
lo primero es asociar el valor 3.5 a la variable x, y luego que la variable x tome el valor, se “presenta” el valor asociado a x para que alguna otra operación lo use.
El valor de x presentado se usa para asignarlo a k, y así es como finalmente n toma el valor presentado por k. Finalmente n presenta el valor para ser usado por “algo” más, y si ese “algo” no existe, el valor es descartado.
Todo lo anterior para decir que para referirnos al valor 3.5, podremos hacerlo con alguna de las variables n, k, o x. Esto es, puede imaginar que tiene 3 datos numéricos en memoria, o puede imaginar que tiene un solo dato y tres variables que hacen referencia a él.
La forma en que o hacen los lenguajes de programación varía de lenguaje a lenguaje, y esos detalles sólo son importantes para programar.
En nuestros pseudocodigos hacerse esa pregunta carece de sentido, y sólo sirve imaginar que las tres variables están asociadas al valor 3.5.
Crearemos una variable que llamaremos x, e indicaremos de forma general que se trata de un número, y que no nos importa mucho el tipo de dato concreto; esto lo haremos por medio del tipo abstracto ::Num o ::Number.
A esta acción se le conoce como declaración de la variable.
Durante una declaración, se puede especificar un valor de iniciaización de la variable declarada, y el valor 100 lo asociaremos usando el símbolo ‘<-’ (flecha hacia la izquierda), que es el operador de asociación.
Tratándose de pseudocódigo, las siguientes posibles formas son válidas para escribir que se declara una variable con un valor inicial
x::Number <- 100
store 100 in x::Number
declare w type Number <- 100
declare w of type Number initialized with 100
Por supuesto, tenemos que buscar frases que sean fáciles de entender durante la lectura de los pseudicódigos, y se deja a criterio de quien escribe el pseudocódigo, siempre teniendo en cuenta el lector objetivo del pseudocódigo.
Este libro prefiere las más próximas a los lenguajes de programación, como es el caso de la primera que se plantea.
Especificar el tipo ::Number es opcional en nuestros pseudocódigos. Esto se debe a que el tipo se toma de la expresión, por lo que también es válida la expresión sin la especificación del tipo:
x <- 100 ó store 100 in x
En la expresión dada, la variable x es de tipo abstracto ::Number, así como también de tipo concreto ::R.
La idea de si se usa el tipo ::Number abstracto de forma explícita, o si se usa el tipo ::R de forma explícita, dependerá de si necesita o no poder cambiar el tipo concreto de la variable.
Se debe recordar de lo visto de tipos, que el tipo de dato ::Number es abstracto, esto es, está habilitado para almacenar cualquiera de los tipos ::N, ::Z, :Q, ::R, ::C, ::I, o subconjunto de alguno de ellos.
En el ejemplo de asociar el valor 3.5 a la variable x, note que la flecha (<-) va de derecha a izquierda, y, en general, la gran mayoría de los lenguajes de programación se asumen este tipo de dirección en sus operaciones de asociación, y por lo tanto, a esta flecha la denominamos operador de asociación (Como veremos más adelante, en nuestros pseudocódigos la flecha puede invertirse para expresar la operación de tal modo que a la izquierda vaya el valor y a la derecha la variable, algo que se verá más adelante).
Cuando se usa el operador de asignación (<-), el valor de la derecha se “deja” disponible para ser usado a su izquierda: si a la izquierda hay una variable, indicamos que el valor se asocia a la variable, y el valor queda disponible para ser reusado.
De hecho, luego de que a una variable se le ha asociado un valor, ese mismo valor se deja disponible para ser usado a su izquierda, y así sucesivamente, por lo que, en nuestro pseudocódigo, así como en muchos lenguajes de programación, las cadenas de asociación son posibles.
Por ejemplo
n <- k <- x <- 3.5
lo primero es asociar el valor 3.5 a la variable x, y luego que la variable x tome el valor, se “presenta” el valor asociado a x para que alguna otra operación lo use.
El valor de x presentado se usa para asignarlo a k, y así es como finalmente n toma el valor presentado por k. Finalmente n presenta el valor para ser usado por “algo” más, y si ese “algo” no existe, el valor es descartado.
Todo lo anterior para decir que para referirnos al valor 3.5, podremos hacerlo con alguna de las variables n, k, o x. Esto es, puede imaginar que tiene 3 datos numéricos en memoria, o puede imaginar que tiene un solo dato y tres variables que hacen referencia a él.
La forma en que o hacen los lenguajes de programación varía de lenguaje a lenguaje, y esos detalles sólo son importantes para programar.
En nuestros pseudocodigos hacerse esa pregunta carece de sentido, y sólo sirve imaginar que las tres variables están asociadas al valor 3.5.
Uso de factores numéricos
Supongamos que asignamos valores a las variables n, k y x como se mostró en el ejemplo anterior.
n <- k <- x <- 3.5
También supongamos que creamos un nuevo valor en memoria denominado w, así:
w::Number <- 8.7
De ahora en adelante, podremos usar las variables x, k, n y w en cualquier otra expresión.
Suponga ahora que queremos elaborar una expresión aritmética, y el resultado almacenarlo en otro espacio que llamaremos r.
r <- 2x + 4w – x3 #tipo implícito, inferido como ::N
Note que el tipo de la variable r es inferido desde la expresión, ya que el resultado de la expresión es un valor numérico, y por eso no lo especificamos el tipo como hicimos con x y con w.
Sin embargo, también es correcto escribir:
r::N <- 2x + 4w – x3 #tipo explícito. No inferido.
La expresión anterior evaluada queda
r <- 2(3.5) + 4(8.7) – (3.5)3
y reduciendo, tenemos
r <- 7 + 34.8 – 42.88
r <- 84.68
lo que significa que r está asociada al valor 84.68.
Pero sigamos experimentando:
¿qué pasa si luego de esta expresión sigue esta otra expresión?
r <- 2r – 0.5x
En este caso, la variable que vamos a asignar es r, pero r también se usa en la expresión de la derecha.
No hay problema. La expresión se convierte en
r <- 2(84.68) – 0.5(3.5)
que se convierte finalmente en
r <- 167.61
El tema de expresiones aritméticas, como la presentada al crear a r, vendrá más adelante.
Por el momento, la intención es comprender cómo se asocian tipos de datos a variables y cómo se asocian valores a variables.
n <- k <- x <- 3.5
También supongamos que creamos un nuevo valor en memoria denominado w, así:
w::Number <- 8.7
De ahora en adelante, podremos usar las variables x, k, n y w en cualquier otra expresión.
Suponga ahora que queremos elaborar una expresión aritmética, y el resultado almacenarlo en otro espacio que llamaremos r.
r <- 2x + 4w – x3 #tipo implícito, inferido como ::N
Note que el tipo de la variable r es inferido desde la expresión, ya que el resultado de la expresión es un valor numérico, y por eso no lo especificamos el tipo como hicimos con x y con w.
Sin embargo, también es correcto escribir:
r::N <- 2x + 4w – x3 #tipo explícito. No inferido.
La expresión anterior evaluada queda
r <- 2(3.5) + 4(8.7) – (3.5)3
y reduciendo, tenemos
r <- 7 + 34.8 – 42.88
r <- 84.68
lo que significa que r está asociada al valor 84.68.
Pero sigamos experimentando:
¿qué pasa si luego de esta expresión sigue esta otra expresión?
r <- 2r – 0.5x
En este caso, la variable que vamos a asignar es r, pero r también se usa en la expresión de la derecha.
No hay problema. La expresión se convierte en
r <- 2(84.68) – 0.5(3.5)
que se convierte finalmente en
r <- 167.61
El tema de expresiones aritméticas, como la presentada al crear a r, vendrá más adelante.
Por el momento, la intención es comprender cómo se asocian tipos de datos a variables y cómo se asocian valores a variables.
Datos atómicos caracter y string
Ahora supongamos que deseamos almacenar en una variable llamada c un caracter, por ejemplo la letra , ‘A’ (note que como es un caracter, lo delimitamos con comillas simples ‘’).
Siguiendo nuestra estrategia, podríamos asociar el valor ‘A’ a la variable c de dos formas: la implícita y la explicita:
c::Char <- ‘A’ //forma explícita
c <- ‘A’ //forma implícita
Por ser c de tipo caracter, solo podrá estar asociado a una única letra o runa.
Por el contrario, si definimos otra variable llamada s de tipo string, podremos almacenar un conjunto consecutivo de caracteres:
s::String <- “01234ABCFXY GGGC”
s ahora tiene 16 caracteres, cada uno reconocido individualmente. Por ejemplo, podremos referirnos al caracter ‘Y’ de la posición 11, como s[ 11 ], o al fragmento de la cadena “ABCF” como s[ 6 : 9 ], pero estos detalles los estaremos revisando más adelante.
Al igual que en los casos anteriores, el tipo de la expresión es suficiente para evitar tener que indicar el tipo, por lo que es válida la siguiente expresión:
d <- “01234ABCFXY GGGC”
Siguiendo nuestra estrategia, podríamos asociar el valor ‘A’ a la variable c de dos formas: la implícita y la explicita:
c::Char <- ‘A’ //forma explícita
c <- ‘A’ //forma implícita
Por ser c de tipo caracter, solo podrá estar asociado a una única letra o runa.
Por el contrario, si definimos otra variable llamada s de tipo string, podremos almacenar un conjunto consecutivo de caracteres:
s::String <- “01234ABCFXY GGGC”
s ahora tiene 16 caracteres, cada uno reconocido individualmente. Por ejemplo, podremos referirnos al caracter ‘Y’ de la posición 11, como s[ 11 ], o al fragmento de la cadena “ABCF” como s[ 6 : 9 ], pero estos detalles los estaremos revisando más adelante.
Al igual que en los casos anteriores, el tipo de la expresión es suficiente para evitar tener que indicar el tipo, por lo que es válida la siguiente expresión:
d <- “01234ABCFXY GGGC”
Datos atómicos lógicos (booleanos)
Supongamos que queremos indicar que algo es falso, o verdadero. Esto, en programación, es altamente común, y es base para la toma de decisiones, y las bifurcaciones algorítmicas.
En nuestros pseudocódigos, los posibles valores serán .f. o .t., pero tendremos las formas alternativas .false. o .true., y siempre encerrados entre puntos para indicar que se trata de un valor, y no de una variable con ese nombre (en pseudocódigo, más variantes son posibles, como .verdadero., .falso. en español, o .treu. , .falsch. en alemán, o .правда. , .ложь. en ruso.
En este libro usaremos sólo las dos primeras alternativas .f. y .t.
Este tipo es fundamental en las expresiones lógicas, lo que entonces lo convierte en un concepto algorítmico y de programación muy importante para representar datos, y para controlar el flujo de la lógica de programación (estructuras de control que veremos más adelante), como los ciclos y las bifurcaciones condicionales.
Para entenderlo mejor, esperaremos hasta analizar las expresiones lógicas.
Por el momento será suficiente con entender que un valor booleano se puede almacenar en una variable como se hace con cualquier otro tipo:
prendido::Bool <- .t. // tipificación explícita
prendido <- .t. // tipificación implícita
En nuestros pseudocódigos, los posibles valores serán .f. o .t., pero tendremos las formas alternativas .false. o .true., y siempre encerrados entre puntos para indicar que se trata de un valor, y no de una variable con ese nombre (en pseudocódigo, más variantes son posibles, como .verdadero., .falso. en español, o .treu. , .falsch. en alemán, o .правда. , .ложь. en ruso.
En este libro usaremos sólo las dos primeras alternativas .f. y .t.
Este tipo es fundamental en las expresiones lógicas, lo que entonces lo convierte en un concepto algorítmico y de programación muy importante para representar datos, y para controlar el flujo de la lógica de programación (estructuras de control que veremos más adelante), como los ciclos y las bifurcaciones condicionales.
Para entenderlo mejor, esperaremos hasta analizar las expresiones lógicas.
Por el momento será suficiente con entender que un valor booleano se puede almacenar en una variable como se hace con cualquier otro tipo:
prendido::Bool <- .t. // tipificación explícita
prendido <- .t. // tipificación implícita
Mutabilidad de datos atómicos
A las letras a los que asociamos valores anteriormente se les conoce con el nombre de variables, dado que pueden mutar su valor siempre que se respete su tipo.
Son variables x, w, r, q, c, d, s. La mutabilidad hace alusión a que el valor de una variable puede cambiar en el tiempo a través el uso de expresiones.
En el caso que queramos asociar un símbolo a un valor y que no pueda ser mutado, hablaremos de constantes o inmutables. Para indicar que una asociación es inmutable o constante, usamos algunas de las palabras const, constant, inmut, o inmutable.
Por ejemplo, si queremos que una variable nos maneje el valor de pi, pero que la variable no pueda ser alterada, la definimos como
constant pi::R+ <- 3.1415926535897932384
Al igual que en los casos anteriores, el contexto es suficiente para evitar tener que poner un tipo para la variable, por lo que también es posible definir a pi como
inmutable pi <- 3.1415926535897932384
En nuestros pseudocódigos, si no se especifica que una variable es inmutable, por defecto es mutable, y el uso de un especificador como var, variable, o mutable, es opcional, y su uso va a depender de si se requiere dar alguna claridad al código.
declare mutable w of type R+ <- 100
o usando una forma mucho más verbosa
declare mutable w of type R+ initialized with 100
Como se puede ver, el uso de lenguaje natural se convierte en una posibilidad cuando de pseudocódigos se trata, aunque mi preferencia es preferir estructuras cortas.
Son variables x, w, r, q, c, d, s. La mutabilidad hace alusión a que el valor de una variable puede cambiar en el tiempo a través el uso de expresiones.
En el caso que queramos asociar un símbolo a un valor y que no pueda ser mutado, hablaremos de constantes o inmutables. Para indicar que una asociación es inmutable o constante, usamos algunas de las palabras const, constant, inmut, o inmutable.
Por ejemplo, si queremos que una variable nos maneje el valor de pi, pero que la variable no pueda ser alterada, la definimos como
constant pi::R+ <- 3.1415926535897932384
Al igual que en los casos anteriores, el contexto es suficiente para evitar tener que poner un tipo para la variable, por lo que también es posible definir a pi como
inmutable pi <- 3.1415926535897932384
En nuestros pseudocódigos, si no se especifica que una variable es inmutable, por defecto es mutable, y el uso de un especificador como var, variable, o mutable, es opcional, y su uso va a depender de si se requiere dar alguna claridad al código.
declare mutable w of type R+ <- 100
o usando una forma mucho más verbosa
declare mutable w of type R+ initialized with 100
Como se puede ver, el uso de lenguaje natural se convierte en una posibilidad cuando de pseudocódigos se trata, aunque mi preferencia es preferir estructuras cortas.
Nombre de variables
Los nombres de las variables pueden ser de cualquier tamaño. Sin embargo, los lenguajes de programación obligan algunas normas. En pseudocódigos papercode nos acogeremos algunas normas básicas.
Para evitar confusiones con expresiones, el nombre de una variable no debe comenzar con un número. Por ejemplo, el nombre 3x es confuso, pues parece más que estamos multiplicando una variable llamada x por 3. Sin embargo, el nombre x3 es menos confuso.
Usar nombres claros, que indiquen el verdadero contenido, y si es posible, propósito de la variable. Por ejemplo, el nombre de variable x3 no dice nada, pero el nombre de variable xml dice ya mucho sobre su contenido.
No use caracteres que puedan ser confusos, como operadores aritméticos, u otros operadores. Por ejemplo, el nombre de variable cantidad-bacterias es confuso, pues parece una resta, e incluso los lenguajes de programación no lo aceptan, y en este caso tiene que retirar el signo de resta y usar otro como el ‘underscore’ ; use cantidad_bacterias. A este tipo de escritura se le conoce en programación como Snake Case.
También, por legibilidad, se pueden usar nombres de variables en formato Camel Case (comenzar con minúscula, y toda palabra posterior comenzarla en mayúscula, como por ejemplo cantidadBacterias), o Pascal Case (comenzar con mayúscula, y toda palabra posterior comenzarla también en mayúscula - CantidadBacterias).
En muchos lenguajes de programación, se hacen recomendaciones para usar distintos casos dependiendo del tipo de variables según el alcance, o según si nivel de complejidad.
Por ejemplo, se puede usar Snake Case para variables, Pascal Case para estructuras y objetos, y Camel Case para funciones. Sin embargo, esto son sólo convenciones que va adquiriendo una comunidad frente a un lenguaje.
Los nombres de las variables se pueden expresar usando letras de cualquier alfabeto, y algunos lenguajes de programación son bastante flexibles. En pseudocódigo, puede usar cualquier tipo de escritura, siempre y cuando no se genere confusión, y sea fácil de leer y entender el propósito de los nombres.
Para evitar confusiones con expresiones, el nombre de una variable no debe comenzar con un número. Por ejemplo, el nombre 3x es confuso, pues parece más que estamos multiplicando una variable llamada x por 3. Sin embargo, el nombre x3 es menos confuso.
Usar nombres claros, que indiquen el verdadero contenido, y si es posible, propósito de la variable. Por ejemplo, el nombre de variable x3 no dice nada, pero el nombre de variable xml dice ya mucho sobre su contenido.
No use caracteres que puedan ser confusos, como operadores aritméticos, u otros operadores. Por ejemplo, el nombre de variable cantidad-bacterias es confuso, pues parece una resta, e incluso los lenguajes de programación no lo aceptan, y en este caso tiene que retirar el signo de resta y usar otro como el ‘underscore’ ; use cantidad_bacterias. A este tipo de escritura se le conoce en programación como Snake Case.
También, por legibilidad, se pueden usar nombres de variables en formato Camel Case (comenzar con minúscula, y toda palabra posterior comenzarla en mayúscula, como por ejemplo cantidadBacterias), o Pascal Case (comenzar con mayúscula, y toda palabra posterior comenzarla también en mayúscula - CantidadBacterias).
En muchos lenguajes de programación, se hacen recomendaciones para usar distintos casos dependiendo del tipo de variables según el alcance, o según si nivel de complejidad.
Por ejemplo, se puede usar Snake Case para variables, Pascal Case para estructuras y objetos, y Camel Case para funciones. Sin embargo, esto son sólo convenciones que va adquiriendo una comunidad frente a un lenguaje.
Los nombres de las variables se pueden expresar usando letras de cualquier alfabeto, y algunos lenguajes de programación son bastante flexibles. En pseudocódigo, puede usar cualquier tipo de escritura, siempre y cuando no se genere confusión, y sea fácil de leer y entender el propósito de los nombres.
NOTACIÓN DE CONJUNTOS
La especificación de un tipo puede ser más específica en nuestros pseudocódigos papercode con el ánimo de aclarar con qué datos se desea trabajar. Cuando se desee que nuestro tipo sea uno muy específico, incluso uno que combine varios tipos, usaremos notación de conjuntos.
Por ejemplo, para especificar que queremos que un tipo de dato es el subconjunto de los números naturales del 1 al 9 solamente, y, además de esos dígitos se requieren los valores .t. y .f. (los valores lógicos o booleanos), podremos especificar
::{1,2,3,4,5,6,7,8,9} U ::{ .t. , .f. }
O lo que es lo mismo, podríamos escribir
::{1,2,3,4,5,6,7,8,9} U ::Bool
Un tipo de este modo especificado permitiría tener un control interesante sobre los posibles valore que puede tomar una variable. Esto es bastante raro en los lenguajes de programación, ya que puede generar confusión, o puede ir en contravía de algunas normas de diseño de código. De hecho, también llega ser raro en pseudocódigo. Sin embargo, representa la posibilidad de hacer una expresión de tipo de datos concretos combinados.
Por ejemplo, para especificar que queremos que un tipo de dato es el subconjunto de los números naturales del 1 al 9 solamente, y, además de esos dígitos se requieren los valores .t. y .f. (los valores lógicos o booleanos), podremos especificar
::{1,2,3,4,5,6,7,8,9} U ::{ .t. , .f. }
O lo que es lo mismo, podríamos escribir
::{1,2,3,4,5,6,7,8,9} U ::Bool
Un tipo de este modo especificado permitiría tener un control interesante sobre los posibles valore que puede tomar una variable. Esto es bastante raro en los lenguajes de programación, ya que puede generar confusión, o puede ir en contravía de algunas normas de diseño de código. De hecho, también llega ser raro en pseudocódigo. Sin embargo, representa la posibilidad de hacer una expresión de tipo de datos concretos combinados.
Cuantificadores
Tome el conjunto de los números enteros positivos menores o iguales a 9, que se puede escribir como se mencionó en la notación de conjuntos:
::{1,2,3,4,5,6,7,8,9}
Un cuantificador nos permitiría definir el conjunto como
::{ Z+ < 10}
Lo que simplificaría mucho nuestras definiciones y las haría mucho más claras.
El subtipo especificado previamente, delimita los posibles valores para una variable; por ejemplo, para especificar que una variable w es de tipo {1,2,3,4,5,6,7,8,9}, podremos escribir
w::{ Z+ < 10} o w::{ x | x ∈ Z+ , x < 10} o también w::{1,2,3,4,5,6,7,8,9}
También se puede delimitar un subconjunto específico si se usan expresiones como parte del conjunto tipo. Por ejemplo, el conjunto de los enteros impares se puede escribir
::{x | x ∈ Z , 2x+1} Que equivale a {… -9, -7, -5, -3, -1, 1, 3, 5 , 7, …}
y que se lee ‘x tal que x es entero impar positivo o negativo’.
Otra forma de especificar un subtipo es con operaciones sobre conjuntos, por lo que podríamos usar los operadores intersección (Ç), unión (È) y diferencia (-) como los hemos usado en matemáticas.
Por ejemplo, la especificación
::{x | x ∈ Z , 4x-3} U {x | x ∈ Z , 5x^2 + 1}
equivale a
{…, -19, -15, -11, -7, 0, 1, 5, 9, 13, …} U {…, 1, 6, 21, 46, …}
Lo que finalmente corresponde al conjunto de datos
{… ,-19, -15, -11, -7, 0, 1, 5, 6 ,9 ,13 , 21, 46, …}
También podremos diseñar nuestros propios conjuntos de datos como se analizó con el tipo de datos entero ::Z. Por ejemplo, el conjunto de los reales que forman una parábola se describe como
::{x ∈ R , x^2}
que se lee el ‘para todo x en el conjunto de los reales, se tiene el conjunto de los reales x2’.
Expresiones más complejas son posibles en pseudocódigo papercode para describir y especificar los dominios de datos.
También los tipos son una forma de garantizar que no se asignan valores incorrectos a las variables, lo que es útil durante llamados a funciones, o durante el asignamiento de valores a variables, al usar un cuantificador como tipo de la variable.
::{1,2,3,4,5,6,7,8,9}
Un cuantificador nos permitiría definir el conjunto como
::{ Z+ < 10}
Lo que simplificaría mucho nuestras definiciones y las haría mucho más claras.
El subtipo especificado previamente, delimita los posibles valores para una variable; por ejemplo, para especificar que una variable w es de tipo {1,2,3,4,5,6,7,8,9}, podremos escribir
w::{ Z+ < 10} o w::{ x | x ∈ Z+ , x < 10} o también w::{1,2,3,4,5,6,7,8,9}
También se puede delimitar un subconjunto específico si se usan expresiones como parte del conjunto tipo. Por ejemplo, el conjunto de los enteros impares se puede escribir
::{x | x ∈ Z , 2x+1} Que equivale a {… -9, -7, -5, -3, -1, 1, 3, 5 , 7, …}
y que se lee ‘x tal que x es entero impar positivo o negativo’.
Otra forma de especificar un subtipo es con operaciones sobre conjuntos, por lo que podríamos usar los operadores intersección (Ç), unión (È) y diferencia (-) como los hemos usado en matemáticas.
Por ejemplo, la especificación
::{x | x ∈ Z , 4x-3} U {x | x ∈ Z , 5x^2 + 1}
equivale a
{…, -19, -15, -11, -7, 0, 1, 5, 9, 13, …} U {…, 1, 6, 21, 46, …}
Lo que finalmente corresponde al conjunto de datos
{… ,-19, -15, -11, -7, 0, 1, 5, 6 ,9 ,13 , 21, 46, …}
También podremos diseñar nuestros propios conjuntos de datos como se analizó con el tipo de datos entero ::Z. Por ejemplo, el conjunto de los reales que forman una parábola se describe como
::{x ∈ R , x^2}
que se lee el ‘para todo x en el conjunto de los reales, se tiene el conjunto de los reales x2’.
Expresiones más complejas son posibles en pseudocódigo papercode para describir y especificar los dominios de datos.
También los tipos son una forma de garantizar que no se asignan valores incorrectos a las variables, lo que es útil durante llamados a funciones, o durante el asignamiento de valores a variables, al usar un cuantificador como tipo de la variable.
Cardinalidad y conjuntos contables e incontables
Un conjunto es contable finito si los posibles valores para la variable pueden ser contados. Por ejemplo, la variable
s::{ Z+ < 10}
es de tipo contable infinito, pues se expande como
::{1,2,3,4,5,6,7,8,9}
y en este caso decimos que la cardinalidad de s es 9.
La cardinalidad de la variable s se expresa como | s |. En el ejemplo | s | = 9, y corresponde al número de los elementos que podrían ser asociados a la variable.
Un conjunto es contable infinito si sus miembros pueden ponerse en una correspondencia uno a uno con los números naturales.
w::{x | x ∈ Z , 4x-3} U {x | x ∈ Z, 5x2+1}
es una variable con tipo contable infinito, pues el rango de valores que puede tomar la variable w es
{…,-19,-15,-11,-7,0,1,5,6,9,13,21,46,…}
La cardinalidad de una variable con tipo contable infinito se expresa como אo se lee Alef-cero, Alef-nul, o Alef-nada.
En nuestros pseudocodigos en papercode, el término אo, puede ser usado para validar si una variable tiene un rango de valores correspondiente a contable finito o infinito.
En el ejemplo | w | = אo.
Pero hay conjuntos de valores que son incontables, como el conjunto de los números reales ::R, o subconjuntos que derivan de él, pues entre dos números reales cualquiera hay otro conjunto infinito, y no puede haber una correspondencia 1 a 1 con el conjunto de los números naturales.
Por ejemplo,
el conjunto ::{x ∈ R , x^2} es incontable, ya que no es posible enumerar sus elementos, pues entre dos números reales cualquiera, hay un infinito número de números reales.
Por lo tanto, se define | x | = 𝔠 , la letra c en fuente gótica Fraktur[1], que se lee cardinalidad del continuo.
En nuestros pseudocódigos, cuando queramos referirnos a dicha cardinalidad, podremos usar simplemente | ::R | para facilitar la escritura de la letra C estilo gótico 𝔠.
[1] Fraktur. (2021). Retrieved 24 Julio 2021, from https://en.wikipedia.org/wiki/Fraktur#Fraktur_in_Unicode
s::{ Z+ < 10}
es de tipo contable infinito, pues se expande como
::{1,2,3,4,5,6,7,8,9}
y en este caso decimos que la cardinalidad de s es 9.
La cardinalidad de la variable s se expresa como | s |. En el ejemplo | s | = 9, y corresponde al número de los elementos que podrían ser asociados a la variable.
Un conjunto es contable infinito si sus miembros pueden ponerse en una correspondencia uno a uno con los números naturales.
w::{x | x ∈ Z , 4x-3} U {x | x ∈ Z, 5x2+1}
es una variable con tipo contable infinito, pues el rango de valores que puede tomar la variable w es
{…,-19,-15,-11,-7,0,1,5,6,9,13,21,46,…}
La cardinalidad de una variable con tipo contable infinito se expresa como אo se lee Alef-cero, Alef-nul, o Alef-nada.
En nuestros pseudocodigos en papercode, el término אo, puede ser usado para validar si una variable tiene un rango de valores correspondiente a contable finito o infinito.
En el ejemplo | w | = אo.
Pero hay conjuntos de valores que son incontables, como el conjunto de los números reales ::R, o subconjuntos que derivan de él, pues entre dos números reales cualquiera hay otro conjunto infinito, y no puede haber una correspondencia 1 a 1 con el conjunto de los números naturales.
Por ejemplo,
el conjunto ::{x ∈ R , x^2} es incontable, ya que no es posible enumerar sus elementos, pues entre dos números reales cualquiera, hay un infinito número de números reales.
Por lo tanto, se define | x | = 𝔠 , la letra c en fuente gótica Fraktur[1], que se lee cardinalidad del continuo.
En nuestros pseudocódigos, cuando queramos referirnos a dicha cardinalidad, podremos usar simplemente | ::R | para facilitar la escritura de la letra C estilo gótico 𝔠.
[1] Fraktur. (2021). Retrieved 24 Julio 2021, from https://en.wikipedia.org/wiki/Fraktur#Fraktur_in_Unicode
CONVERSIONES
En pseudocódigos, podremos usar tipos para indicar que se lleve a cabo algunas conversiones útiles. Por ejemplo, convertir un valor que es real ::R sea a entero ::Z, o un ::String, convertido a entero ::Z. Esta magia nos daría un gran poder de expresividad.
En los lenguajes de programación, este tipo de conversiones puede ser mucho más tediosa. Sin embargo, en nuestros seudocódigos, cualquier tipo podrá ser usado contra cualquier otro sin problemas.
En los lenguajes de programación, este tipo de conversiones puede ser mucho más tediosa. Sin embargo, en nuestros seudocódigos, cualquier tipo podrá ser usado contra cualquier otro sin problemas.
EJEMPLO.
Se tiene el número real 2.1 y se requiere obtener el número entero 2. R/ Se puede hacer una conversión explicita. En este caso, se usa el tipo entero usando la forma funcional ::Z( ), y de ese modo obtengo el número entero 2. número::R <- 3.5 parteentera <- ::Z(número) la variable parteentera almacena 3 |
EJEMPLO.
Hallar la parte fraccionaria del número 3.5. R/ Ya sabemos que se puede determinar la parte entera. Hallar la parte fraccionaria es tan simple como: número::R <- 3.5 partefrac <- número -::Z(número) la variable partefrac almacena 0.5 |
EJEMPLO.
Se desea conocer el código del caracter o letra ‘A’. R/ EXPLICACIÓN. Recordemos que cualquier caracter lleva asociado un código UNICODE. En este caso, también una conversión es útil, ya que puedo convertir un único caracter a su valor entero correspondiente. Eso es posible en cualquier lenguaje. Es importante anotar que este tipo de conversiones es posible solo si se intenta con un caracter. Aplicarlo a una cadena no tendría sentido, ya que una cadena tiene múltiples caracteres: letra ::Char <- ‘A’ código <- ::N(letra) la variable código contiene el valor entero 65. |
EJEMPLO.
Se desea conocer el caracter cuyo código es 66. R/ En este caso, pretender ir del código al caracter. Podemos hacer el casting a través del tipo caracter. Así de simple. letra <- ::Char(66) la variable letra contendrá el valor ‘B’ |
EJEMPLO.
Se desea determinar el residuo de dividir 31 entre 3. R/ alternativa #1 Esta división da 10 como parte entera, y 1 como residuo. Pero en computación es tradicional que esta división de 10.3333333…, por lo que para hallar adecuadamente lo que se pide, se logra así: num::R <- 31 / 3 fracc::R <- num - ::Z(num) #número menos la parte entera residuo::Z <- fracción * 3 #caracter * es multiplicación Note que la clave de la solución está en determinar la parte fraccionaria de forma única, y luego multiplicar esa parte fraccionaria por el número que usamos como divisor. alternativa #2 Una forma más general, sería tener los valores numerador y denominador almacenados en variables. La solución sería: x <- 31 y <- 3 n <- x / y # el símbolo / es de división frac <- n -::Z(n) res <- frac * y alternativa #3 La expresión x/y no es necesario tenerla separada en la variable n, por lo que podemos escribir fracción:R <- x/y - ::Z(x / y) res::Z <- fracción * y y la variable fracción podríamos evitarla también, escribiendo res::Z <- ( x / y -::Z(x / y) ) * y |
En el ejemplo anterior, cuál de las tres formas alternativas usar, es meramente una cuestión de gusto, y muchos programadores prefieren la mas larga, con tal de que el código quede más claro para leer, ya que algunos programadores encuentran algo confuso tener toda la expresión en una sola línea.
Ahora suponga que define una nueva variable llamada π, así:
π ::R <- 3.1415926535897932384
Note que el tipo de la variable π (pi) lo declaramos explícitamente.
Se desea llevar dicho número π a una string (cada lenguaje tendrá su propio mecanismo).
Para nuestro pseudocódigo algorítmico usaremos (como tal vez ya sospechaba) el tipo ::String, así:
spi <- ::String( π )
En este caso, no se indicó qué tipo es spi, pero dado que se aplicó el tipo ::String a la variable π, la variable spi implícitamente toma el tipo ::String, y la variable spi contendrá ahora una secuencia de caracteres, donde cada caracter es un dígito de π, incluido el punto, así: “3.1415926535897932384”.
Como número, la cadena spi no tiene sentido para el computador par ser usada en un cálculo numérico, y se trata de una representación para humanos. La cadena spi ahora cuenta también con una longitud que corresponde al número de caracteres presentes. Recuerde que esta cadena no es un número útil para operaciones, como sí lo es el número real π (pi).
π ::R <- 3.1415926535897932384
Note que el tipo de la variable π (pi) lo declaramos explícitamente.
Se desea llevar dicho número π a una string (cada lenguaje tendrá su propio mecanismo).
Para nuestro pseudocódigo algorítmico usaremos (como tal vez ya sospechaba) el tipo ::String, así:
spi <- ::String( π )
En este caso, no se indicó qué tipo es spi, pero dado que se aplicó el tipo ::String a la variable π, la variable spi implícitamente toma el tipo ::String, y la variable spi contendrá ahora una secuencia de caracteres, donde cada caracter es un dígito de π, incluido el punto, así: “3.1415926535897932384”.
Como número, la cadena spi no tiene sentido para el computador par ser usada en un cálculo numérico, y se trata de una representación para humanos. La cadena spi ahora cuenta también con una longitud que corresponde al número de caracteres presentes. Recuerde que esta cadena no es un número útil para operaciones, como sí lo es el número real π (pi).
EJEMPLO.
Se desea llevar la cadena “2.8182” a número. R/ En nuestros algoritmos, podremos usar cualquier tipo de datos que nos lleve a un número, incluyendo la posibilidad de truncar la parte fraccionaria: strnum <- “2.8182” #String forma implícit real <- ::R(strnum) #Contenido real será 2.8182 num <- ::Number(strnum) #Contenido de num será 2.8182 note que, si se usa el tipo entero, se trunca el valor: ente <- ::Z(strnume) # el contenido de ente será 2 |
Nota: Es importante entender que estas técnicas como se presentan no aplican a lenguajes de programación. Cada lenguaje trae sus propios mecanismos para hacer sus conversiones.
Estas facilidades serán usadas en nuestros pseudocódigos más adelante.
Estas facilidades serán usadas en nuestros pseudocódigos más adelante.
DATOS COMPUESTOS Y AGRUPACIONES
Muchas veces nuestros datos son más que un único dato atómico, y en este caso manejar datos separados puede no ser muy lingüístico o expresivo.
En nuestros algoritmos, usaremos conglomerados de datos usando tres conceptos comunes en programación: las estructuras, las tuplas, y los arreglos.
En nuestros algoritmos, usaremos conglomerados de datos usando tres conceptos comunes en programación: las estructuras, las tuplas, y los arreglos.
Estructuras
Las estructuras permiten crear un nuevo tipo que se compone de variables de cualquier otro tipo. Las estructuras son un paquete de datos, donde cada dato lleva nombre.
En las estructuras damos nombre a sus componentes para poder luego referirnos a ellos. El uso de las estructuras es importante para poder agrupar datos que tienen mucha relación, y así poderlos referenciar en grupo, y no tener que referirse a cada una de sus partes individuales.
Las estructuras son mecanismos cohesionadores, lo que significa que se agrupan datos que son próximos en semántica, y da sentido tenerlos juntos, porque modelan mejor lo que se quiere expresar.
El tipo de dato estructura se define en nuestros pseudocódigos usando la palabra struct, structure o record seguida del nombre de la estructura. También puede opcionalmente adornarse con el prefijo define.
Luego irán los nombres de los campos con sus tipos, y cerramos con las palabras end, end struct, end structure, o end record, según sean las preferencias. La palabra end puede adornarse con la palabra type.
Un campo podrá ser de cualquier tipo, incluyendo otra estructura. Las estructuras pueden anidar otras estructuras.
En archivos, a la estructura que define la unidad de datos, se le denomina tradicionalmente registro.
La sintaxis en pseudocódigo para la definición de un tipo una estructura, es:
structure NombredelTipoEstructura
field :: Tipo
field2 :: Tipo
…
end
Se debe insistir que se trata de definir un nuevo tipo de dato, y no se está declarando un grupo de variables.
Una escritura más verbosa para pseudocódigo sería:
Define type structure NombredelTipoEstructura
fieldname_1 of type Tipo
fieldname_2 of type Tipo
end type structure
En las estructuras damos nombre a sus componentes para poder luego referirnos a ellos. El uso de las estructuras es importante para poder agrupar datos que tienen mucha relación, y así poderlos referenciar en grupo, y no tener que referirse a cada una de sus partes individuales.
Las estructuras son mecanismos cohesionadores, lo que significa que se agrupan datos que son próximos en semántica, y da sentido tenerlos juntos, porque modelan mejor lo que se quiere expresar.
El tipo de dato estructura se define en nuestros pseudocódigos usando la palabra struct, structure o record seguida del nombre de la estructura. También puede opcionalmente adornarse con el prefijo define.
Luego irán los nombres de los campos con sus tipos, y cerramos con las palabras end, end struct, end structure, o end record, según sean las preferencias. La palabra end puede adornarse con la palabra type.
Un campo podrá ser de cualquier tipo, incluyendo otra estructura. Las estructuras pueden anidar otras estructuras.
En archivos, a la estructura que define la unidad de datos, se le denomina tradicionalmente registro.
La sintaxis en pseudocódigo para la definición de un tipo una estructura, es:
structure NombredelTipoEstructura
field :: Tipo
field2 :: Tipo
…
end
Se debe insistir que se trata de definir un nuevo tipo de dato, y no se está declarando un grupo de variables.
Una escritura más verbosa para pseudocódigo sería:
Define type structure NombredelTipoEstructura
fieldname_1 of type Tipo
fieldname_2 of type Tipo
end type structure
EJEMPLO.
Defina una estructura que represente un punto en el plano cartesiano que consta de un par ordenado de números reales (X, Y). R/ structure Punto x::R y::R end |
Esa es la forma de definir el tipo de dato Punto.
Cuando necesitemos representar un punto de un espacio bidimensional (plano cartesiano), podemos usar dos variables independientes, o simplemente usamos una variable de tipo Punto y le pasamos los valores a sus componentes; si no pasamos valores a sus componentes, se asume que será el valor 0 para datos tipo ::Number, el valor "" (cadena vacía) para datos tipo ::String, el valor '' (caracter nulo) para datos tipo ::Char, y el valor .f.para datos ::Bool.
Los componentes de una estructura deberán tener el tipo para claridad de la definición. De no hacerse, se indica que los campos son de cualquier tipo, lo que no es recomendable y no habla mucho de un buen diseño.
Cuando necesitemos representar un punto de un espacio bidimensional (plano cartesiano), podemos usar dos variables independientes, o simplemente usamos una variable de tipo Punto y le pasamos los valores a sus componentes; si no pasamos valores a sus componentes, se asume que será el valor 0 para datos tipo ::Number, el valor "" (cadena vacía) para datos tipo ::String, el valor '' (caracter nulo) para datos tipo ::Char, y el valor .f.para datos ::Bool.
Los componentes de una estructura deberán tener el tipo para claridad de la definición. De no hacerse, se indica que los campos son de cualquier tipo, lo que no es recomendable y no habla mucho de un buen diseño.
EJEMPLO.
Cree una estructura que represente un punto del plano cartesiano, y úsela para definir varios puntos cualesquiera en el plano cartesiano con los valores que desee. R/ define structure Punto x::R y::R end type structure para usar el tipo, simplemente se hace de forma explícita durante la definición de las variables, o se hace implícito. a::Punto <- Punto(12.4, 7.3) #forma explícita del tipo b <- Punto(35.2, 4.1) #forma implícita c <- Punto(a.x+b.x , a.y+b.y) #punto coordenado (47.6, 11.4) si durante la inicialización no se indican valores para la estructura se asumen valores de inicialización según el tipo. d <- Punto() #punto de coordenadas (0.0 , 0.0) Para este último caso, si los tipos de los campos de la estructura no están definidos, se genera pseudocódigo ambiguo. En este caso se recomienda especificar en la estructura los tipos de los campos. |
Tenga en cuenta los componentes de un punto son x,y. Si se quiere usar alguno de sus componentes, la coordenada x, o la coordenada y, se especifica el punto concreto o nombre de variable, y luego se cualifica con punto la coordenada qu se quiere leer.
Ejemplos de consultas de valores son
a.x, a.y, b.y, b.y, c.x, c.y, d.x, d.y.
Esta es una excelente forma de empacar variables que da sentido que vayan juntas.
En el ejemplo, note que, en adelante, se podrá hacer referencia a a.x, como el valor 12.4, a b.y como el valor 4.1, y así sucesivamente.
También, un tercer punto c es creado con base en operaciones sobre los términos de las estructuras de datos a y b y el contenido de c.x será igual a 47.6 y el contenido de c.y será 11.4.
En nuestros algoritmos, las estructuras son mutables como se da en nuestras variables.
Sin embargo, cada lenguaje de programación define sus propias políticas.
Ejemplos de consultas de valores son
a.x, a.y, b.y, b.y, c.x, c.y, d.x, d.y.
Esta es una excelente forma de empacar variables que da sentido que vayan juntas.
En el ejemplo, note que, en adelante, se podrá hacer referencia a a.x, como el valor 12.4, a b.y como el valor 4.1, y así sucesivamente.
También, un tercer punto c es creado con base en operaciones sobre los términos de las estructuras de datos a y b y el contenido de c.x será igual a 47.6 y el contenido de c.y será 11.4.
En nuestros algoritmos, las estructuras son mutables como se da en nuestras variables.
Sin embargo, cada lenguaje de programación define sus propias políticas.
Tuplas
Es una forma de empaquetar varios valores, incluso de distintos tipos.
Una tupla es una lista de valores encerrada entre paréntesis, donde los elementos están enumerados desde el primero, que está en la posición 1, pasando por el segundo elemento que está n la posición 2, y sucesivamente hasta el último elemento en la posición n, siendo n el número de elementos en la tupla.
Los valores en una tupla pueden ser de cualquier naturaleza, y no requieren ser del mismo tipo: es como una cajita en la que podemos meter cualquier cantidad de datos de cualquier tipo.
No se puede confundir con una estructura ya que son conceptos diferentes. En la estructura los valores siempre llevan un nombre. En una tupla es opcional que lleven nombre, y pueden ser accedidos por posición.
En una tupla los valores no pueden ser modificados en pseudocódigo papaercode, mientas que a una estructura es posible modificar sus valores.
En una tupla para acceder los valores puedo usar la posición del dato a través de un índice, mientras que en una estructura solo puedo usar los nombres.
Para declarar una variable de tipo tupla, usamos Tuple {::R,::R}. Internamente van los tipos de sus componentes. Por ejemplo, para declarar una variable x de tipo Tupla con dos valores reales, podemos escribir
x ::Tuple {::R,::R}
ó
x of type Tuple { type R+, type R+ }
Dado que tradicionalmente La tupla en los lenguajes de programación es inmutable, luego que una tupla existe sus valores no pueden ser alterados.
x of type Tuple {::R,::R} <- (3.14159, 1.4142)
El tipo explícito de x es Tuple { ::R, ::R }, que se lee Tupla con dos valores reales. Una tupla puede contener cualquier número de valores, pero no puede ser modificada.
A esa característica se le conoce como inmutabilidad.
Esto es muy útil para poder hablar de más de un valor a la vez cuando los dos valores están asociados. Es una alternativa a la estructura, y presenta la ventaja que no necesita ser definido como sí lo requiere la estructura.
Un escenario donde las tuplas son muy útiles es cuando en una función necesitamos devolver más de un valor, lo que revisaremos más adelante cuando estemos estructurando nuestros algoritmos.
Otro escenario es cuando se necesita asignar varios valores a la vez a múltiples variables en vez de hacerlo línea a línea.
Otro uso frecuente es cargar varios valores bajo un solo nombre, y poder accederlos luego usando su posición: la posición 1 hace referencia al primer elemento, y así sucesivamente.
Una tupla es una lista de valores encerrada entre paréntesis, donde los elementos están enumerados desde el primero, que está en la posición 1, pasando por el segundo elemento que está n la posición 2, y sucesivamente hasta el último elemento en la posición n, siendo n el número de elementos en la tupla.
Los valores en una tupla pueden ser de cualquier naturaleza, y no requieren ser del mismo tipo: es como una cajita en la que podemos meter cualquier cantidad de datos de cualquier tipo.
No se puede confundir con una estructura ya que son conceptos diferentes. En la estructura los valores siempre llevan un nombre. En una tupla es opcional que lleven nombre, y pueden ser accedidos por posición.
En una tupla los valores no pueden ser modificados en pseudocódigo papaercode, mientas que a una estructura es posible modificar sus valores.
En una tupla para acceder los valores puedo usar la posición del dato a través de un índice, mientras que en una estructura solo puedo usar los nombres.
Para declarar una variable de tipo tupla, usamos Tuple {::R,::R}. Internamente van los tipos de sus componentes. Por ejemplo, para declarar una variable x de tipo Tupla con dos valores reales, podemos escribir
x ::Tuple {::R,::R}
ó
x of type Tuple { type R+, type R+ }
Dado que tradicionalmente La tupla en los lenguajes de programación es inmutable, luego que una tupla existe sus valores no pueden ser alterados.
x of type Tuple {::R,::R} <- (3.14159, 1.4142)
El tipo explícito de x es Tuple { ::R, ::R }, que se lee Tupla con dos valores reales. Una tupla puede contener cualquier número de valores, pero no puede ser modificada.
A esa característica se le conoce como inmutabilidad.
Esto es muy útil para poder hablar de más de un valor a la vez cuando los dos valores están asociados. Es una alternativa a la estructura, y presenta la ventaja que no necesita ser definido como sí lo requiere la estructura.
Un escenario donde las tuplas son muy útiles es cuando en una función necesitamos devolver más de un valor, lo que revisaremos más adelante cuando estemos estructurando nuestros algoritmos.
Otro escenario es cuando se necesita asignar varios valores a la vez a múltiples variables en vez de hacerlo línea a línea.
Otro uso frecuente es cargar varios valores bajo un solo nombre, y poder accederlos luego usando su posición: la posición 1 hace referencia al primer elemento, y así sucesivamente.
Tuplas con nombre en pseudocódigos
Los elementos asignados como valores a la tupla también pueden llevar nombre, y en ese caso se puede cualificar un elemento como en el caso de las estructuras. Esta posibilidad algorítmica (también posible en algunos lenguajes), facilita la referenciación de valores sin usar posiciones como se verá a continuación.
punto::Tuple{::R,::R} <- (x = 5.78 , y = 4.26)
ó
punto <- (x = 5.78 , y = 4.26)
distancia <- (punto.x ^ 2 + punto.y ^ 2) ^ 0.5
punto::Tuple{::R,::R} <- (x = 5.78 , y = 4.26)
ó
punto <- (x = 5.78 , y = 4.26)
distancia <- (punto.x ^ 2 + punto.y ^ 2) ^ 0.5
Acceso a elementos de una tupla
Para acceder alguno de los valores de una tupla, podemos usar muchas formas en pseudocódigo.
Si la tupla no contiene campos con nombre, se puede usar su posición entre corchetes, o se usa punto y luego la posición o escribimos algo más verboso pero lo suficientemente claro.
Por ejemplo, para acceder el primer valor de la tupla punto anterior, podemos escribir
punto [ 1 ]
ó
punto.1
ó
get position 1 of punto
Pero si la tupla contiene campos con nombre, podemos escribir
punto.x
ó
x of punto.
Si la tupla no contiene campos con nombre, se puede usar su posición entre corchetes, o se usa punto y luego la posición o escribimos algo más verboso pero lo suficientemente claro.
Por ejemplo, para acceder el primer valor de la tupla punto anterior, podemos escribir
punto [ 1 ]
ó
punto.1
ó
get position 1 of punto
Pero si la tupla contiene campos con nombre, podemos escribir
punto.x
ó
x of punto.
EJEMPLO.
Represente dos puntos en el plano cartesiano con color (de tipo String) y visibilidad de (tipo booleano). Use tipificación implícita. R/ px <- (5.78 , 4.26 , ”Azul” , .t.) py <- (8.01 , 0.12 , ”Rojo” , .F.) Note que p1 y p2 contienen 4 valores de distinto tipo. Para acceder alguno de esos valores, debe indicar cuál valor consulta con un índice, ya que no tienen nombre. Por ejemplo, si se quiere el segundo valor del punto px, se puede acceder así: px[2] ó px.2 Algo más verboso sería get position 2 of px que corresponde al valor numérico 4.26. EJEMPLO.
Repita el ejercicio anterior usando tuplas con nombre. R/ pa <- (x = 5.78 , y = 4.26, color = ”Azul”, visible = .t.) pb <- (x = 8.01 , y = 0.12, color = ”Rojo”, visible = .f.) Para acceder alguno de esos valores, puede indicar cuál desea consultar con un índice como en el ejemplo anterior. Sin embargo, dado que los elementos ya tienen nombre, es más intuitivo trabajar con ellos. Por ejemplo, diremos que queremos el color del punto pb, así: pb.color Algo más verboso sería get color of pb que corresponde a la cadena “Rojo”. EJEMPLO.
Declare una variable de tipo tupla que contendrá un número y una cadena. Use tipo explícito. Asigne cualquier valor de tupla a la variable. No use nombres para los campos. Finalmente, acceda al valor de la cadena desde la variable. R/ pw::Tuple{ ::Num, ::String } <- (3.1415926535497932384 ,”Pi”) que declara y asigna valores pw[2] ó pw.2 que accede la cadena “Pi” |
Arreglos
Un arreglo es una estructura que permite almacenar un conjunto de datos del mismo tipo, bajo un mismo nombre, donde los elementos están enumerados de tal modo que el elemento que se encuentra de primero está en la posición 1 (uno) [1], el segundo elemento está en la posición 2, y así sucesivamente.
Puede pensar en un arreglo como una tupla mutable, cuyos elementos son homogéneos, esto es, todos son del mismo tipo obligatoriamente.[2]
[1] Muchos lenguajes de programación comienzan en la posición cero y otros lo hacen en la posición 1. En los pseudocódigos de este libro se usa la posición 1 como la primera de los arreglos.
[2] No se puede confundir un arreglo con las listas de algunos lenguajes, o la colección Array de otros lenguajes, donde es posible almacenar objetos de distinto tipo.
Puede pensar en un arreglo como una tupla mutable, cuyos elementos son homogéneos, esto es, todos son del mismo tipo obligatoriamente.[2]
[1] Muchos lenguajes de programación comienzan en la posición cero y otros lo hacen en la posición 1. En los pseudocódigos de este libro se usa la posición 1 como la primera de los arreglos.
[2] No se puede confundir un arreglo con las listas de algunos lenguajes, o la colección Array de otros lenguajes, donde es posible almacenar objetos de distinto tipo.
Tipificación de un arreglo
Sea T cualquier tipo de datos. En nuestros pseudocódigos, un arreglo se definirá como
[ tamaño opcional ]::T , cuando el arreglo es de una dimensión.
Alternativamente, podremos usar alguna de las siguientes opciones en lenguaje natural:
array of T
ó
array of N T (en este caso, n es el número de elementos iniciales)
Si el arreglo es de más de una dimensión se escribe
[,,,…]::T.
Esto es, se abre y cierra corchetes, y luego se indica el tipo, que puede ser cualquier de los vistos. También podremos ser más verbosos y escribir
N dimension array of T
Por ejemplo, para dos dimensiones, escribimos [ , ]::T, siendo T el tipo; pero también podríamos escribir 2 dimension array of T.
Si el tipo no se especifica, se infiere desde la inicialización.
El siguiente es un ejemplo de la inicialización de una variable x de tipo arreglo de una dimensión, que podrá almacenar en sus posiciones valores lógicos (booleanos).
x <- [.t., .f., .f., .t., .t.] # tipo implícito
Si se quisiera definir la variable de forma tal que sea explícito el tipo, podemos escribir
x []::Bool <- [.t., .f., .f., .t., .t.]
Que en una escritura de pseudocódigo más cercana al lenguaje natural, sería:
X array of Bool <- [.t., .f., .f., .t., .t.]
Si no hay inicialización, el tipo es obligatorio.
x []::Bool
En este caso, no se conoce el tamaño del arreglo. La variable después será establecida a valores.
Si se especifica el valor de las dimensiones, automáticamente se está creando un arreglo con una cantidad concreta de elementos vacíos.
x[4]::Bool
Esto hace que el arreglo tenga 4 elementos inicializados automáticamente en un valor de .f. Por lo tanto, la variable x estará asociada al arreglo [.f., .f., .f., .f.]
A continuación, algunos ejemplos de arreglos:
valores <- [8.01 , 0.12 , 0.97]
En este caso, la variable valores es de tipo concreto array of ::R, donde todos sus elementos serán valores reales.
puntos <- [(8.01 , 0.12), (0.97, 14.8)]
En este caso, los elementos del arreglo puntos son tuplas. El tipo de los elementos es entonces ::Tuple { R , R } y el tipo de todo el arraglo es array of ::Tuple { R , R }.
En el siguiente ejemplo, se desea una matrix de 2x2 de reales:
matriz [2,2]::R <- [[ 1 , 2 ],[ 3 , 4 ]]
Note que, en el caso de arreglos, el tipo es asociado a todos los elementos, de modo que no puede haber elementos de distinto tipo dentro de un arreglo.
También es importante ver que los tipos implícitos son posibles porque se inicializa explícitamente el arreglo con datos.
Cuando el arreglo no se inicializa con datos, se debe especificar el tipo.
[ tamaño opcional ]::T , cuando el arreglo es de una dimensión.
Alternativamente, podremos usar alguna de las siguientes opciones en lenguaje natural:
array of T
ó
array of N T (en este caso, n es el número de elementos iniciales)
Si el arreglo es de más de una dimensión se escribe
[,,,…]::T.
Esto es, se abre y cierra corchetes, y luego se indica el tipo, que puede ser cualquier de los vistos. También podremos ser más verbosos y escribir
N dimension array of T
Por ejemplo, para dos dimensiones, escribimos [ , ]::T, siendo T el tipo; pero también podríamos escribir 2 dimension array of T.
Si el tipo no se especifica, se infiere desde la inicialización.
El siguiente es un ejemplo de la inicialización de una variable x de tipo arreglo de una dimensión, que podrá almacenar en sus posiciones valores lógicos (booleanos).
x <- [.t., .f., .f., .t., .t.] # tipo implícito
Si se quisiera definir la variable de forma tal que sea explícito el tipo, podemos escribir
x []::Bool <- [.t., .f., .f., .t., .t.]
Que en una escritura de pseudocódigo más cercana al lenguaje natural, sería:
X array of Bool <- [.t., .f., .f., .t., .t.]
Si no hay inicialización, el tipo es obligatorio.
x []::Bool
En este caso, no se conoce el tamaño del arreglo. La variable después será establecida a valores.
Si se especifica el valor de las dimensiones, automáticamente se está creando un arreglo con una cantidad concreta de elementos vacíos.
x[4]::Bool
Esto hace que el arreglo tenga 4 elementos inicializados automáticamente en un valor de .f. Por lo tanto, la variable x estará asociada al arreglo [.f., .f., .f., .f.]
A continuación, algunos ejemplos de arreglos:
valores <- [8.01 , 0.12 , 0.97]
En este caso, la variable valores es de tipo concreto array of ::R, donde todos sus elementos serán valores reales.
puntos <- [(8.01 , 0.12), (0.97, 14.8)]
En este caso, los elementos del arreglo puntos son tuplas. El tipo de los elementos es entonces ::Tuple { R , R } y el tipo de todo el arraglo es array of ::Tuple { R , R }.
En el siguiente ejemplo, se desea una matrix de 2x2 de reales:
matriz [2,2]::R <- [[ 1 , 2 ],[ 3 , 4 ]]
Note que, en el caso de arreglos, el tipo es asociado a todos los elementos, de modo que no puede haber elementos de distinto tipo dentro de un arreglo.
También es importante ver que los tipos implícitos son posibles porque se inicializa explícitamente el arreglo con datos.
Cuando el arreglo no se inicializa con datos, se debe especificar el tipo.
Tamaño de un arreglo
Cuando se realizan algoritmos basados en arreglos, es conveniente poder preguntar por el tamaño. Cuando el arreglo es de una sola dimensión, esto es, es una lista ordenada, el tamaño se consulta con el operador de tamaño
|arreglo|
Podremos aceptar la variante de lenguaje natural:
size of nombre_arreglo
Cuando el tamaño del arreglo es de dos dimensiones, esto es, tiene filas y columnas, se les llama matriz.
Para saber cuántas filas tiene, se asume que las filas son su primera dimensión, y el tamaño de la matriz se puede conocer con |nombre_arreglo, 1|. Para conocer el tamaño de la segunda dimensión, esto es, el número de columnas de la matriz, se utiliza en pseudocódigo |nombre_arreglo , 2|.
Podremos aceptar la variante de lenguaje natural:
size of nombre_arreglo [for] dimension dimension.
|arreglo|
Podremos aceptar la variante de lenguaje natural:
size of nombre_arreglo
Cuando el tamaño del arreglo es de dos dimensiones, esto es, tiene filas y columnas, se les llama matriz.
Para saber cuántas filas tiene, se asume que las filas son su primera dimensión, y el tamaño de la matriz se puede conocer con |nombre_arreglo, 1|. Para conocer el tamaño de la segunda dimensión, esto es, el número de columnas de la matriz, se utiliza en pseudocódigo |nombre_arreglo , 2|.
Podremos aceptar la variante de lenguaje natural:
size of nombre_arreglo [for] dimension dimension.
Insertar elementos en un arreglo
En pseudocódigo, si se desea adicionar un elemento a un arreglo, se podrá al final, o en una posición específica, y siempre con una función especial en pseudocódigo que llamaremos aggregate(), y que también podremos escribir como append(), insert(), pack(), or bundle(). La función aumenta el tamaño del arreglo y adiciona el nuevo elemento. Escribiremos:
aggregate (nombre arreglo, valor de elemento). Adiciona un nuevo elemento al final del arreglo.
Dado que es pseudocódigo, también podremos escribir la siguiente variante en lenguaje natural:
aggregate valor to arreglo
aggregate (nombre arreglo, valor, posición). Adiciona un nuevo elemento en la posición especificada. Los demás elementos se desplazan a la derecha de ser necesario. El arreglo crece con una nueva posición.
De nuevo, y dado que es pseudocódigo, también podremos escribir alguna de las siguientes variantes en lenguaje natural:
aggregate valor to arreglo in position posición
Por ejemplo, la siguiente línea inicializa un arreglo de reales a los que les asocia 5 valores
array_numbers []::R <- [1.7, 5.67, 7.6, 6.0, 11.8]
El arreglo contendrá 5 elementos. Para adicionar un nuevo elemento al final del arreglo en pseudocódigo papercode, podremos decir alguna de:
aggregate 12 to array_numbers
ó
aggregate ( array_numbers, 12.0 )
en este momento, el arreglo tiene el siguiente contenido:
[1.7, 5.67, 7.6, 6.0, 11.8, 12.0]
Podemos también indicar la posición de inserción de un nuevo elemento:
aggregate 12.0 to array_numbers in position 3
Ya el arreglo se encuentra así:
[1.7, 5.67, 12.0, 7.6, 6.0, 11.8, 12.0]
Recuerde: cualquiera de los verbos aggregate(), append(), insert(), pack(), o bundle() sirven al propósito.
Otros verbos como add(), put(), entre otros, no se recomiendan para pseudocódigo.
aggregate (nombre arreglo, valor de elemento). Adiciona un nuevo elemento al final del arreglo.
Dado que es pseudocódigo, también podremos escribir la siguiente variante en lenguaje natural:
aggregate valor to arreglo
aggregate (nombre arreglo, valor, posición). Adiciona un nuevo elemento en la posición especificada. Los demás elementos se desplazan a la derecha de ser necesario. El arreglo crece con una nueva posición.
De nuevo, y dado que es pseudocódigo, también podremos escribir alguna de las siguientes variantes en lenguaje natural:
aggregate valor to arreglo in position posición
Por ejemplo, la siguiente línea inicializa un arreglo de reales a los que les asocia 5 valores
array_numbers []::R <- [1.7, 5.67, 7.6, 6.0, 11.8]
El arreglo contendrá 5 elementos. Para adicionar un nuevo elemento al final del arreglo en pseudocódigo papercode, podremos decir alguna de:
aggregate 12 to array_numbers
ó
aggregate ( array_numbers, 12.0 )
en este momento, el arreglo tiene el siguiente contenido:
[1.7, 5.67, 7.6, 6.0, 11.8, 12.0]
Podemos también indicar la posición de inserción de un nuevo elemento:
aggregate 12.0 to array_numbers in position 3
Ya el arreglo se encuentra así:
[1.7, 5.67, 12.0, 7.6, 6.0, 11.8, 12.0]
Recuerde: cualquiera de los verbos aggregate(), append(), insert(), pack(), o bundle() sirven al propósito.
Otros verbos como add(), put(), entre otros, no se recomiendan para pseudocódigo.
Desagregado de elementos de un arreglo
En pseudocódigo, la operación inversa a adicionar también es posible. Para borrar un elemento a un arreglo, se especifica la posición. La función disaggregate() decrementará el tamaño del arreglo. También podremos escribir unpack(), delete(), remove(), erase(), drop() :
disaggregate (nombre arreglo, posición). borra el elemento en la posición.
Por ejemplo, en el arreglo anterior disaggregate(somenumbers,2) dejará el arreglo así:
[1.7, 7.6, 6.0, 11.8, 12.0]
En pseudocódigo, podremos escribir alguna de las siguientes variantes en lenguaje natural:
disaggregate posición from arreglo
ó
from arreglo disaggregate posición
También recuerde: cualquiera de los verbos disaggregate(), unpack(), delete(), remove(), erase(), eliminate() o drop() sirven al propósito.
Otros verbos como substract() o terminate(), entre otros, no se recomiendan para pseudocódigo para no generar ambigüedad.
disaggregate (nombre arreglo, posición). borra el elemento en la posición.
Por ejemplo, en el arreglo anterior disaggregate(somenumbers,2) dejará el arreglo así:
[1.7, 7.6, 6.0, 11.8, 12.0]
En pseudocódigo, podremos escribir alguna de las siguientes variantes en lenguaje natural:
disaggregate posición from arreglo
ó
from arreglo disaggregate posición
También recuerde: cualquiera de los verbos disaggregate(), unpack(), delete(), remove(), erase(), eliminate() o drop() sirven al propósito.
Otros verbos como substract() o terminate(), entre otros, no se recomiendan para pseudocódigo para no generar ambigüedad.
TIPOS ABSTRACTOS Y TIPOS CONCRETOS
Hasta el momento, hemos aprendido que, en nuestro pseudocódigo algorítmico, podemos dejar que algunas asociaciones a variables tengan el tipo implícito, y otras veces se debe explicitar.
A continuación, un conjunto de reglas aclaradoras.
A continuación, un conjunto de reglas aclaradoras.
- Todo variable nueva a la que se le asigne un dato numérico atómico y no se le especifique el tipo, podrá asumirse que lleva tipo de dato abstracto implícito ::Number.
- Todo variable nueva a la que se le asocie un dato numérico, y no se le especifique el tipo, llevará el tipo concreto del dato ::R, ::Z, ::N, ::Q, ::C según sea el caso para el valor asignado.
- Según lo anterior, un variable numérica tendrá tipo de dato concreto (::R, ::Z, ::N, ::Q, ::C), y tipo de dato abstracto ::Number. Tanto ::R, ::Z, ::N, ::Q, y ::C, son tipos concretos del tipo de dato abstracto ::Number.
- Todo variable nueva a la que se le asigne un caracter y no se le especifique el tipo, llevará como tipo implícito el tipo ::Char.
- Todo variable nueva a la que se le asigne una secuencia de caracteres y no se le especifique el tipo, llevará como tipo de dato implícito el tipo ::String.
- Toda operación aritmética con datos de tipo abstracto ::Number, dará como resultado el tipo de dato concreto más apropiado. Por ejemplo, sumar enteros con reales, da reales; sumar naturales con enteros, da enteros; multiplicar enteros con reales con complejos da complejos; etc. Esto significa que en una expresión, se promueven los tipos de los operandos al tipo más amplio.
- Un caracter podrá formar parte de una expresión aritmética. En ese caso se usa es el valor Unicode del caracter. Por ejemplo, para el caracter 'B' con código 66, la expresión 'B'/ 4 es igual a 16.5 de tipo::R, que a su vez es de tipo abstracto ::Number. Pero también note, por ejemplo, que para el caracter 'D' con código 68, la expresión 'D' / 2 es igual a 34, que es de tipo ::Z (esto normalmente no es así en los lenguajes de programación).
- Toda variable que desee ser declarada sin un valor inicial, tendrá que llevar un tipo explícito. En ese caso, el valor inicial es 0 para datos concretos numéricos enteros, 0.0 para datos concretos numéricos reales, cadena nula "" para strings, y caracter nulo '' con código cero para variables de tipo caracter.
- El tipo de dato de los componentes de una estructura se debe explicitar.
- Toda expresión deberá pertenecer a algún tipo de forma implícita (ver más adelante el capítulo de expresiones).
- El tipo implícito de una expresión podrá convertirse en un nuevo tipo, si se especifica adecuadamente el nuevo tipo, y la conversión es posible.
- Un valor booleano podrá ser convertido a string para obtener las cadenas ".t." o ".f.", a través de la aplicación de la función de tipo ::Str( )
- Un valor numérico podrá ser convertido a ::Bool. Si el valor es 0, la convesión da .f. , y si el valor es distinto de cero, el valor es .t.
TALLER PSEUDOCÓDIGO: TIPOS
- Prediga el código Unicode para el caracter ‘H’ y para el caracter ‘9’
- Suponga el número 18. ¿Tiene este número un código? Explique su respuesta.
- Identifique qué valores son de tipo ::Q
1/4 1/2 0.125 0.11111111… -0.121212 √2 π - Identifique qué valores son de tipo ::C
1/4i 1/2i+2 0.125 -0.121212j √2i + π - Prediga el código Unicode para el caracter ‘H’ y para el caracter ‘9’
- Suponga el número 18. ¿Tiene este número un código? Explique su respuesta.
- Identifique el tipo de los valores “I <3 you”, ‘u’, “नमस्ते”, ‘д’
- Determine el número de códigos requeridos para escribir la cadena “computador”
- Dado un valor booleano x, identifique sus posibles valores.
- Dado un valor booleano x, identifique los posibles valores de su negación.
- Determine el valor para la negación de la negación de .f.
- Elabore una expresión cuantificadora para números enteros positivos impares
- Describa el conjunto de números ::{x½x ∈ Z , 2x+7}
- Describa el conjunto de números ::{x½x ∈ Z+ , 2x+7}
- Enumere los primeros 10 valores del conjunto ::{x | x ∈ Z+ , 2x2+y2}
- Determine los valores finales para las variables
x::Number <- 8
y::Number <- 2
z::Number <- 2x + 4y – x3
w::Number <- w – y + z - Defina 2 variables a y b, y a cada una de las variables asóciele cualquier valor.
- Defina una tercera variable hipo a partir de una expresión que calcule la suma de los cuadrados de las variables a y b.
- Construya una nueva expresión que le sume a la variable hipo la resta de a y b y deje el resultado en la misma variable hipo.
- Defina una constante pi.
- Defina una variable radio, y asocie la variable al valor 4.
- Defina la variable volumen, y asóciele la expresión 4/3 multiplicado por pi, multiplicado por el radio al cubo.
- Defina tres variables c1, c2, y c3, y asócieles los caracteres ‘0’, ‘1’, ‘A’. Use tipo para la variable c2.
- Según lo visto hasta el momento, ¿qué código tiene asociado c1, c2, y c3?
- Defina la variable nombap usando tipo, y asígnele su nombre y apellido, separados por un espacio.
- Indique en qué posición de la variable nombap se encuentra el espacio, y la última letra del apellido.
- Indique cuál es la longitud de la string nombap.
- Convertir π+e a entero.
- Conocer el código Unicode del caracter ‘W’.
- Conocer el caracter que representa el código Unicode 84.
- Determinar la parte fraccionaria de (π+e)
- Determinar la parte entera del número e
- Convertir la parte entera de π/e a real.
- Sumar la parte entera de e a la parte fraccionaria de π.
- Hallar el residuo de dividir un número x entre un número y.
- Convertir la cadena “1.2345” a número entero.
- Convertir la cadena “1.2345” a número real.
- Convertir la cadena “123” a número real.
- Usando estructuras, defina dos números complejos, con parte real e imaginaria. Usando estructuras, cree un tercer número complejo compuesto por la suma de la parte real y la parte imaginaria.
- Use tuplas para definir dos números complejos, parte real y parte imaginaria. Cada número complejo deberá llevar un color como string. Use tuplas y cree un tercer número complejo compuesto por la suma de la parte real y la parte imaginaria, y asigne un nuevo color al nuevo número.
- Use arreglos y defina dos números complejos. Cada arreglo tiene dos posiciones, una parte real y una parte imaginaria. Use arreglos y cree un tercer número complejo compuesto por la suma de la parte real y la parte imaginaria.
- A continuación, se presentan algunas definiciones implícitas. Identifique en cada caso el tipo de dato (no el valor) asociado a la variable.
x1 <- 4
x2 <- [1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8]
x3 <- (8, .t.)
x4 <- (“Betelguese”,5.8,6)
x5 <- (“Sirius”,5, (12.4, 3.6,"GIIV",’C’))
x6 <- 4
x7 <- x6 + x4[2]
x8 <- ( Z(‘A’) + R(‘B’) ) + 2
x9 <- [ (1,2)]
x10 <- [ ([1],2) ]
x11 <- [ ([1],(2,3)) ]
x12 <- x11[1][1]
x13 <- x11[1][2][2]
x14 <- x11[1][2][2]
x15 <- x2[x1] - Identifique cuáles conversiones son posibles. Para el caso de las conversiones posibles, identifique el nuevo valor. Para el caso de las no posibles, argumente.
c1 <- :Str(123.4)
c2 <- ::Bool(.False.)
c3 <- :Str(123)
c4 <- ::R(“321”)
c5 <- ::N(“3.21”)
c6 <- ::N(“.t.”)
c7 <- ::Bool(“.t.”)
c8 <- ::Bool(.t.)
c9 <- ::Bool(2)
c10 <- ::R(2)
c11 <- 2 * 3.2
c12 <- ::Z≠(2 * 3.2)
c13 <- ::Z+(-2 * 3.2)
c14 <- ::Z+(-2 * - 3.2)
c15 <- ::N(-2 * - 3.2)
c16 <- ::R(-2 * - 3.2)
c17 <- ::Str(::Z(-2 * - 3.2))
c18 <- ::R( ::Str(-2 * - 3.2))
c19 <- ::Chr(::N(-33 * - 2))