Xwork's Blog

The lord is waiting to take your hand.

Vamos a platicar #12 - La luz al final del túnel

 Hola de nuevo a todos, el día de hoy solo vamos a platicar un poco.


Cómo muchos sabrán, la situación del mundo se complico a finales del año 2019 e inicios del 2020, pero se complico aun más en marzo, por lo que ya ha pasado mas de un año. Para todos fue un problema y más si perdimos a alguien. El tiempo ha pasado, y si bien no mencioné nada (y trate de no hacerlo, ya que había información de sobra) es importante que las cosas ya van mejorando.

Hay mucho que celebrar. La primera es que si estas leyendo esto, significa que casi la libramos ya (eso dependiendo de que país seas, pero por lo general). La segunda cosa es que en junio cumplimos cinco años y he estado trabajando para terminar los proyectos que quiero publicar y finalmente, también parece ser que el blog alcanzará sus primeras cien mil visitas en el mes de junio por lo que decidí hacer una buena tanda de post para ese mes.

Hace algún tiempo pensé en hacer alguna clase de cooperación con algunos de los blogs que surgieron casi al mismo tiempo que el mío, pero para mala suerte de todos, todos ellos desaparecieron.

Y bien, por ahora es todo.

Los leo luego

Learning machine #17 - Programando en Pascal - Arreglos, arreglos dinámicos y arreglos multidimensionales.

 Hola de nuevo a todos, el dia de hoy vamos a continuar con un poco mas de programación en Pascal. EN alguno de los post anteriores, vimos cómo usar arreglos, arreglos de punteros,  pero nos falto ver cómo usar arreglos dinámicos y arreglos de dimensiones múltiples. Si bien ya los usamos en los arreglos de punteros, no hemos visto aun cómo son la reglas para usarlos.


Arreglos de una sola dimensión.

A manera de repaso veamos cómo es que se crea un arreglo de una sola dimensión en Pascal. En Pascal, para poder crear un arreglo, se debe de hacer lo siguiente.
type
	MiArr = array [0..9] of integer;
var
    Lista : MiArr;
Primero, debemos de crear un nuevo tipo, en el ejemplo anterior es "MiArr", seguido de la palabra reservada "array[]", dentro de los corchetes, se debe de establecer el rango para los valores de los índices. Normalmente se establece de cero a n pero se pueden crear arreglos que no sean de base cero (que no empiece el primer índice en cero). Incluso para valores que NO sean del tipo "real", se pueden usar valores negativos. Después de los corchetes debe de ir la palabra reservada "of" y finalmente el tipo del que serán los elementos contenidos en el arreglo.

Para inicializar los valores del arreglo, simplemente se les asigna un valor (normalmente usando un "for") y para poder usar los valores, bastara con llamar a la variable seguida de un corchete dentro del cual ira el valor del índice que queremos leer. Para ver con más claridad, retomemos un ejemplo que ya habíamos visto.
program Arreglos;

type
ArregloDeNumeros = array[0..99] of integer;

var
MisNumeros : ArregloDeNumeros;
i : integer;

begin

    for i := 0 to 99 do
    begin 
        MisNumeros[i] := i * 2;
    end;
    
    for i := 1 to 99 do
    begin 
        writeln(MisNumeros[i]);
    end;
    
end.
Cómo podrás ver, para asignar valores a todos los elementos del arreglo, simplemente usamos un ciclo "for" y para leer los valores usamos otro, pero si queremos leer solo uno en particular, solo bastaría con algo cómo "MisNúmeros[3]" que serviría para retornar el valor del elemento con índice tres.

Arreglos multidimensionales.

Para declarar un arreglo de dimensión múltiple, se sigue mas o menos los pasos anteriores, es decir: creamos un tipo, asignamos a una variable el nuevo tipo  y lo usamos. Pero el cambio viene al momento de definir el tamaño del arreglo. Primero veamos el siguiente ejemplo.

type
	MiArr = array [0..9 , 0..9] of integer;
var
    Lista : MiArr;

Cömo podrás observar, simplemente se definen las dimensiones de cada uno de los arreglos, por lo que en ejemplo anterior, habremos creado un arreglo de dos dimensiones con un tamaño de 10x10. Para agregar una dimensión mas, bastará con agregar otra coma seguida del rango.

Ahora miremos el siguiente ejemplo:
program ArreglosMulti;

type
ArregloDeNumeros = array[0..9 , 0..9] of integer;

var
MisNumeros : ArregloDeNumeros;
i , j : integer;

begin

    for i := 0 to 9 do
    begin 
    for j := 0 to 9 do
        MisNumeros[i,j] := i + j * 2;
    end;
    
    for i := 1 to 9 do
    begin 
        for j := 0 to 9 do
        write(' ',MisNumeros[i,j]);
        writeln();
    end;
	
end.
Si miramos bien ahora los arreglos se accesan mediante un sistema coordenado. para acceder al tercer elemento de la segunda fila, bastaría con tener algo cómo "MisNumeros[2,3]". Finalmente y de manera meramente ilustrativa, veamos el ejemplo de un array de 10x10x10 elementos.
program ArreglosMulti;

type
ArregloDeNumeros = array[0..9 , 0..9, 0..9] of integer;

var
MisNumeros : ArregloDeNumeros;
i , j , k : integer;

begin

    for i := 0 to 9 do
    begin 
        for j := 0 to 9 do
        begin
            for k := 0 to 9 do
                MisNumeros[i , j , k] := i + j + k * 2;
        end;
    end;
    
    for i := 1 to 9 do
    begin 
        for j := 0 to 9 do
        begin
            for k := 0 to 9 do
            write(' ',MisNumeros[i,j,k]);
            
        writeln();
        end;
        writeln();
    end;

end.
Y de manera similar, para acceder a un elemento seria "MisNumeros[1,2,3]".
Al momento de crear arreglos de varias dimensiones, no es necesario que estos sean "cuadrados", en los ejemplos, son arreglos de 10x10, pero pueden ser de valores diferentes cómo de 3x4x10 y para definir su tamaño solamente debemos de establecerlos al momento de crear el tipo "array[0..3,0..4,0..10]", solamente debemos de tener cuidado a la hora de acceder a los valores y que el indice al que queremos acceder, este dentro del intervalo.

Arreglos dinámicos.

Los arreglos dinámicos se distinguen de los otros por no tener un tamaño fijo y que a la hora de inicializarlos, tienen tamaño cero. Son especialmente útiles a la hora de ejecución, ya que nos permite cambiar el tamaño del arreglo en función a lo que el programa requiera y así en lugar de crear un arreglo de longitud 1000 para cubrir todas las posibles necesidades, solamente se crean los necesarios a cómo se vaya necesitando.

Para crear un arreglo dinámico, se siguen los mismo pasos que antes, es decir; se crea un tipo  nuevo y cuando le indicamos que va  a ser un arreglo no establecemos la longitud. Para apreciar mejor cómo se hace, veamos el siguiente ejemplo:
program ArreglosDina;

type
ArregloDeNumeros = array of integer;

var
MisNumeros : ArregloDeNumeros;
i , Items : integer;

begin

    Items := 10;
    setlength(MisNumeros , Items);
    
    for i := 0 to (Items - 1) do
            MisNumeros[i] := i * 2;

    for i := 0 to (Items - 1) do
            writeln(' ',MisNumeros[i]);

end.
Cómo podrás ver, al momento de crear el tipo "ArregloDeNumeros" seguido de la palabra reservada array, no se establece el tamaño pero simplemente se establece el tipo. Para ajustar el tamaño del arreglo, antes de usarlo, debemos de usar la función "setlength()". La función "setlength()".recibe dos o mas parámetros, el primero es el nombre de la variable del cual va a ajustar el tamaño, en el ejemplo anterior fue "MisNumeros", seguido del tamaño a asignar (que en el ejemplo fue la variable "Items" con un valor de 10). Para acceder al valor de cada elemento se hace igual que con los arreglos tradicionales.

Y bien, por ahora es todo. Aun quedan muchas cosas pendientes en el lenguaje Pascal, pero creo que solo un post mas dedicado a los arreglos estará bien (antes de olvidarme de la serie "programando en Pascal" por dos años). Cómo de costumbre puedes copiar y pegar los códigos para probarlos.

Los leo luego.


Vamos a programar #94 - Formateando números en arduino - Camino a speedometer version final.

Hola de nuevo a todos, el día de hoy vamos a continuar con mas partes para llegar a la versión final del velocímetro.


Leyendo algunos comentarios que hace la gente sobre que más se le podría modificar al velocímetro, muchos de ellos coincidían que había que corregir algunos de ellos. Los principales "detalles" estaban en la pantalla. Si bien no eran errores, aprovechando que se va a actualizar, decidí arreglarlos de una vez.

Supongamos que en la pantalla tenemos una velocidad de 10.09 km/h pero si desaceleramos, a por ejemplo 9.1 la pantalla mostraba algo cómo 9.19, y la cosa era peor si nos deteníamos ya que se mostraba 0.09. La razón por la que pasaba esto es por cómo se maneja la pantalla. Para ponerlo de forma simple, solo cuando se escribe algo en cierta posición, la pantalla se actualiza pero solo en esa zona, cuando escribimos "v=10.09" se usan siete espacios y mientras los usemos con números que usen el mismo "ancho" no se verá ningún problema, pero cuando tenemos cualquier número inferior a 10.00 cómo 9.9 ahora solo se usan menos espacios por lo que en lugar de actualizar los mismos siete de antes, solo se actualizan cinco o seis. Para poder solucionarlo, podemos escribir número que si importar cual sea, siempre ocupen la misma cantidad de espacios.

En C existen varias formas de formatear números, pero algunas de ellas no están disponibles para usarse en arduino (y debo de admitirlo, eso no lo sabia hasta apenas) y por eso veremos cómo es posible usar el reemplazo que arduino ofrece.

Primero que nada, hay que definir cual es el "estilo" que queremos que cada número tenga. En el caso del velocímetro, hay cuatro números importantes: la velocidad, la distancia, las revoluciones (o vuletas) y el voltaje de la batería. En el caso de la velocidad, una velocidad máxima de 99.99km/h es mas que suficiente para una bicicleta por lo que el numero ocuparía cinco espacios (con el punto incluido). Para las distancia, un viaje de 999.99 km es mas que suficiente para la mayoría de los ciclistas, por lo que seis digitos parecen suficiente, para las revoluciones, 999999 parecen suficientes por lo que seis espacios parecen suficientes y finalmente la batería, ya que el voltaje máximo de una sola pila es 4.2v, con solo reservar tres espacios es mas que suficiente.

Ahora veamos un código hipotético en C que serviría para usarse en un programa de computadora (por ejemplo) pero que no produciría el resultado esperado en arduino. EL código es el siguiente:

#include <stdio.h>

float Speed = 9.1;
float Distance = 9.04;
int Revolution = 16384;
float Battery = 2.0;

char BuffSpeed[20];
char BuffDistance[20];
char BuffRevolution[20];
char BuffBattery[20];

int main()
{

    sprintf(BuffBattery , "R=%3.1f\n", Battery);
    sprintf(BuffRevolution , "R=%6d\n", Revolution);
    sprintf(BuffDistance , "d=%6.2f\n", Distance);
    sprintf(BuffSpeed, "V=%5.2f\n", Speed);

    printf(BuffSpeed);
    printf(BuffDistance);
    printf(BuffRevolution);
    printf(BuffBattery);

    return 0;
}

Al compilarlo con los valores asignados, produce el siguiente resultado:

V= 9.10

d=  9.04

R= 16384

R=2.0

Pero cómo no es muy fácil de apreciar, solo para este ejemplo vamos a poner "0" en lugar de espacios en blanco para que se mas fácil de apreciar (en la pantalla no para poder preservarla un poco mas.) por lo que probamos con el siguiente código:

#include <stdio.h>

float Speed = 9.1;
float Distance = 9.04;
int Revolution = 16384;
float Battery = 2.0;

char BuffSpeed[20];
char BuffDistance[20];
char BuffRevolution[20];
char BuffBattery[20];

int main()
{

    sprintf(BuffBattery , "R=%3.1f\n", Battery);
    sprintf(BuffRevolution , "R=%06d\n", Revolution);
    sprintf(BuffDistance , "d=%06.2f\n", Distance);
    sprintf(BuffSpeed, "V=%05.2f\n", Speed);

    printf(BuffSpeed);
    printf(BuffDistance);
    printf(BuffRevolution);
    printf(BuffBattery);

    return 0;
}

Al compilarlo con los valores asignados, produce el siguiente resultado:

V=09.10

d=009.04

R=016384

R=2.0

Ahora resulta mas sencillo observar que por ejemplo la velocidad siempre ocupara cinco espacios a pesar de ser menor a 10km/h y que por ejemplo la distancia ocupa seis espacios a pesar de ser menor a 100km.

Pero que pasa si tratamos de ejecutar el mismo código en arduino?


Cómo puede observarse, la mayor parte del código se compila pero no funciona. Esto se debe principalmente a que a la hora de formatear los números del tipo "float" requiere mas poder de procesamiento por lo que en arduino no se implementó (**o eso es lo que quiero creer**), para el caso del los enteros es posible usar la misma función "sprintf()".

Para poder hacer algo similar, podemos usar la funcion "dtostrf()". Esta funcion lo que hace es convertir un número "double" a su equivalente en "string", para eso la funcion recibe cuatro parametros.

  • char * dtostrf (double __val, signed char __width, unsigned char __prec, char *__s)
    • __val es el valor que se va a convertir
    • __width es el tamaño que debe de tener la cadena.
    • __prec Es la cantidad de decimales que usaran
    • __s Es el sitio donde se almacenara el resultado.
Ahora recordemos que queremos que la velocidad tenga cinco espacios, pero además de dos decimales, lo que podemos hacer es algo cómo lo que sigue:

dtostrf(Speed , 5 , 2 , BuffVelocity);

Con lo anterior le estamos indicando que el string resultante debe de convertir la variable "speed", pero además el resultado, debe de tener una longitud de 5 y dos decimales, todo lo anterior lo debe de guardar en "BuffVelocity". Solo para ejemplificar, portemos el programa que corre en la computadora para que corra en arduino y para eso usaremos una pantalla LCD.

//YWROBOT
//Compatible with the Arduino IDE 1.0
//Library version:1.1
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
// Conexiones de la pantalla usando el convertidor a i2c
//SCL - A5
//SDA - A4
LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 16 chars and 2 line display

float Speed = 9.1;
float Distance = 9.04;
int Revolution = 16384;
float Battery = 2.0;

char BuffSpeed[20];
char BuffDistance[20];
char BuffRevolution[20];
char BuffBattery[20];


void setup()
{
    lcd.init();
    lcd.backlight();
}


void loop()
{
    dtostrf(Speed , 5 , 2 , BuffSpeed);
    dtostrf(Distance , 6 , 2, BuffDistance);
    sprintf(BuffRevolution , "R=%6d", Revolution);
    dtostrf(Battery , 4 , 2, BuffBattery);

    lcd.setCursor(0, 0);
    lcd.print("v=");
    lcd.setCursor(2 , 0);
    lcd.print(BuffSpeed);

    lcd.setCursor(8, 0);
    lcd.print("d=");
    lcd.setCursor(10, 0);
    lcd.print(BuffDistance);

    lcd.setCursor(0,1);
    lcd.print(BuffRevolution);

    lcd.setCursor(10,1);
    lcd.print("v=");
    lcd.print(BuffBattery);
}


Al compilarlo y ejecutarlo tenemos que ahora si se produce el resultado esperado.

Y bien, por ahora es todo, ya casi llegamos a la versión final del velocímetro que justo acaba de cumplir tres años desde la primera.

Los códigos de antes solo fueron ilustrativos, por lo que si quieres probarlos, puedes copiarlos y pegarlos para usarlos.

Los leo luego.

Learning machine #16 - Programando en Pascal - Arreglos de punteros.

 Hola de nuevo a todos, el día de hoy vamos a continuar con más aprendizaje del lenguaje de programación Pascal.


En el post anterior vimos cómo es posible crear arreglos y usar punteros, pero en el programa del triangulo de Pascal, fue cuando mucha gente prguntó cómo es que funcionaba. Hay que recordar que cuando usamos punteros, el código debe de ser bien manejado si no, pueden ocurrir cosas malas.


Para poder crear un arreglo de punteros, primero debemos de crear un par de tipos, el primero debe de ser una nuevo tipo del tipo "array of algo" donde "algo" es alguno de los tipos soportados por Pascal. Seguido debemos de crear un nuevo tipo que va a ser un puntero del tipo que acabamos de crear. Para ilustrar un poco mejor, retomemos parte del código del triangulo de Pascal.


type
    Values = array of integer;
    PValues = ^Values;

En la declaración de los tipos, creamos primero el tipo "Values" que a su vez es del tipo "array of integer", una vez creado, solo queda crear un nuevo tipo que será un puntero al tipo que acabamos de crear, en este caso es "PValues" que es un puntero de "^Values".

Para poder utilizar los punteros hay que inicializarlos y para eso, hay que hacer la declaración de una variable que sea del tipo que creamos al ultimo, es decir al puntero "PValues" (en el área de las variables) y después cuando vayamos a usar la variable, debemos de inicializarla de forma explicita haciendo uso de la función "new()". Finalmente hay que establecer el tamaño que tendrá el arreglo haciendo uso de la función "setlength()". Para poder apreciar un poco más, de nueva cuenta tomemos el código del triangulo de Pascal y revisemos la función "CalculateLevel()".

function CalculateLevel (Level : integer) : PValues;
var
    i : integer;
    Result1 : PValues;
    PResult : PValues;

begin
    
    new(Result1);
    Setlength(Result1^, Level);
    
    
    if (Level = 1) then
    begin
        Result1^[1] := 1;
    end;

    if (Level = 2) then
    begin
        Result1^[1] := 1;
        Result1^[2] := 1;
    end;
	
    if (Level > 2) then
    begin
        PResult := CalculateLevel(Level - 1);
        for i := 1 to Level do
        begin
            if (i = 1) or (i = Level) then
            begin
                Result1^[i] := 1;
            end
            else
            begin
                Result1^[i] := PResult^[i] + PResult^[i - 1];
            end;
        end;
    end;
	
    exit(Result1);
	
end;
Para poder usar los valores dentro del arreglo, bastará con usar el nombre de la variable que se el arreglo, seguido de "^" y a su vez seguido del número del índice entre corchetes, en el código anterior, cuando queremos asignar el valor de uno al elemento uno, tenemos "Result1^[1] := 1;".

Un ejemplo pero ahora usando el tipo string.

program ArregloDePunteros;
    type
        Nombres = Array of string;
        PointToNombres = ^Nombres;
    var
        ListaDeNombres : PointToNombres;
        i : integer;
begin
    New(ListaDeNombres);
    Setlength(ListaDeNombres^ , 4);

    ListaDeNombres^[1] := 'RMFP';
    ListaDeNombres^[2] := 'RSC';
    ListaDeNombres^[3] := 'USG';
    ListaDeNombres^[4] := 'SCL';

    for i := 1 to 4 do
        writeln (ListaDeNombres^[i]);
        
end.

Cómo podrás observar, el procedimiento es exactamente el mismo. Primero creamos los tipos "Nombres"; que es del tipo "Array Of String", y seguido creamos el tipo "PointToNombres" que es un puntero a "Nombres". Después creamos una variable llamada "ListaDeNombres" que será del tipo "PointToNombres", luego la inicializamos usando "New()" y establecemos el tamaño usando "Setlength()". Finalmente para acceder a los valores, usamos la variable "ListaDeNombres^".




Y bien, por ahora es todo, en el siguiente post veremos mas a detalle los arreglos. Cómo de costumbre, puedes usar el compilador online para probar el código.

Los leo luego.

Learning machine #15 - Programando en Pascal - Tipos, Punteros y arreglos.

 Hola de nuevo a todos, el día de hoy vamos a continuar con un poco mas del lenguaje de programacion Pascal.


Hace algunos días hice un programa que sirve para calcular el triangulo de Pascal. La versión en C, Python y Pascal están disponibles para su consulta, pero a partir de ellos, se generaron dudas y si bien en el caso de Python y C siempre he dicho que en el blog no hay tutoriales para aprender a programar, en el caso de Pascal no es así. En el caso de C y Pascal se hacen uso de punteros y si bien la forma de declararlos en cada uno es diferente, la forma de uso es esencialmente la misma, por eso este post sirve para poder entender cómo es que se utilizan los punteros en Pascal, pero la idea para C es la misma (en el caso de los punteros). Para poder entender cómo se usan los tipos también es necesario saber sobre los tipos (solo en el caso de Pascal)


Tipos.

En pascal es simple declarar tipos. Para hacerlo, debemos de hacer uso de la palabra reservada "Type"
Tomemos cómo ejemplo el código que sigue.

program Tipos;
type
    Colores = string;
    DiasDeLaSemana = string;
    Numeros = integer;
    
var
    MiColor : Colores;
    Hoy : DiasDeLaSemana;
    Fecha : Numeros;
    
begin

    MiColor := 'Verde';
    Hoy := 'Sabado';
    Fecha := 24;

    writeln (MiColor);
    writeln (Hoy);
    writeln (Fecha);

end.

Con lo anterior, habremos creado tres nuevos tipos, el tipo "Colores", el tipo "DiasDeLaSemana" y el tipo "Numeros", a su vez cada uno hereda del tipo "string", "string" e "integer" respectivamente. Para poder usar cada nuevo tipo creado, simplemente creamos variables y les asignamos el tipo que acabamos de crear, en el caso del ejemplo anterior tenemos: "MiColor", "Hoy" y "Fecha" cada una de los tipos que acabamos de declarar.

A simple vista no parece tener mucho chiste, ¿por qué no usar "MiColor" directamente con el tipo "string" o "Fecha" con el tipo "integer"?, la respuesta es simple, el poder declarar tipos "propios" nos da la posibilidad de manejar nuestro código mejor, pero no solo eso, algunas variables cómo los registros "record" son mas fáciles de manejar así, pero además es un requisito necesario para poder trabajar con arreglos de punteros.

Punteros.

En ciencias de la computación, un puntero es un objeto del lenguaje de programación, cuyo valor se refiere a (o "apunta a") otro valor almacenado en otra parte de la memoria del ordenador utilizando su dirección. Un puntero referencia a una ubicación en memoria, y a la obtención del valor almacenado en esa ubicación se la conoce como desreferenciación del puntero. A modo de analogía, un número de página en el índice de un libro podría considerarse un puntero a la página correspondiente; desreferenciar un puntero sería como ir a la página con el número de página especificada en el índice wikipedia/Punteros


En pascal, primero debemos de crear un tipo, este a su vez será un puntero de cualquiera de los admitidos por Pascal precedido por "^". Si queremos declarar un puntero hacia un valor "integer", debemos de hacer una declaración cómo la que sigue:

type
    PointToInt = ^integer;
Con eso habremos creado un nuevo tipo llamado "PointToInt" que es un puntero hacia el tipo "integer", al igual que cualquier tipo que hayamos creado, para usarlo, simplemente debemos de crear una nueva variable del tipo "PointToInt" (en este caso)

program Pointers;
type
    PointToInt = ^integer;
var
    MiNumero : PointToInt;
begin
    new(MiNumero);
    MiNumero^ := 20;
    writeln (MiNumero^);
    Dispose(MiNumero);
end.

Para poder utilizar la variable, además de declarar la  variable con el nuevo tipo, debemos de inicializarla (reservar memoria), esto lo logramos con el procedimiento "new()" que recibe cómo parámetro la variable que queremos usar. Una vez que se inicializo, para poder acceder a los valores, debemos de escribir el nombre de la variable seguido por "^". Cuando terminamos de usar cualquier variable creada de esta forma, debemos de liberar la memoria que usamos (dependiendo del sistema operativo, en la mayoría de los casos cuando cerramos el programa, se liberan en automático los recursos, pero siempre es una buena idea hacerlo por nuestra cuenta) para poder hacerlo, hacemos uso del procedimiento "dispose()" que recibe cómo parámetro el nombre de la función.

Algunos dirán que no es necesario crear un tipo para cada puntero, pero creo que más sencillo hacerlo, así si queremos crear más punteros bastará con mandar a llamar al tipo.

Arreglos.

Los arreglos son colecciones de variables del mismo tipo, se pueden crear de cualquier tipo soportado por Pascal. Al igual que los punteros, se pueden declarar definiendo un tipo. Para hacerlo, debemos de hacerlo declarando al tipo como "array[] of algo", Dentro de los corchetes, debemos de introducir el rango en el cual el arreglo desde índice mas bajo, seguido de ".." y finalmente el índice mas alto, para el tipo "algo", puede ser cualquiera de los que soporta Pascal. Un ejemplo de una declaración de un arreglo es el siguiente:

type
ArregloDeNumeros = array[0..99] of integer;
Con lo anterior habremos creado un nuevo tipo llamado "ArregloDeNumeros", que posee 100 espacios desde 0 hasta 99 y cada uno de ellos será del tipo "integer". Para poder utilizar el arreglo, bastará con crear una variable y asignarle el tipo que recién acabamos de crear. Para inicializar el arreglo, bastará con asignarle valores a cada elemento. La forma más sencilla de hacerlo es mediante un ciclo "for" con el siguiente código:

program Arreglos;

type
ArregloDeNumeros = array[0..99] of integer;

var
MisNumeros : ArregloDeNumeros;
i : integer;

begin

    for i := 1 to 99 do
    begin 
        MisNumeros[i] := i * 2;
    end;
    
    for i := 1 to 99 do
    begin 
        writeln(MisNumeros[i]);
    end;
    
end.

Ahora un ejemplo con arreglos del tipo "string":

program Arreglos;
uses
	sysutils;
type
	ArregloDeNumeros = array[0..99] of integer;
	ArregloDePalabras = array[0..99] of string;
var
	MisPalabras : ArregloDePalabras;
	MisNumeros : ArregloDeNumeros;
	i : integer;
begin
	for i := 0 to 99 do
	begin 
		MisNumeros[i] := i * 2;
		MisPalabras[i] := concat('EL valor de i es ', IntToStr(i));
	end;
	for i := 0 to 99 do
	begin 

	end;
end.

Para acceder a cada valor dentro del arreglo; una vez que ya ha sido inicializado, simplemente escribimos el nombre de la variable, seguido de corchetes ([]) y dentro de estos escribiremos el valor del elemento, en este caso si po ejemplo queremos saber el valor del elemento con índice 90 tendríamos

		writeln(MisNumeros[90]);
		writeln(MisPalabras[90]);

Y bien, por ahora es todo, pero aun queda pendiente una parte importante que hace que el programa del triangulo de pascal funcione y para eso necesitamos saber de arreglos dinámicos en este post solamente vimos como usar los estáticos, pero además necesitamos saber cómo funciona u arreglo de punteros, pero eso será en el siguiente post. Recuerda que puedes probar los códigos en el compilador online.

Los leo luego.

Vamos a programar #93 - El triangulo de pascal (ver. Pascal)

 Hola de nuevo el día de hoy vamos a continuar con mas del triangulo de Pascal, pero esta vez en el lenguaje de programación pascal.



Para entender un poco sobre el triangulo de pascal, recuerda que en el post "Vamos a programar #91" podemos encontrar cómo se calcula a mano y el código en Python. Ahora veamos el código en Pascal que sirve para calcular el triangulo de Pascal.





Lo primero que hacemos es declarar variables globales. Seguido. creamos dos tipos, el tipo "Values" que a su vez es del tipo "array of integer" y el segundo tipo llamado "PValues" que es un puntero a "Values" (en el siguiente post detallaremos algunas cosas sobre los tipo y los punteros).

Después creamos dos funciones. La primera función es "CalculateLevel" y cómo su nombre sugiere sirve para calcular los valores del nivel actual, recibe un parametro del tipo "integer" que sirve para indicar el numero de nivel a calcular, esta regresa un valor del tipo "PValues"

La siguiente función es "DrawPascalTriangle" que cómo su nombre lo indica sirve para dibujar el triangulo. Recibe un parámetro del tipo "integer" que sirve para indicar el numero de niveles que el triangulo tendrá. Para hacerlo, simplemente recorre de uno al número de niveles y a su vez por cada nivel, recorrerá todos los valores que el resultado de "CalculateLevel" contenga.

SI habrás notado, el código en C y el código en Pascal son bastante diferentes al de Python; esto se debe a un par de razones. La primera de ellas es que el código en Python está administrado por el propio interprete, en el caso de C y Pascal; en estos ejemplos, no es así ya que usamos punteros.

Y bien por ahora es todo, cómo de costumbre, puedes descargar el código de mi dropbox para que lo pruebes o en el código hay un botón de ejecutar que te llevará a la versión en línea (donde se puede ejecutar). Pero antes debo de hacer énfasis en cómo es que pascal maneja el tipo "integer". Por default cuando compilamos código, se usaran 16 bits para los enteros, cómo estos tienen signo, los valores permitidos estarán en el rango de -32,768 a 32,767 (por eso está limitado a 18 niveles en el compilador online). Podemos cambiar las directivas para que se usen 32 bits, pero eso será en otro post. Por ahora recomiendo la versión en línea.

Los leo luego.

Bienvenido el 2021

 Hola de nuevo a todos, el dia de hoy solo escribo para desearles a todos un buen año 2021, es cierto que el 2020 fue un año complicado, pero si nos sirve de consuelo a todos, el 2021 podrá ser peor (o no). Cómo es costumbre, continua visitando el blog de XWork y disfrutemos del tiempo que tenemos porque en un instante se puede acabar.


Saludos y nos seguimos leyendo.

Vamos a programar #92 - El triangulo de Pascal (ver. C)

 Hola de nuevo a todos, el día de hoy vamos a ver cómo hacer un programa en C que calcule el triangulo de Pascal.


Cómo podrás recordar, hace unos día publiqué una version en Python; y tal cómo lo prometí justo antes de acabar el 2020, les traigo la versión en C. Cómo la explicación de que es el triangulo de Pascal se incluye en ese post (además de cómo hacer los cálculos a mano), simplemente pasaremos al código fuente. Al igual que el código en Python, vamos a calcular el triangulo de Pascal de manera recursiva y si surgen dudas las resolveremos en los próximos post

El código en C que sirve para calcular el triangulo de Pascal es el siguiente ():


// Prueba del triangulo de pascal en C

#include <stdio.h>
#include <stdlib.h>

int *CalculateLevel(int Level)
{
    int *Result;
    Result  = (int *)malloc(Level * sizeof(int));
        
    if (Level == 0)
         *Result = 1;
    if (Level == 1)
    {
        *Result = 1;
        *(Result + 1) = 1;
    }
    if (Level > 1)
    {
        int *ResultP = CalculateLevel(Level - 1);
        for (int i = 0; i < Level; i++)
        {
            if (i == 0 || i == Level - 1)
                *(Result + i) = 1;
            else
                *(Result + i) = *(ResultP + i) + *(ResultP + i - 1);
        }
    }
    return(Result);
    
}

void DrawPascalTriangle(int Number)
{

    if (Number > 20)
    {
        printf("Solo se admiten 20 niveles");
    }
    else
    {
        for (int i = 0; i < (Number + 1); i++)
        {
            int *Result = CalculateLevel(i);
            for (int j = 0; j < i; j++)
            {
                printf( " %5d ", *(Result + j));
            }
        printf("\n");
        }

    }
}


int main()
{
    int Levels;
    printf("Numero de niveles\n");
    scanf("%d", &Levels);
    DrawPascalTriangle(Levels);

    return 0;
}



Y bien, cómo podrás notar, resulta un poco sencillo portar programas de un lenguaje a otro, si tienes dudas de cómo funciona el programa puedes escribir aquí o en mi twitter. Cómo de costumbre puedes descargar el código fuente de mi Dropbox para que lo pruebes, pero ademas puedes verlo funcionar en linea gracias a los compiladores web.

Los leo luego.

Vamos a programar #91 - EL triangulo de Pascal (ver. Python)

 Hola de nuevo a todos, el día de hoy vamos a ver cómo hacer el triangulo de pascal usando Python.




Hace unos días mientras leía los comentarios, alguien sugirió que hiciera un programa que calculara el triangulo de pascal y ya que ando un poco corto de ideas, decidí hacerlo. Pero antes de continuar, veamos que es el triangulo de pascal.

En las matemáticas, el triángulo de Pascal es una representación de los coeficientes binomiales ordenados en forma de triángulo. Es llamado así en honor al filósofo y matemático francés Blaise Pascal, quien introdujo esta notación en 1654, en su Traité du triangle arithmétique.1​ Si bien las propiedades y aplicaciones del triángulo fueron conocidas con anterioridad al tratado de Pascal por matemáticos indios, chinos, persas, alemanes e italianos, fue Pascal quien desarrolló muchas de sus aplicaciones y el primero en organizar la información de manera conjunta.2​


El triángulo de Pascal se puede generalizar a dimensiones mayores. La versión de tres dimensiones se llama pirámide de Pascal o tetraedro de Pascal, mientras que las versiones más generales son llamadas simplex de Pascal.

Wikipedia/Triangulo De Pascal

 La composición del triangulo de pascal es realmente simple, en la cima del triangulo, siempre ubicaremos un uno, de hecho en todas las orillas pondremos un uno de modo que en cada nivel haya tantos número cómo el nivel en el que estamos. Para el nivel dos, ya que solo hay extremos en ambos se pondrá un uno.

Para calcular los números del tercer nivel, imaginemos que tenemos tres lugares, los extremos deben de llevar el número uno, por lo que solo nos hace falta determinar el que esta en el lugar dos. Para hacerlo de manera "sencilla" debemos de revisar el nivel anterior y debemos de sumar el numero que esta en la misma posición que el numero que queremos saber (DEL NIVEL ANTERIOR), y sumarlo con el que inmediatamente antes. Para darnos una idea, miremos la siguiente imagen.


Si revisamos bien, nos ubicamos en el nivel tres, pero el numero que queremos saber es el que esta en el segundo lugar del tercer nivel (marcado con una X), entonces tenemos que tomar el numero del nivel anterior que esta en las misma posición que nuestro numero, en la imagen podemos apreciar que el número que esta en la segunda posición del nivel dos es uno y el numero que esta antes en el nivel dos, también es uno, por lo que tendríamos que el segundo numero del tercer nivel es igual a uno mas uno, por lo tanto su valor es dos.


Ahora a manera de ejemplo calculemos el valor de los números en el nivel 4, para eso imaginemos que tenemos algo cómo la imagen que sigue.


Solo tendríamos que determinar X y Y. Para X ya que está en la posición dos del cuarto nivel, tomaríamos los números en la posición dos y uno del tercer nivel y tendríamos cómo resultado 3




Para calcular el numero Y, simplemente hacemos lo mismo. Tomamos el tercer y segundo número del nivel tres y simplemente lo sumamos obteniendo otro tres.


Así podemos calcular cualquier nivel.


Entonces en python podemos crear código cómo el que sigue:


# Prueba del triangulo de pascal en python
def CalculateLevel(Level):
    Result = {}
    if Level == 1:
        Result[0] = 1
    if Level == 2:
        Result[0] = 1
        Result[1] = 1
    if Level > 2:
        ResultP = CalculateLevel(Level - 1)
        for i in range(Level):
            if (i == 0) or (i == Level - 1):
                Result[i] = 1
            else:
                Result[i] = ResultP[i - 1] + ResultP[i]
    return Result
 
def DrawPascalTriangle(Number):
    if Number > 20:
        print("Solo se admiten 20 Niveles")
    else:
        for i in range(Number + 1):
            Result = CalculateLevel(i)
            for j in range(len(Result)):
                print(Result[j], end = '  ')
            print()
    


if __name__ == "__main__":
    import sys
    DrawPascalTriangle(int(sys.argv[1]));


El código consta de dos funciones, la primera de ellas es "CalculateLevel(Level)" y cómo su nombre lo sugiere, calcula los valores para el nivel actual, recibe un parámetro numérico que indica cual es el nivel que queremos calcular. En el algoritmo anterior, vimos que cuando el triangulo consta de un nivel, el valor es uno por lo que creamos una condición y si el nivel solicitado es uno, en un arreglo agregamos un valor de uno. Si la variable "Level" es dos, hacemos lo mismo, solo que agregamos otro valor de uno. Para cuando el valor es mayor que dos, lo primero que hacemos es llamar de forma recursiva a "CalculateLevel" pero usando cómo parámetro el valor de "Level" menos uno así obtenemos el nivel anterior, después hacemos un iterador para recorrer todos las posiciones del nivel y dentro de el primero hacemos una comparación y si el valor del iterador corresponde al primer o al ultimo elemento le asignamos el valor de uno, en caso contrario hacemos los calculo usando el valor del iterador para asignar el valor a la posición actual usando los valores del nivel anterior (cómo explicamos antes). Finalmente devolvemos el valor de la variable "Result" que es donde almacenamos los valores

Después creamos la función "DrawPascalTriangle(Number)" que sirve para "dibujar" el triangulo, ya que la consola suele ser pequeña, si el parámetro "Number" es mayor a 20 escribimos un mensaje diciendo que solo se admiten 20 niveles en caso contrario, hacemos dos iteradores, uno que va a recorrer de uno hasta el nivel dado y a su vez calculará cada nivel y el otro que imprimirá en pantalla todos los valores en cada nivel.

Cómo podrás ver el código es realmente sencillo, para usarlo, simplemente debes de ejecutarlo desde la consola pasando cómo parámetro el valor del nivel hasta el cual quieres calcular
pascaltri.py 20
Y bien por ahora es todo, cómo de costumbre puedes descargar el código de mi dropbox para que lo pruebes antes de que acabe el año voy a publicar las versiones en pascal, en c y probablemente en C# o Javascript.

Los leo luego.

Vamos a programar #90 - La sucesión de Fibonacci y la función de Ackerman (ver. Python)

 Hola de nuevo a toos, el dia de hoy vamos a ver un poco de Python. En días anteriores, mientras revisaba algunos comentarios en twitter, aalgunas personas me preguntaron sobre el estado del blog, pese al que el estado actual ha empeorado un poco debido a cierto bicho, el hecho fue que un par de "accidentes" me impidieron crear nuevos post. Pero dejando eso de lado, mucha gente pidio que si les podia ayudar con python (si hacemos memoria, casi no hay programas hechos en éste lenguaje), y la razon principal es debido a que simplemente lo olvide (conste que ya lo habia mencionado en algun post). Para probar que aun estoy al pendiente, decidi hacer un par de programas con (segun google) las busquedas mas gfrecuentes relacionadas a python que conducian a mi blog.



Los números de Fibonacci.

La version en C del los número de fibonacci la puedes encontrar en el siguiente post. Además incluye una pequeña anotación sobre que es. Ambas versiones son similares y sirven para hacer énfasis en cómo es posivble traducir de un lenguaje a otro cuando se trata de programas simples.
El programa en pyton que calcula la sucesión de Fibonacci es el siguiente.

def CalcFibonacci(Number):
    v1 = 0
    v2 = 1
    v3 = 0
    
    while v1 < Number:
        print(v1)
        v3 = v1 + v2
        v1 = v2
        v2 = v3


if __name__ == "__main__":
    import sys
    CalcFibonacci(int(sys.argv[1]))

Cómo podrás observar, el código es realmente sencillo y mucho mas practico que la versión que C ya que no hay que compilarlo cada vez. Para ejecutarlo, solamente deberás de ejecutarlo desde una consola escribiendo el nombre del script seguido del parámetro (que será el número hasta donde queremos llegar)

Fibonacci.py 200

La funcion de Ackerman.

La versión en C de la función de Ackerman la podemos encontrar en el siguiente post. Al igual que la sucesión, incluye una pequeña descripción. El programa en pyton que calcula la función de Ackerman es el siguiente
def AckermanFunction(Number1, Number2):
    if Number1 == 0:
        return Number2 + 1
    else:
        if Number2 == 0:
            return (AckermanFunction(Number1 - 1, 1))
        return (AckermanFunction(Number1 - 1, AckermanFunction(Number1, Number2 - 1)))

if __name__ == "__main__":
    import sys
    try:
        for i in range(4):
            for j in range(5):
                print(AckermanFunction(i, j),end='  ')
            print()
    except RecursionError:
        print("Error: Se alcanzo el maximo de recursion permitido")
Para la implementación en Python use de forma recursiva la función "AckermanFunction"  para demostrar que algunas veces es mas conveniente usar o no otro lenguaje, en este caso python ofrece protección para las llamadas recursivas, si por ejemplo en los ciclos "for" en cada rango usamos 10 y 5 por ejemplo, el programa nos dirá que se alcanzo el máximo de recursión permitida (cosa que en c no ocurre).

Y bien, por ahora es todo, en post siguientes continuaremos con mas de Python, pero al igual que todos los programas aquí hechos, no son con la intención de que la gente que sepa programar aprenda (excepto Pascal). El código fuente para la sucesión de fibonacci la puedes descargar de aqui y el código fuente de la funcion de Ackerman la puedes descargar de acá.

Los leo luego.