Computer Science › Fundamentos da Ciência da Computação
Os quatro pilares do pensamento computacional (decomposição, reconhecimento de padrões, abstração e design de algoritmos) e por que eles são uma forma de pensar, não uma forma de programar.
Quebrar um problema em uma sequência ordenada de passos inequívocos antes de escrever qualquer linha de código real, usando um exemplo de robô num mundo-grade de brinquedo para separar o pensamento algorítmico da sintaxe.
Nomear um espaço de memória para guardar um valor, e os tipos primitivos (int, float, bool, str) a partir dos quais todo programa é construído.
Por que a representação binária de ponto flutuante torna a maioria das frações decimais inexata, e como comparar floats com tolerância em vez de igualdade exata.
Combinar valores e operadores em expressões, e a diferença entre a igualdade matemática e o 'armazene o resultado aqui' da atribuição.
Como um programa escolhe entre dois ou mais futuros possíveis com `if`, `elif` e `else`, e por que a ordem das condições numa cadeia determina qual ramo de fato é alcançado.
A diferença entre `for` sobre uma sequência conhecida e `while` até uma condição mudar, e como um invariante de laço prova que um laço computa a resposta certa para toda entrada, não só a testada.
Medir empiricamente o desempenho de um programa com um cronômetro e com um contador de operações, e por que nenhum dos dois, sozinho, prevê o que acontece numa entrada dez vezes maior.
Como descrever o crescimento do tempo de execução de um algoritmo conforme a entrada cresce, ignorando deliberadamente constantes de máquina, e como ler a taxa de crescimento certa diretamente na estrutura do código.
O que torna uma lista diferente de todo valor estudado até aqui: ela é mutável, e essa única propriedade muda o que um programa pode assumir sobre um valor guardado numa variável.
Onde Big-O deixa de ser notação abstrata: por que ordenações quadráticas simples e o merge sort dividir-e-conquistar divergem drasticamente conforme a entrada cresce, mesmo resolvendo o mesmo problema.
Como uma tabela hash permite buscar um valor por chave em tempo aproximadamente constante, e quando esse acesso associativo é a ferramenta certa em vez do acesso posicional de uma lista.
Um tipo sequência que se comporta quase como uma lista, mas do outro lado da linha da imutabilidade: por que essa restrição é uma garantia valiosa, não uma lista com menos recursos.
O que a atribuição realmente faz com um objeto mutável, quando duas variáveis passam a compartilhar a mesma lista e como quebrar esse compartilhamento com uma clonagem deliberada.
Como uma função separa sua interface (o que entra, o que sai) da sua implementação (como o resultado é de fato produzido), tornando isso o primeiro mecanismo concreto de decomposição e abstração deste currículo.
Como uma função que chama a si mesma numa versão estritamente menor do mesmo problema resolve corretamente, através da pilha de chamadas, um caso base e o salto de fé recursivo.
Generalizando recursão de 'um número chegando a zero' para 'uma estrutura chegando à sua instância mais simples', aplicada a strings e listas aninhadas de profundidade arbitrária.
Por que uma suíte de testes que passa nunca é uma prova geral de corretude, e como a depuração sistemática localiza um bug dividindo o pipeline pela metade, aplicando a mesma ideia de bisseção à estrutura do programa.
A diferença entre lidar com uma falha externa esperada e documentar um invariante interno de que o próprio código depende, e por que confundir os dois é uma fonte comum de bugs difíceis de explicar.
A assinatura de uma função como um contrato: como argumentos posicionais e nomeados se vinculam a parâmetros, o que `None` implícito realmente significa, e por que confundir `print` com `return` é um dos bugs iniciais mais comuns.
Como o modelo de dados do Python trata uma função criada com `def` como um objeto comum, permitindo que funções sejam armazenadas, passadas como argumento e retornadas exatamente como qualquer outro valor.
Resolver equações sem solução em forma fechada por aproximação sucessiva, e por que explorar a ordem do espaço de busca com bisseção elimina metade dos candidatos a cada passo em vez de testá-los um a um.
Ler um valor digitado pelo usuário e imprimir um resultado de volta: o menor loop de feedback possível que um programa pode ter.
Part of the Computer Science curriculum.
Os quatro pilares do pensamento computacional (decomposição, reconhecimento de padrões, abstração e design de algoritmos) e por que eles são uma forma de pensar, não uma forma de programar.
Quebrar um problema em uma sequência ordenada de passos inequívocos antes de escrever qualquer linha de código real, usando um exemplo de robô num mundo-grade de brinquedo para separar o pensamento algorítmico da sintaxe.
Nomear um espaço de memória para guardar um valor, e os tipos primitivos (int, float, bool, str) a partir dos quais todo programa é construído.
Por que a representação binária de ponto flutuante torna a maioria das frações decimais inexata, e como comparar floats com tolerância em vez de igualdade exata.
Combinar valores e operadores em expressões, e a diferença entre a igualdade matemática e o 'armazene o resultado aqui' da atribuição.
Como um programa escolhe entre dois ou mais futuros possíveis com `if`, `elif` e `else`, e por que a ordem das condições numa cadeia determina qual ramo de fato é alcançado.
A diferença entre `for` sobre uma sequência conhecida e `while` até uma condição mudar, e como um invariante de laço prova que um laço computa a resposta certa para toda entrada, não só a testada.
Medir empiricamente o desempenho de um programa com um cronômetro e com um contador de operações, e por que nenhum dos dois, sozinho, prevê o que acontece numa entrada dez vezes maior.
Como descrever o crescimento do tempo de execução de um algoritmo conforme a entrada cresce, ignorando deliberadamente constantes de máquina, e como ler a taxa de crescimento certa diretamente na estrutura do código.
O que torna uma lista diferente de todo valor estudado até aqui: ela é mutável, e essa única propriedade muda o que um programa pode assumir sobre um valor guardado numa variável.
Onde Big-O deixa de ser notação abstrata: por que ordenações quadráticas simples e o merge sort dividir-e-conquistar divergem drasticamente conforme a entrada cresce, mesmo resolvendo o mesmo problema.
Como uma tabela hash permite buscar um valor por chave em tempo aproximadamente constante, e quando esse acesso associativo é a ferramenta certa em vez do acesso posicional de uma lista.
Um tipo sequência que se comporta quase como uma lista, mas do outro lado da linha da imutabilidade: por que essa restrição é uma garantia valiosa, não uma lista com menos recursos.
O que a atribuição realmente faz com um objeto mutável, quando duas variáveis passam a compartilhar a mesma lista e como quebrar esse compartilhamento com uma clonagem deliberada.
Como uma função separa sua interface (o que entra, o que sai) da sua implementação (como o resultado é de fato produzido), tornando isso o primeiro mecanismo concreto de decomposição e abstração deste currículo.
Como uma função que chama a si mesma numa versão estritamente menor do mesmo problema resolve corretamente, através da pilha de chamadas, um caso base e o salto de fé recursivo.
Generalizando recursão de 'um número chegando a zero' para 'uma estrutura chegando à sua instância mais simples', aplicada a strings e listas aninhadas de profundidade arbitrária.
Por que uma suíte de testes que passa nunca é uma prova geral de corretude, e como a depuração sistemática localiza um bug dividindo o pipeline pela metade, aplicando a mesma ideia de bisseção à estrutura do programa.
A diferença entre lidar com uma falha externa esperada e documentar um invariante interno de que o próprio código depende, e por que confundir os dois é uma fonte comum de bugs difíceis de explicar.
A assinatura de uma função como um contrato: como argumentos posicionais e nomeados se vinculam a parâmetros, o que `None` implícito realmente significa, e por que confundir `print` com `return` é um dos bugs iniciais mais comuns.
Como o modelo de dados do Python trata uma função criada com `def` como um objeto comum, permitindo que funções sejam armazenadas, passadas como argumento e retornadas exatamente como qualquer outro valor.
Resolver equações sem solução em forma fechada por aproximação sucessiva, e por que explorar a ordem do espaço de busca com bisseção elimina metade dos candidatos a cada passo em vez de testá-los um a um.
Ler um valor digitado pelo usuário e imprimir um resultado de volta: o menor loop de feedback possível que um programa pode ter.