Exercícios de lógica de programação: 8 resolvidos
FizzBuzz, fatorial, número primo, palíndromo e mais quatro: enunciado, teste de mesa, solução rodando no Node e o critério para saber que acertou.
Exercício de lógica funciona quando você resolve primeiro o algoritmo, prevê casos e só então traduz. Os oito problemas abaixo têm entrada, critério de acerto, solução executada no Node v26.3.0 e uma variação para impedir memorização.
Para cada desafio, faça três colunas: entrada, passos e saída esperada. Use o teste de mesa nas três primeiras voltas. Se olhar a solução, feche-a e escreva novamente com seus nomes.
1. FizzBuzz: resto e ordem das condições
De um a quinze, múltiplos de três viram Fizz, de cinco viram Buzz e de ambos viram FizzBuzz. O caso de ambos precisa vir primeiro:
function fizzBuzz(limite) {
const saida = [];
for (let n = 1; n <= limite; n += 1) {
if (n % 15 === 0) saida.push('FizzBuzz');
else if (n % 3 === 0) saida.push('Fizz');
else if (n % 5 === 0) saida.push('Buzz');
else saida.push(String(n));
}
return saida;
}
console.log(fizzBuzz(15).join(' '));Critério: 3, 5 e 15 precisam cair em três respostas diferentes. Variação: use 4 e 6 em vez de 3 e 5. Isso força reconstruir o mínimo múltiplo comum, não copiar o quinze.
2. Fatorial com laço e caso zero
Multiplique os inteiros de dois até n. Produto começa em um:
function fatorial(n) {
if (!Number.isInteger(n) || n < 0) throw new RangeError('entrada inválida');
let resultado = 1;
for (let fator = 2; fator <= n; fator += 1) resultado *= fator;
return resultado;
}
console.log(fatorial(0), fatorial(1), fatorial(5));Critério: zero e um devolvem um; negativo é rejeitado. Depois compare com a versão de recursividade e explique qual ocupa pilha crescente.
3. Número primo sem testar até o próprio número
Um primo maior que um não tem divisor até sua raiz quadrada. Conte as tentativas antes e depois do corte:
function contarTestes(n, ateRaiz) {
let testes = 0;
const limite = ateRaiz ? Math.floor(Math.sqrt(n)) : n - 1;
for (let divisor = 2; divisor <= limite; divisor += 1) testes += 1;
return testes;
}
console.log(contarTestes(9999, false));
console.log(contarTestes(9999, true));O plano sugeria 99, mas o código executado conta divisores de 2 até 99: são 98 testes. Critério funcional: 2 e 97 são primos; 1 e 9.999 não. Critério de custo: parar assim que encontrar divisor.
4. Palíndromo depois de normalizar texto
Remova espaços e pontuação, converta para minúsculas e compare com o inverso:
function ehPalindromo(texto) {
const limpo = texto.toLocaleLowerCase('pt-BR').replace(/[^a-záàâãéêíóôõúç0-9]/gi, '');
return limpo === [...limpo].reverse().join('');
}
console.log(ehPalindromo('arara'));
console.log(ehPalindromo('Ame o poema'));
console.log(ehPalindromo('algoritmo'));Critério: caixa e espaço não mudam a resposta. Variação: compare apenas até o meio, sem criar string invertida, e conte comparações.
5. Ordenação por seleção visível
Em cada posição, encontre o menor valor restante e troque. Registre o array depois das três primeiras passagens:
function selecao(valores) {
const lista = [...valores];
for (let inicio = 0; inicio < lista.length - 1; inicio += 1) {
let menor = inicio;
for (let i = inicio + 1; i < lista.length; i += 1) {
if (lista[i] < lista[menor]) menor = i;
}
[lista[inicio], lista[menor]] = [lista[menor], lista[inicio]];
console.log(inicio + 1, [...lista]);
}
return lista;
}
selecao([7, 3, 5, 1]);Esta entrada encontra o mínimo logo na primeira passagem e por acaso termina ordenada; as passagens restantes ainda verificam posições. Critério: saída crescente e entrada original preservada. Variação: teste [4, 3, 2, 1] e conte comparações para relacionar com complexidade.
6. Fibonacci iterativo
Comece com zero e um; cada próximo é soma dos dois anteriores:
function fibonacci(quantidade) {
const sequencia = [];
let anterior = 0;
let atual = 1;
for (let i = 0; i < quantidade; i += 1) {
sequencia.push(anterior);
[anterior, atual] = [atual, anterior + atual];
}
return sequencia;
}
console.log(fibonacci(10));Critério: quantidades zero, um e dez devolvem comprimentos correspondentes. Variação: calcule somente o décimo valor sem guardar a lista inteira.
7. Somar algarismos
Transforme o número em texto, percorra caracteres e converta cada um:
function somarAlgarismos(numero) {
let soma = 0;
for (const caractere of String(Math.abs(numero))) soma += Number(caractere);
return soma;
}
console.log(somarAlgarismos(5831));
console.log(somarAlgarismos(-90));Critério: sinal não entra na soma e zero funciona. Variação: resolva com resto e divisão inteira, sem converter para texto; compare a ordem em que os dígitos aparecem.
8. Encontrar o segundo maior sem ordenar
Mantenha dois acumuladores. Duplicata do maior não deve virar segundo maior:
function segundoMaior(valores) {
let maior = -Infinity;
let segundo = -Infinity;
for (const valor of valores) {
if (valor > maior) {
segundo = maior;
maior = valor;
} else if (valor > segundo && valor < maior) {
segundo = valor;
}
}
return segundo === -Infinity ? null : segundo;
}
console.log(segundoMaior([4, 9, 2, 9, 7]));
console.log(segundoMaior([5, 5]));Critério: duplicatas não contam como valor distinto e lista sem dois valores distintos devolve null. Variação: devolver também os índices das duas primeiras ocorrências.
Rotina de vinte minutos com prova de acerto
Use cinco minutos para pseudocódigo e casos, dez para implementação e cinco para teste de borda e explicação. “Rodou” não é critério; cada exercício acima declara saídas que precisam passar.
Marque em quais blocos você precisou olhar sintaxe. Se a trava foi raciocínio, refaça no papel. Se foi método da linguagem, consulte a trilha de JavaScript sem misturar as duas lacunas.
Crie um caderno de erros com quatro campos: problema, hipótese inicial, primeiro caso que falhou e regra aprendida. Não copie apenas a solução final. O histórico de hipóteses permite reconhecer padrões, como limite inclusivo, acumulador reiniciado e índice ausente.
Na segunda rodada, troque o domínio sem trocar a estrutura. FizzBuzz pode virar calendário de manutenção; busca pode virar localização de pedido; segundo maior pode virar segunda maior nota distinta. Se o algoritmo continua funcionando com nomes novos, você entendeu o padrão e não apenas a história.
Depois imponha uma restrição por vez. Resolva palíndromo sem criar string invertida, Fibonacci sem guardar toda a sequência e segundo maior sem ordenar. Restrições revelam estado necessário, mas só entram depois da versão simples passar nos casos.
Explique a complexidade dominante de cada solução. FizzBuzz e soma de dígitos crescem com entrada percorrida; seleção usa laço aninhado; busca por índice é linear. Não precisa provar formalmente, mas precisa contar voltas para tamanhos pequenos e prever a tendência.
Feche cada sessão escolhendo uma variação para o dia seguinte. O intervalo obriga seu cérebro a reconstruir em vez de reconhecer. Ao voltar, escreva casos antes de abrir o arquivo antigo. Se resolver por outro caminho e ambos passarem, compare clareza, passos e tratamento de borda sem procurar uma única resposta “oficial”.
Depois dos oito, reescreva dois sem olhar e explique a decomposição em funções. Use o guia de lógica para escolher o próximo assunto e mantenha a trilha de Lógica como sequência de revisão.
Perguntas frequentes
Quanto tempo devo tentar antes de olhar a solução?
Preciso resolver os exercícios com a menor quantidade de linhas?
Dúvidas e comentários
Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.
Entrar para perguntarÉ o mesmo login gratuito dos cursos.
Nenhuma dúvida por aqui ainda — a primeira pode ser a sua.
Todo o código deste artigo foi executado em Node v26.3.0, e as saídas exibidas são as reais — como produzimos este conteúdo.
Fontes consultadas
- ECMAScript — Array Objects — tc39.es
- ECMAScript — Math.sqrt — tc39.es


