Lógica de programação com Labirintos

 

💻🧙💻

Aprendendo lógica de programação com labirintos 2D

Recentemente um amigo me pediu ajuda com suas aulas de lógica na faculdade (acredito que ele esteja fazendo tecnólogo em Analise de Sistemas ou algo nesta linha).

Esse meu amigo chama-se Vinicius, mas todos (do nosso círculo de amizades em comum) o conhecem como Vinão (se você imaginar o Vinão como uma versão nerd e introvertida do Detona Ralph,vai ser possível fazer uma boa imagem de como ele é).

Enfim, quando o Vinão me pediu ajuda, eu fiquei preocupado, porque eu nunca dei aulas de lógica ou de programação. Por outro lado, há quase vinte anos eu cheguei a dar aulas de informática básica (Windows e pacote Office) por um tempo e por isso tenho lá os meus truques para ensinar conceitos relacionados a esse vasto campo chamado T.I. (Tecnologia da Informação). Nesta época eu descobri que gosta de ensinar mais do que eu imaginava. Então é claro que eu aceitei ajudar o Vinão.

Mas, antes de começar a ajudar o meu amigo, fui investigar por onde seria melhor começar a ensinar lógica de programação e encontrei um artigo bem completo sobre isso (na minha opinião esse artigo resume os pontos principais sobre o tema). Sendo assim, não vou repetir aqui o que é dito lá (deixo o link para quem estiver interessado).

Ao invés de repetir o conteúdo que está muito bem explicado lá (e que recomendo muito), vou listar os tópicos abordados por este artigo, os quais definem como se pode dividir essa matéria chamada "Lógica de Programação". Vou resumir também o que se vê em cada tópico e por último, explicar qual estratégia vou usar para ajudar o Vinão a se exercitar na criação de algoritmos de uma forma simples.

Os pontos principais para estudar lógica de programação são:

Algoritmos: uma forma de descrever uma atividade qualquer dividindo-a em um conjunto de instruções;

Conceitos e regras básicas de programação: no caso, toda linguagem de programação possui regras e conceitos similares e, entendendo esses conceitos, é possível aprender mais facilmente qualquer linguagem de programação;

Matemática: a matemática é a base para o entendimento da lógica;

Linguagem de Programação Inicial: por fim, após compreender e treinar as áreas anteriores resolvendo exercícios que ensinam seus conceitos, é possível começar a estudar alguma linguagem de programação inicial;


Mas hoje eu não vou falar sobre todos esses itens. Irei me focar apenas no primeiro: Algoritmos.

Então, me sentindo um professor de Hogwarts ensinando uma das bases fundamentais do lado negro da força, começo a explicar para meus alunos (estes aspirantes à bruxos dos bits) que a realidade é uma ilusão, o universo é um holograma, compre ouro e fim da aula... Não! Talvez eu tenha me empolgado um pouco...

Vamos lá... Que tal assim? Toda tecnologia suficientemente avançada é indistinguível da mágica... Não, assim também não...

Bom, acho melhor eu focar no conceito em si. Algoritmos; o elemento fundamental da alquimia cibernética.

Ser capaz de criar algoritmos eficientes é importantíssimo para se tornar um bom programador (e por conseguinte, ser capaz de criar coisas legais como a SkyNet, a Matrix, programar um robo de companhia chamado Sony ou talvez Hall 9000).

Mas antes de entender o porque disso (da importância dos algoritmos), é preciso entender primeiro o que é um algoritmo e depois o que é um algoritmo eficiente.

Em primeiro lugar, no estudo da matemática chama-se algoritmo uma "Sequência finita de instruções não ambíguas utilizadas para resolver um problema ou fazer um cálculo".

Em informática (ou seja, Tecnologia da Informação ou T.I.), algoritmo é o nome que se dá para um "Conjunto de regras e operações bem definidas e não ambíguas, que, aplicadas a um conjunto de dados e num número finito de etapas, conduzem à solução de um problema".

Mas em T.I. costumamos usar como analogia para exemplificar o que é um algoritmo o bom e velho exemplo da "receita de bolo". Uma receita de bolo é um algoritmo, pois descreve um conjunto de instruções sobre como se deve fazer um bolo.

Sendo assim, podemos imaginar o cozinheiro como um robô que deve executar as operações necessárias para preparar um bolo. A receita é o algoritmo que o robô consulta para saber o que deve fazer, quando e em que ordem deve fazer. Os ingredientes para preparar o bolo são os recursos disponíveis.

Neste sentido, uma receita de bolo eficiente é aquela que permite ao cozinheiro fazer um bolo no menor tempo possível e disperdiçando a menor quantidade possível de insumos (como ingredientes, água, energia, etc) e tempo.

Para exemplificar como uma receita pode ser mais eficiente que outra, vou listar duas sequencias de instruções abaixo (uma lista chamaremos de receita A, e a outra de receita B), sendo uma mais eficiente que a outra. Além disso, sabemos que na vida real cada cozinheiro leva um tempo diferente para realizar cada uma das instruções de uma receita. Porém, para o nosso exemplo vou descrever o tempo que o nosso hipotético cozinheiro leva para realizar cada instrução (podemos imaginar o Bender, de Futurama, cozinhando algo para sua tribulação), de modo que no final saibamos o tempo total que levará para as instruções serem concluídas. Mas um alerta, os tempos devem ser somados de forma arbitrária (pois algumas tarefas podem ser realizadas paralelamente a outras).

Também é importante dizer que algumas atividades podem ser feitas paralelamente a outras, enquanto que outras só podem ser realizadas após o término de outras que dependam das atividades anteriores (parece complexo, mas para quem tem alguma familiaridade com a cozinha, a coisa é mais simples do que esse texto faz parecer).


Receita A

(tempo para concluir: 1 minuto)-> separe uma caneca com 250 mls de água;

(tempo para concluir: 1 minuto)-> Ensaboe o garfo com detergente;

(tempo para concluir: 1 minuto)-> Ensaboe o prato com detergente;

(tempo para concluir: 1 minuto)-> Enchague o prato e o garfo com a caneca com 250 ml de água ao mesmo tempo;

( tempo para concluir: 1 minuto )-> Encha uma panela com 1,5 litros de água;

( tempo para concluir: 20 segundos )-> Ligue o fogo;

( tempo para concluir: 10 minutos )-> Coloque a panela no fogo e deixe aquecendo por 10 minutos (enquanto isso, vá adiantando as próximas instruções);

( tempo para concluir: 2 minutos )-> Quebre três ovos em um prato;

( tempo para concluir: 1 minuto )-> Misture 4 colheres de farinha de trigo no prato com os ovos;

( tempo para concluir: 6 minuto )-> Bata os ovos com a farinha de trigo por 6 minutos;

( tempo para concluir: 10 segundos )-> Após 10 minutos, coloque a mistura de farinha e ovos na panela com água quente;

ETC.

TEMPO TOTAL: 15 minutos e 30 segundos.


Receita B

(tempo para concluir: 1 minuto)-> separe uma caneca com 250 mls de água;

(tempo para concluir: 1 minuto)-> Ensaboe o garfo com detergente;

(tempo para concluir: 1 minuto)-> Enchague o garfo com a caneca com 250 ml de água;

(tempo para concluir: 1 minuto)-> separe uma caneca com 250 mls de água;

(tempo para concluir: 1 minuto)-> Ensaboe o prato com detergente;

(tempo para concluir: 1 minuto)-> Enchague o prato com a caneca com 250 ml de água;

( tempo para concluir: 2 minutos )-> Quebre três ovos em um prato;

( tempo para concluir: 1 minuto )-> Misture 4 colheres de farinha de trigo no prato com os ovos;

( tempo para concluir: 6 minuto )-> Bata os ovos com a farinha de trigo por 6 minutos;

( tempo para concluir: 1 minuto )-> Encha uma panela com 1,5 litros de água;

( tempo para concluir: 20 segundos )-> Ligue o fogo;

( tempo para concluir: 10 minutos )-> Coloque a panela no fogo e deixe aquecendo por 10 minutos ;

( tempo para concluir: 10 segundos )-> Após 10 minutos, coloque a mistura de farinha e ovos na panela com água quente;

ETC.

TEMPO TOTAL: 26 minutos e 30 segundos


No caso, esses trechos de receita são inventados para este exemplo (e não possuem nenhuma serventia culinária). Mas ambos demonstram a diferença de eficiencia em instruções que se destinam a obter um mesmo resultado.

Na receita A, as instruções estão em uma ordem que permite que parte das instruções sejam realizadas enquanto a água na panela está esquentando no fogo. Isso faz com que 10 minutos sejam economizados para a conclusão dessas instruções.

Na receita B as instruções estão em uma ordem diferente, fazendo com que apenas após preparar a mistura de ovos batidos com farinho de trigo a água seja aquecida por 10 minutos. De modo que é preciso aguardar os 10 minutos para colocar a mistura de farinha com ovos na água quente.

Como é possível constatar, basta uma pequena mudança na ordem de um algoritmo para aumentar muito o tempo que o mesmo leva para ser concluído.

Tempo é um recurso valioso e o principal alvo de quem tenta escrever um algoritmo eficiente.

Mas não é o único. As primeiras instruções da Receita A permitem economizar 2 minutos e 250 ml de água se compararmos com a Receita B, pois a ordem que o enxague é feito, permite que a mesma água seja usada para tirar o sabão do garfo e do prato (estamos supondo que 250 ml de água são suficientes para enchaguar ambos os utensílios do exemplo).

Ainda assim, mesmo a Receita A poderia ser melhorada, iniciando as instruções para lavagem e enxague dos utensílios após a panela ser levada ao fogo. Mas como esse é apenas um exemplo, achei melhor deixar como está para poder exemplificar não apenas o que é um algoritmo, mas como podemos analisá-lo em busca de eficiência para economizar recursos.

E já que estamos usando como exemplo de algoritmo uma receita de bolo hipotética (que só existe para esse exemplo), podemos dizer também que um livro de culinária com receitas é um lirvo de algoritmos, visto que ele reune vários conjuntos de instruções que se destinam a cumprir objetivos determinados (que seria a realização de vários pratos culinários).

Em resumo, podemos dizer que tudo o que fazemos pode ser descrito como um algoritmo, uma vez que tudo o que fazemos pode ser descrito na forma de uma lista de instruções.

Como o mundo 3D é mais complexo e perigoso (com fogões, utensílios de cozinha pontiagudos e afiados e coisas imprevistas), resolvi levar o meu amigo para dimensão 2D, onde a beleza da simplicidade linear permite manter as variáveis do nosso estudo dentro de uma margem de conforto e segurança.

Com isso pensei em criar labirintos impressos e desafiar meu amigo a sair de um ponto inicial desses labirintos e ir para um ponto final específico usando algoritmos. Chamei isso de Algoritmos Vs Labirintos.

O exercício consiste em apresentar um labirinto 2D na forma de um tabuleiro impresso em uma folha A4 com um ponto inicial e um ponto final pré-definidos (ambos representados respectivamente por um △ e um ※), um conjunto de instruções limitados (como virar à direita, avançar N casas) e uma lista numerada em branco em que as instruções devem ser escritas com caneta (de modo que não possam ser apagadas).

O desafio parece simples: afinal, basta ir preenchendo a lista com comandos até chegar ao ponto final. Porém, o difícil mesmo não é preencher a lista, e sim preencher a lista de modo a construir um algoritmo o mais eficiente possível. Ou seja, quanto menor a quantidade de linhas necessárias para chegar ao ponto final no labirinto, mais eficiente é o conjunto de instruções.

Como a lista deve ser preenchida a caneta, caso seja usado um comando que leve para o lado errado do labirinto, não será possível apagar e começar de novo. Deve-se completar a tarefa e depois recomeçar do zero (em uma folha nova), com a intenção de fazer um trajeto mais curto do que o anterior.

Aqui está um exemplo de como ficou a folha do exercício (e mais duas variações):

versão 1


versão 2

versão 3

A versão 3 é praticamente um mini-game baseado em lógica. Ainda vou melhorar a ideia. Mas por hora esse já é um exercício bem legal para lógica (e abstração: acho que abstração é fundamental para o desenvolvimento da lógica).

Repito que esta pode parecer uma atividade simples e de fato ela é simples. Mas é nesta simplicidade que está o seu poder de ensinar a prática de elaborar algoritmos eficientes.

Claro que eu irei melhorar este exercício, adicionando mais complexidade, funções utilitárias, comandos e recursos que devem ser usados (e economizados) para que o desafio seja completado.

Talvez o meu eterno apreço por jogos é que tenha me induzido a uma solução desse tipo para ensinar essa matéria.