Se eu perguntar a primeira coisa que passa pela sua cabeça quando você pensa em “tecnologias modernas”, as respostas entre todos os leitores serão bem diferentes entre si, com certeza: robôs autônomos, assistentes eletrônicas, realidade virtual, os cenários estranhos e exagerados de Black Mirror, a exploração espacial de Star Wars (ou até a família “moderna” dos Jetsons, se sua idade permitir). Por mais que esses exemplos todos sejam bem diferentes em si, eles se unem em um ponto.

Em todos eles, estamos querendo dizer a máquinas como elas devem agir. Mesmo que não seja você diretamente, alguém teve de dizer a uma assistente virtual como agir para descobrir se aquele restaurante abre aos domingos ou não. De forma bem resumida (mas não menos verdadeira), podemos dizer que programar é a arte de dizer a um computador o que você quer que ele faça (ou o mais perto do que você quer possível). E pra organizar isso, precisamos de algoritmos.

A base de um algoritmo, por exemplo, que vai ser programado em um computador, é ter uma sequência de passos que deve ser realizada em uma determinada ordem para alcançar um certo objetivo. Ou seja, um algoritmo não é um código de programação já pronto ou um circuito integrado presente em um chip de um aparelho eletrônico. O algoritmo é a sequência lógica dos passos, independente onde eles estejam sendo executados.

Você mesmo pode executar algoritmos. Aliás, esse termo é bem mais antigo que a própria computação, porque a matemática tem vários algoritmos muito importantes que você, inclusive, aprendeu nos primeiros anos da escola. Lembra como somar dois números? Somar as unidades, aí se der mais que 10, você “sobe um” e depois vai somar as dezenas e por aí vaí? Não importa quais números você deseja somar, os passos que você vai executar e a ordem deles é sempre a mesma! Subtração, multiplicação, fatoração, ou mesmo resolver a Torre de Hanói ou certos tabuleiros de Sudoku: você mesmo pode executar algoritmos pra realizar tudo isso.

Fonte da imagem: TutorialsPoint

Fonte da imagem: TutorialsPoint

Saindo da escola, nós executamos algoritmos diariamente. Se deixarmos alguns detalhes mais rígidos de lado, ótimos exemplos são receitas! Eu, pelo menos, toda vez que sigo certinho a receita de bolo de banana da minha mãe, ele fica delicioso. Mas faz todo o sentido pela nossa definição: você prepara a massa em vários passos, depois unta a forma, coloca pra assar, espera um pouco, abre pra ver, se ainda tiver cru, deixa mais um pouco… É uma forma metódica de pensar, mas muito útil algumas vezes.

Exatamente pelo fato de um código de programação ser diferente do algoritmo em si, é que nós temos várias representações pra uma sequência de passos. Pessoas que estão começando a programar agora se familiarizam rápido com duas delas. Uma delas é o fluxograma, uma espécie de gráfico visual representando o fluxo dos passos, onde ele se divide de acordo com o resultado de um passo intermediário e por aí vai ― várias profissões, e não só programadores, utilizam fluxogramas pela facilidade de entender o que está acontecendo em cada etapa.

Fonte da imagem: Fluxograma.net

Fonte da imagem: Fluxograma.net

Outra forma é o que a gente chama de pseudocódigo, essa mais perto da computação: é como se estivéssemos programando em uma linguagem mais “aberta”, ou seja, sem as restrições técnicas, mas seguindo certas regras mais básicas e puras da programação.

Claro que temos alguns algoritmos bem mais simples e outros algoritmos mais complexos. Às vezes, até pra mesma coisa: nesse texto que eu fiz sobre algoritmos de ordenação, eu mostro diferentes formas de ordenar números em um computador e como elas têm diferenças grandes, mesmo que sirvam pra mesma coisa. É possível dividir algoritmos em grupos a partir de como eles são construídos e como funcionam.

Um exemplo seria tentar ordenar várias fichas em ordem alfabética. Se eu fizer isso sozinho, como já dissemos, existem várias e várias formas de fazer isso… Mas e se eu tiver que fazer isso com um amigo meu, ao mesmo tempo? Algoritmos desses são utilizados muito em computação paralela, uma área na qual é preciso encontrar formas eficientes de fazer uma tarefa muito grande ser executada por vários processadores ao mesmo tempo.

Outro exemplo pode dar um nó na cabeça, mas é bem legal pois tem a ver com recursão, a ideia de executar várias vezes um processo semelhante no próprio resultado dele. Lembra aqueles GIFs hipnóticos que ficam entrando dentro deles mesmos, tipo esse? É, existem algoritmos que podem fazer isso!

Fonte da imagem: Penjee

Fonte da imagem: Penjee

É como se, por exemplo, estivéssemos pensando em um algoritmo para abrir matryoshkas, as “bonecas russas” (aquelas que tem uma parecida dentro, mas menor). Eu poderia dizer que, para isso, é só você continuar abrindo a boneca enquanto ainda houver alguma delas para abrir ― quando consideramos esse tipo de repetição, estamos fazendo um algoritmo iterativo, ou seja, que depende de várias iterações/execuções de alguns passos para terminar. Outra forma seria falar para abrir a boneca e, caso você encontra outra, comece o processo de novo. E caso aconteça de novo, comece de novo! Essa seria a ideia de um algoritmo recursivo.

Para terminar o nosso papo sobre algoritmos, falta falar sobre uma coisa: nós estamos falando muito sobre as sequências de passos, mas não sobre os passos em si! Um dos motivos de existirem tantas formas diferentes, ou seja, vários algoritmos para realizar a mesma tarefa, vem do nível de abstração que você pode colocar em cada um dos passos.

Lembra quando eu falei sobre o algoritmo de soma agora pouco? Se você já terminou o Ensino Fundamental, pelo menos, você deve estar muito familiarizado em como somar dois números; então, eu posso simplesmente falar para você somar 23 + 67 e, bom, só isso vai ser o suficiente ― inclusive, eu poderia colocar essa “instrução” como um dos passos de outro algoritmo maior e mais complexo. Agora, se você é uma criança que ainda está no ensino básico, fazer isso não é tão simples assim: eu vou precisar não só explicar como funciona, mas explicar com passos mais simples.

E quando falamos de programação, quebrar tarefas complexas em várias tarefas menores e mais simples é essencial (por mais que elas não pareçam complexas para a visão humana). Em um outro texto, sobre o poder da abstração na ciência da computação, eu cheguei a comentar como a tecnologia que a gente conhece hoje é composta por várias camadas que se comunicam. Quanto mais acima você está, mais fácil é de um ser humano entender o que acontece, mas quanto mais você se aproxima da máquina em si, as etapas são quebradas em pedaços cada vez menores e precisamos de mais esforço pra entender o que todas elas significam.

Fonte da imagem: ResearchGate

Fonte da imagem: ResearchGate

Como um exemplo, vamos pensar em uma instrução, em um programa de computador, que deve somar três números que estejam na memória RAM e colocar em outro espaço da memória o resultado. Em linguagens de alto nível, como são geralmente as que usamos diariamente pra programar, isso seria feito em uma linha. Simples e fácil. Mas não é isso que o processador vai executar de verdade; na real, seria algo parecido com essa lista de passos:

(nota: um registrador é o lugar de armazenamento de valores mais próximo do seu processador, usado para realizar armazenar temporariamente dados que precisam ser usados ao executar instruções)

  1. Copie o primeiro valor da memória e coloque-o no registrador A
  2. Copie o segundo valor da memória e coloque-o no registrador B
  3. Some A e B, colocando o resultado em A
  4. Copie o terceiro valor da memória e coloque-o no registrador B
  5. Some A e B, colocando o resultado em A
  6. Copie o valor do registrador A no lugar onde deveria estar o resultado na memória

Uma única linha tornam-se seis quando começamos a pensar em passos mais simples e, de verdade, é isso o que acontece! Um dos maiores desafios de um programador não é aprender simplesmente a escrever um código capaz de que o computador entenda, mas, sim, encontrar o melhor algoritmo que aquele sistema consegue realizar para o seu objetivo.

A verdade é que isso é bem divertido e por mais que você possa ler e estudar sobre problemas famosos, que trazem consigo soluções muito inteligentes para lidar com uma série de situações (como as ordenações), saber como fazer isso vem da prática, resolvendo problemas simples ou complexos. É como se fosse um exercício de organização, um quebra-cabeça em que você tem que achar a melhor solução para resolver o seu problema.

No final das contas, algoritmos são como receitas de bolo que o seu computador pode entender, mas que você já aprende e executa desde pequeno ― mas o seu papel de cozinheiro é usar a sua criatividade e lógica para descobrir quais ingredientes usar e em qual ordem você tem que misturar na tigela. Vai por mim, a alegria de fazer um bom bolo e ver seu código funcionar são igualmente incríveis…

Fonte da imagem: Moley

Fonte da imagem: Moley