# Programas, algoritmos e notebooks

Executar scripts e células, seguir um algoritmo e reconhecer erros de estado.

Página: https://resumos.rgo.pt/cadeiras/ct-iadp/ambiente/

Um programa transforma uma entrada numa saída através de instruções. Para analisar vendas, a entrada pode ser um ficheiro CSV. A saída pode ser a faturação por loja. Antes de escrever código, diz que dados existem, qual é a pergunta e como vais conferir o resultado.

## Um algoritmo antes do código

Queremos a média de três quantidades: 2, 4 e 6. Somamos as quantidades e dividimos pelo número de observações. O resultado esperado é 4. Este procedimento é um **algoritmo**, uma sequência finita de passos para resolver um problema.

Escrever `2 + 4 + 6 / 3` não traduz esse algoritmo, porque a divisão acontece antes das somas. Precisamos de agrupar a soma:

```python
quantidades = [2, 4, 6]
soma = sum(quantidades)
media = soma / len(quantidades)
print(media)
```

O programa escreve `4.0`. `sum` soma os elementos e `len` conta-os. Ainda não precisamos de saber todos os métodos de listas para seguir este cálculo.

## Uma fórmula traduzida em passos

Para um triângulo, recebemos base e altura na mesma unidade. Multiplicamos ambas e dividimos por dois. Se a base for 6 cm e a altura 4 cm, a área é 12 cm quadrados.

```
ler base e altura
area recebe base vezes altura dividido por dois
escrever area
```

Este **pseudocódigo** descreve os passos sem depender da sintaxe de Python. Num fluxograma, retângulos podem representar cálculos, paralelogramos entradas e saídas, e losangos decisões. Depois de definir os passos, escolhemos nomes e escrevemos o programa. Este é o mesmo tipo de problema usado nos materiais de introdução da turma; os valores aqui permitem conferir a fórmula à mão.

## Script, consola e notebook

Um **script** é um ficheiro de código, normalmente com extensão `.py`. Python executa-o de cima para baixo. A consola interativa permite experimentar uma instrução de cada vez. Um notebook `.ipynb` junta células de código, texto e resultados.

No Spyder, escreve o programa no editor e executa o ficheiro. A consola mostra o resultado e o explorador de variáveis ajuda a observar o estado. Confirma que o Python selecionado tem as bibliotecas de que o programa precisa. Instalar uma biblioteca noutro ambiente não a torna disponível nesse intérprete.

No Jupyter, seleciona uma célula de código e usa `Shift+Enter` para a executar e avançar. Uma célula Markdown explica o raciocínio; não executa Python. O número junto da célula indica a ordem de execução, que pode ser diferente da ordem visual.

| Ambiente | O que executas | Onde aparece o resultado |
| --- | --- | --- |
| Consola | Uma expressão ou instrução | Na própria consola |
| Spyder | Um script ou seleção | Na consola IPython |
| Jupyter | Uma célula | Por baixo da célula |
| Blocos destas páginas | O programa completo do bloco | No painel Resultado |

Os blocos destas páginas executam no navegador. Cada execução começa num ambiente descartável. Uma variável criada num bloco não fica disponível no seguinte. Os exemplos importam as suas bibliotecas e criam os seus dados.

## Estado escondido num notebook

Imagina estas duas células:

```
# Célula 1
preco = 5
```

```
# Célula 2
print(preco * 2)
```

Se executares a célula 2 primeiro num kernel novo, recebes `NameError`. Se já existia `preco = 7` de uma experiência anterior, a célula 2 escreve 14. O texto do notebook pode parecer correto, mas a saída depende de algo que já não está visível.

Antes de entregar ou estudar a resolução, reinicia o kernel e executa todas as células por ordem. Os dados iniciais, imports e cálculos devem chegar ao mesmo resultado sem intervenção manual. Guarda o notebook depois desta verificação.

## Ler uma mensagem de erro

Começa pela última linha do traceback, que indica o tipo de erro e a causa. Depois procura a linha do teu código onde aconteceu.

| Erro | Exemplo | O que conferir |
| --- | --- | --- |
| `SyntaxError` | `if x > 0` sem dois pontos | Sintaxe da instrução |
| `IndentationError` | Bloco sem indentação | Alinhamento do bloco |
| `NameError` | Usar `total` antes de o definir | Nome e ordem das instruções |
| `TypeError` | `"3" + 2` | Tipo dos operandos |
| `ValueError` | `int("três")` | Valor que tentaste converter |
| `IndexError` | Lista com três elementos, índice 3 | Limites dos índices |
| `KeyError` | Coluna inexistente | Chave ou rótulo usado |

Uma saída errada sem erro também é um problema. Calcula um caso pequeno à mão, escreve os valores intermédios e encontra o primeiro passo em que divergem.

## Preparar análise de dados

Para as aulas, usa o ambiente indicado pelo docente, incluindo a versão das bibliotecas. Num ambiente local de Python com Jupyter instalado, este comando abre os notebooks na pasta atual:

```
jupyter notebook
```

Dentro de uma célula, confere as versões:

```
import sys
import numpy as np
import pandas as pd
import matplotlib

print(sys.version)
print(np.__version__, pd.__version__, matplotlib.__version__)
```

`pandas` e NumPy manipulam os dados; Matplotlib desenha gráficos. Esta separação permite conferir a tabela que deu origem à figura. Não aceites um gráfico apenas porque parece plausível.
