Sumas con beepers en GvR

En este artículo vamos a plantear un ejercicio avanzado para GvR. Pero comencemos por el principio porque seguramente te estés preguntado ¿qué es GvR?

GvR son las iniciales de Guido van Robot (http://gvr.sourceforge.net), un entorno para introducir a los más jóvenes en los fundamentos de la programación y además un simpático guiño a Guido van Rossum (autor de Python).

Para instalar GvR en Windows lo más sencillo es que descargues y descomprimas el paquete standalone (https://sourceforge.net/projects/gvr/files/GvR%20GTK/4.4/GvRng-4.4_win32_standalone.zip/) que incluye todo lo necesario para empezar a utilizarlo sin necesidad de instalar nada más.

Al abrir GvR nos encontraremos con una interfaz muy simple dividida en dos paneles laterales. El de la derecha, con dos pestañas, nos dará acceso al “Code Editor” donde introduciremos las instrucciones para controlar el robot y al “World Editor” con las instrucciones para recrear el mapa.

En el panel de la izquierda tenemos tres pestañas de las cuales la más interesante es la primera “Guido’s World” la cuál nos mostrará una recreación visual del mapa y el robot.

Representación visual del mapa en GvR

Como podemos ver en la imagen los elementos que componen un mapa de GvR son muy básicos:

  • Por un lado tenemos al propio robot en forma de triángulo con una G en medio, el vértice del triángulo nos indica hacia donde está mirando.
  • Además del robot tenemos las paredes representadas con líneas rojas. Si chocamos con una pared nuestro robot se detendrá inmediatamente y tendremos que empezar de nuevo.
  • Por último tenemos los beepers (esos círculos azules). El robot puede recoger los beepers y guardarlos en su mochila y también puede soltarlos siempre y cuando tenga alguno guardado. Los beepers pueden apilarse, es decir, pueden soltarse varios en la misma casilla, en cuyo caso dentro del círculo azul se mostrará cuantos beepers hay apilados.

El propio lenguaje en sí es a su vez muy simple contando con tan solo un puñado de instrucciones, puedes consultar la referencia aquí (http://gvr.sourceforge.net/documents/languageRef/gvr.html).

De hecho el lenguaje es tan simple que ni siquiera tenemos variables en las que almacenar información o tipos de datos (Integers, Strings, etc.) y es esta limitante la que me motivó a escribir el ejercicio que veremos a continuación.

El ejercicio propuesto consiste en sumar números de varios dígitos con cada dígito representado mediante beepers apilados.

En la imagen superior podemos ver un mapa de GvR para este ejercicio simulando la siguiente suma:

8 0 7 1 0 +

3 3 5 1 6 +

7 0 8 2 0 +

1 5 1 1 1

Sin poder convertir los beepers a Integers, sin operadores aritméticos que faciliten los cálculos y sin variables en las que almacenar información de estado (posición del robot, acarreo, cálculos intermedios, etc.) parece una tarea ardua pero a veces, en la vida real, el dispositivo para el que estemos programando no tiene tanta memoria como nos gustaría.

En este ejercicio nuestros estudiantes tendrán que estrujarse el cerebro y usar el pensamiento lateral para descubrir por sí mismos el compromiso RAM-CPU, a menudo si no queremos o podemos consumir más memoria podemos suplirlo con un exceso de ciclos de procesador.

Empezaremos creando una librería de movimientos para nuestro robot. Si has revisado la documentación del lenguaje te habrás dado cuenta de que aunque existe una función para girar a la izquierda, no existe otra para girar a la derecha. Esto no es un problema y forma parte de los retos que plantea GvR para que los estudiantes aprendan desde el principio a resolver problemas más complejos con herramientas muy simples. En este caso para girar a la derecha simplemente tendremos que girar 3 veces a la izquierda, creemos una función para ello. Igualmente ya hemos visto que chocar con una pared hará que nuestro programa se detenga inmediatamente así que antes de avanzar siempre nos interesará comprobar si hay una pared delante o no, creemos otra función para ello. Así, con funciones simples pero útiles podemos crear una sencilla librería que nos facilite el control de nuestro robot.

Ahora que podemos controlar nuestro robot de forma sencilla vamos a atacar el ejercicio. Cuando aprendemos a sumar de pequeños lo hacemos en dos pasos, primero con sumas sencillas donde la suma de dígitos en una columna no es mayor de 9 y por lo tanto no hay acarreo. Después pasamos a sumas más complejas donde los dígitos ya sí suman más de 9 y tenemos que hacer un acarreo (“llevarnos una” a la siguiente columna). Nosotros lo haremos igual, primero veremos como resolver sumas sencillas y después veremos como nos peleamos con el acarreo.

Resolver una suma sencilla en este escenario es muy fácil gracias al apilado de beepers. Lo único que tenemos que hacer es ponernos encima de una columna y descender por ella recogiendo todos los beepers, al llegar abajo los soltamos todos resultando en la suma de los dígitos y pasamos a la siguiente columna.

Ejemplo de suma sencilla (sin acarreos)

Resultado de la suma

Ahora probemos a resolver una suma con acarreo pero sin calcular el acarreo, el resultado sería el siguiente:

Ejemplo de suma con acarreo, las casillas vacías representan un 0

Resultado de la suma, sin calcular el acarreo

La problemática que encontramos ahora es, con las limitaciones del lenguaje, cómo detectamos para cada casilla si hay acarreo o no y en caso positivo cuántas nos “tenemos que llevar”.

Bien, lo primero que haremos será recorrer las casillas de derecha a izquierda ya que el acarreo siempre realiza hacia la izquierda. Para cada casilla tenemos que saber si hay al menos 10 beepers. Con una variable que pusiésemos usar de contador sería muy fácil, pero sin ella no nos queda más remedio que sacrificar algo de CPU e intentar coger 9 beepers (aunque haya menos en la casilla, pero no podemos saberlo de antemano). Cuidado, intentar coger un beeper cuando no hay ninguno en la casilla hará que nuestro programa se detenga así que tendremos que usar nuestra librería de control donde habremos creado una función que antes de coger un beeper compruebe si hay alguno.

Si tras “intentar” coger 9 beepers no queda ninguno en la casilla entonces es que en esa casilla no hay al menos 10 beepers y por lo tanto no hay acarreo. Soltamos todos los beepers para dejar la casilla como estaba y pasamos a la siguiente de la izquierda.

Por otro lado si tras “intentar” coger 9 beepers queda alguno en la casilla entonces es que la casilla hay al menos 10 beepers y debemos proceder con el acarreo. Para ello cogemos 1 más (sólo habíamos cogido 9), nos movemos a la casilla de la izquierda y soltamos 1 (al haber quitado 10 nos llevamos 1), ahora nos quedan 9 beepers en la mochila de los que nos tenemos que deshacer. Es necesario que vaciemos la mochila ya que de lo contrario cuando volvamos a coger beepers de una casilla para comprobar si hay acarreo, en caso de que no lo haya y tengamos que soltar todos los beepers para dejar la casilla como estaba estaremos soltando 9 beepers de más.

Para vaciar la mochila volvemos al punto de partida (base), a la derecha del todo y soltamos todos los beepers. Una vez tenemos la mochila vacía lo ideal sería volver a la casilla que estábamos calculando antes pero sin variables no tenemos forma de almacenar la posición, así que no nos queda más remedio que sacrificar CPU de nuevo y volver a calcular todos los acarreos desde el principio, si bien puesto que ya hemos quitado 10 beepers de una casilla, ya nos queda un acarreo menos que calcular.

Reducir los acarreos por oleadas también nos garantiza que en caso de que en una casilla no solo haya más de 10 beepers sino más de 20, 30, etc, estos acarreos también se calculen correctamente.

Resultado de la suma con el acarreo calculado

Quizá lo último que nos queda por aclarar es cómo saber cuándo estamos en la base, al comienzo de una columna para empezar a “barrer” beepers hacia abajo o cuándo hemos llegado al final de la suma. Para poder sabe en que punto estamos no apoyamos en las paredes. Cuando toquemos la pared de arriba sabremos que estamos al comienzo de una columna, cuando toquemos la pared de la izquierda sabremos que hemos llegado al final de la suma y si bajamos abajo del todo y nos desplazamos a la derecha hasta que toquemos una pared entonces habremos llegado a la base. De esta manera si queremos sumar más cantidad de números o números más largos (con más dígitos) simplemente tendremos que mover la pared de arriba más arriba y la de la derecha más a la derecha.

Y con esto llegamos al final de nuestro ejercicio y del post. Espero que os haya gustado y os permita inspirar a vuestros alumnos para que vayan más allá de los límites aparentes. Tenéis todo el código a vuestra disposición mi repositorio (https://gitlab.com/kaisec/GvR_Lessons).

0 comentarios

Dejar un comentario

¿Quieres unirte a la conversación?
Siéntete libre de contribuir

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *