Projeto e análise de algoritmos
As habilidades necessárias para projetar e analisar algoritmos estão misturadas com as habilidades necessárias para efetivamente descrever algoritmos.
Uma descrição completa de qualquer algoritmo tem quatro componentes:
- o quê: uma especificação precisa do problema que o algoritmo resolve;
- como: uma descrição precisa do algoritmo;
- por quê: uma prova de que o algoritmo resolve o problema que ele deve resolver;
- quão rápido: uma análise do tempo de execução do algoritmo.
Mesmo assim, apresentá-los nessa ordem é melhor para o leitor.
Recomendo que você tenha como objetivo escrever para um programador competente porém cético e que não é tão esperto quanto você é.
Pense em você mesmo seis meses atrás.
Conforme você cria um novo algoritmo, você naturalmente desenvolve muita
intuição sobre o problema e sobre como seu algoritmo funciona.
Porém qualquer que leia o seu algoritmo depois não vai compartilhar essa
mesma intuição e experiência (nem mesmo você seis meses depois).
Tudo o que eles terão é a sua descrição do algoritmo.
Mesmo que você nunca tenha que explicar os seus algoritmos para mais
ninguém, ainda é importante desenvolvê-los com uma audiência em mente.
Tentar se comunicar claramente força você a pensar mais
claramente.
Escrever para uma audiência de novatos, que vão interpretar suas palavras
exatamente como foram escritas, força você a pensar em detalhes finos.
Escrever para uma audiência cética força você a desenvolver argumentos
robustos para corretude e eficiência, ao invés de apenas confiar na sua
intuição ou inteligência.
O seu trabalho principal enquanto projetista de algoritmos é ensinar outras pessoas como e por quê o seu algoritmo funciona.
Especificando o problema
Antes de conseguirmos desenvolver um novo algoritmo, temos que
concordar sobre qual problema o algoritmo supostamente deve resolver.
Similarmente, antes de descrever um algoritmo, precisamos descrever o
problema que o algoritmo deve resolver.
Os problemas normalmente são apresentados usando alguma linguagem
natural (português, inglês), em termos de objetos do mundo real.
Nós, projetistas de algoritmos, precisamos reformulá-los em termos de
objetos matemáticos formais e abstratos (números, vetores, listas, grafos,
árvores, ...).
A especificação deve incluir detalhes o suficiente para que qualquer
outra pessoa consiga usar nosso algoritmo como caixa preta,
sem saber como ou por quê o algoritmo de fato funciona.
Em particular, precisamos descrever o tipo e o significado de cada
parâmetro de entrada, e como a saída depende deles.
Por outro lado, a especificação precisa deliberadamente esconder detalhes
desnecessários para quem vai usar o algoritmo como caixa preta.
Descrevendo o algoritmo
Algoritmos são representações abstratas de procedimentos que podem ser implementados em qualquer linguagem de programação que suporte as operações primitivas necessárias.
Os detalhes sintáticos idiossincráticos da sua linguagem de programação
favorita são totalmente irrelevantes.
Focar nesses detalhes só vai te distrair do que realmente está acontecendo.
Uma boa descrição de algoritmo deve ser mais próxima do que escrevemos nos comentários de um programa real do que do código em si.
Descrições em linguagem natural também não são uma boa ideia.
Elas estão cheias de ambiguidades e tons de significado.
A forma mais clara de apresentar um algoritmo é usando uma combinação
de pseudocódigo e linguagem natural estruturada.
Assim você consegue revelar a estrutura interna do algoritmo e esconder
detalhes irrelevantes de implementação, tornando o algoritmo mais fácil de
entender, analisar, debugar e implementar.