Dia 10 — Desafios: sintaxe do zero

Informatica · Conteudo · publicado em 02/10/2026
Dia 10 de 13

Desafios: sintaxe do zero

Aula 1

Desafio 1: validar e formatar um cadastro

O que o desafio resolve

Um cadastro chega do formulário como texto cru: espaço sobrando nas pontas, maiúscula misturada com minúscula, um campo que o usuário deixou em branco. Antes de gravar isso em qualquer lugar, três perguntas precisam de resposta: o dado está preenchido, está no formato certo, e está limpo o suficiente para comparar depois.

A ordem importa e é o que separa o código que funciona do que dá erro em produção: validar antes de formatar. Se o trim e o toLowerCase vierem primeiro, o dado ruim vira dado bonito e passa pela validação como se estivesse correto.

O que a página valida é o resultado de validar formulário: o navegador tem a validação dele, e a escrita em JavaScript existe para produzir mensagem no lugar certo, no português da aplicação, e não no do sistema operacional.

As quatro peças

O programa se monta com quatro peças independentes, e nenhuma delas sabe da existência das outras.

Formatação, uma função por transformação. Cada uma devolve valor novo e não altera o texto original.

const semEspaco = (texto) => texto.trim();
const minusculo = (texto) => texto.toLowerCase();

Nome de exibição, que junta as duas e cuida das maiúsculas. O split(/\s+/) é o detalhe: com split(' ') cada espaço vira uma palavra vazia, e "bia carvalho" sai como "Bia Carvalho", com os três espaços intactos no meio.

const nomeDeExibicao = (texto) => {
  const partes = semEspaco(texto).toLowerCase().split(/\s+/);
  return partes
    .map((parte) => parte.charAt(0).toUpperCase() + parte.slice(1))
    .join(' ');
};

Validação, que devolve sempre a mesma forma de objeto — com e sem erro — para quem chama nunca precisar perguntar se o erro veio.

function validar(cadastro) {
  const erros = [];
  // cada regra empurra seu problema e segue
  return { valido: erros.length === 0, erros };
}

Formatação final, o objeto que vai para o banco: já limpo, já minúsculo, idade já convertida para número.

const prontoParaGravar = {
  nome: nomeDeExibicao(cadastro.nome),
  email: minusculo(semEspaco(cadastro.email)),
  idade: Number(semEspaco(cadastro.idade)),
  cidade: semEspaco(cadastro.cidade),
};

Campo obrigatório

Espaço em branco é ausência. Por isso o trim vem antes da comparação, e é '' que decide — não a string crua.

O objeto de cadastro é o que vem do formulário: um objeto com uma chave por campo, o mesmo que a validação recebe e o mesmo que a formatação devolve limpo. O que entra nele é texto; o que sai é número.

for (const campo of ['nome', 'email', 'cidade']) {
  if (semEspaco(cadastro[campo]) === '') {
    erros.push(campo + ': campo obrigatorio');
  }
}

O for sobre a lista de campos evita três blocos idênticos. Quando a regra for diferente para cada campo, o laço não serve e cada um ganha seu if.

O ciclo é o do exercício: a pessoa preenche, o formulário entrega o objeto de cadastro, e a validação roda antes de qualquer gravação. O trim e toLowerCase são o par que devolve o texto limpo.

Cada if empurra o problema na lista e segue em frente: quem cadastrou errou o e-mail e esqueceu a cidade, vê as duas mensagens de uma vez, e não uma por tentativa. O oposto disso é o retorno antecipado — o return que para a função na primeira falha —, que esconde as outras. Ele é a escolha certa quando a regra é "ou o cadastro inteiro passa, ou não passa", e a escolha errada quando a pessoa precisa ver todos os problemas de uma vez.

Formato: e-mail, idade e número

ChecagemCódigoPor quê
um @ sóemail.split('@').length === 2dois @ não formam e-mail
domínio com pontopartes[1].includes('.')ana@localhost não é endereço de verdade
sem espaço no meio/\s/.test(email)espaço é erro de digitação
inteiroNumber.isInteger(Number(texto))"30abc" não é número
na faixanota >= 18 && nota <= 120regra de negócio

A checagem de espaço tem uma sutileza que quebra metade das implementações: se o teste rodar sobre o e-mail já em minúsculo, o resultado é idêntico e o if nunca entra. O que interessa é o espaço no meio, e ele só existe no texto original.

const emailCru = semEspaco(cadastro.email);
const partes = emailCru.split('@');

if (partes.length !== 2 || !partes[1].includes('.') || /\s/.test(emailCru)) {
  erros.push('email: invalido');
}

Number('30abc') devolve NaN em vez de erro, e Number('') devolve 0. A diferença entre NaN e 0 é o que separa "campo vazio" de "campo preenchido com lixo", e o Number.isInteger é o que distingue as duas: Number.isInteger(Number('')) é false, mesmo com a comparação numérica passando.

Para número dentro de faixa, a guarda de NaN tem que vir antes da comparação de faixa: comparar com NaN devolve false nos dois lados, e o else if pode ser tomado como se o número fosse pequeno demais.

Os três erros que aparecem em produção

Validar o que já foi formatado. Com o toLowerCase antes da checagem, o teste de espaço nunca acusa, e o e-mail com espaço no meio vai para o banco.

Devolver duas formas diferentes. A função que devolve { valido: false } no erro e a lista de erros no sucesso obriga todo mundo a checar os dois formatos. Devolva sempre o mesmo objeto.

Formatar antes de validar. O custo é maior que o trabalho jogado fora: nomeDeExibicao('') devolve '', nomeDeExibicao de um número devolve NaN misturado no nome, e o erro aparece no JSON.stringify final, longe da origem.

O alert de validação que o navegador faz sozinho (required, type="email") não substitui a validação em JavaScript: ele protege o envio, não o dado que já chegou, e a mensagem dele está em português do sistema operacional, não no português da sua aplicação. A validação escrita à mão é a que produz mensagem de erro no lugar certo.

Formato de e-mail não se resolve com uma expressão regular só. O que resolve, em código de produção, é uma mensagem de erro boa: o usuário precisa saber o que corrigir, e "email inválido" sem dizer o que falta é o mesmo campo perdido de novo na próxima tentativa.

Exemplo

'use strict';
// ============================================================
// AULA 1 - Desafio 1: validar e formatar um cadastro
//
// O programa inteiro: entra um cadastro com espaços e letras
// misturadas, valida campo por campo, formata o que passou e
// imprime o relatório. Roda do primeiro campo ao último.
// ============================================================

// ------------------ 1. ENTRADA ------------------
// O que chegaria do formulário, cru: espaço sobrando nas pontas,
// maiúscula misturada com minúscula, um campo vazio.
const cadastro = {
  nome: '  ana souza ',
  email: '  [email protected] ',
  idade: '30',
  cidade: '',
};

// ------------------ 2. FORMATO ------------------
// Uma função por transformação. Cada uma devolve um valor novo, e o
// texto original continua intacto se algo der errado no meio do caminho.
const semEspaco = (texto) => texto.trim();
const minusculo = (texto) => texto.toLowerCase();

// Nome de exibição: `trim`, minúsculas, e a inicial de cada palavra em
// maiúscula. O `split(/\s+/)` é o que importa: com `split(' ')` cada
// espaço vira uma palavra vazia e o nome sai com três espaços no meio.
const nomeDeExibicao = (texto) => {
  const partes = semEspaco(texto).toLowerCase().split(/\s+/);
  return partes
    .map((parte) => parte.charAt(0).toUpperCase() + parte.slice(1))
    .join(' ');
};

// ------------------ 3. VALIDAÇÃO ------------------
// Cada `if` empurra o problema na lista e segue em frente, e o resto da
// função não precisa de `else` nem de nivelamento.
// Devolve sempre a mesma forma de objeto: quem chama nunca precisa
// perguntar "e se não vier erro?".
function validar(cadastro) {
  const erros = [];

  // Campo obrigatório. Espaço também é ausência, então o `trim` vem
  // antes da comparação: é `''` que decide, não a string crua.
  for (const campo of ['nome', 'email', 'cidade']) {
    if (semEspaco(cadastro[campo]) === '') {
      erros.push(campo + ': campo obrigatório');
    }
  }

  // E-mail: um arroba, e um domínio com ponto depois dele.
  const emailCru = semEspaco(cadastro.email);
  if (emailCru !== '') {
    const partes = emailCru.split('@');
    if (partes.length !== 2 || !partes[1].includes('.')) {
      erros.push('email: precisa ter um @ e um domínio depois dele');
    }
    // Espaço no MEIO do e-mail é erro de digitação; espaço nas pontas
    // não é, porque o `trim` acima já tirou. Por isso o teste é sobre o
    // texto original, e não sobre a versão em minúsculas.
    if (/\s/.test(emailCru)) {
      erros.push('email: não pode ter espaço');
    }
  }

  // Idade precisa ser número inteiro dentro da faixa.
  const idadeTexto = semEspaco(cadastro.idade);
  const idadeNumero = Number(idadeTexto);
  if (idadeTexto === '' || !Number.isInteger(idadeNumero)) {
    erros.push('idade: precisa ser um número inteiro');
  } else if (idadeNumero < 18 || idadeNumero > 120) {
    erros.push('idade: precisa estar entre 18 e 120');
  }

  return { valido: erros.length === 0, erros };
}

// ------------------ 4. PROCESSAMENTO ------------------
// Formata DEPOIS de validar. O caminho invertido, formatar e só depois
// validar, joga trabalho fora quando o dado está errado.
const resultado = validar(cadastro);

// ------------------ 5. SAÍDA ------------------
console.log('--- ENTRADA (o que chegou do formulário) ---');
console.log('nome  : [' + cadastro.nome + ']');
console.log('email : [' + cadastro.email + ']');
console.log('idade : [' + cadastro.idade + ']');
console.log('cidade: [' + cadastro.cidade + ']');

console.log('\n--- VALIDAÇÃO ---');
if (resultado.valido) {
  console.log('Cadastro válido.');
} else {
  console.log('Cadastro recusado. ' + resultado.erros.length + ' problema(s):');
  // `forEach` em vez de `for`: aqui não existe índice, só a mensagem.
  resultado.erros.forEach((erro, i) => console.log(`  ${i + 1}. ${erro}`));
}

// ------------------ 6. O MESMO CÓDIGO, CADASTRO PREENCHIDO ------------------
const cadastroBom = {
  nome: '  bia   carvalho ',
  email: ' [email protected] ',
  idade: ' 22 ',
  cidade: ' Olinda ',
};
const resultadoBom = validar(cadastroBom);

console.log('\n--- MESMO CÓDIGO, AGORA COM O CADASTRO PREENCHIDO ---');
console.log('validado:', resultadoBom.valido);

if (resultadoBom.valido) {
  // O que vai para o banco: já limpo, já minúsculo, já número.
  const prontoParaGravar = {
    nome: nomeDeExibicao(cadastroBom.nome),
    email: minusculo(semEspaco(cadastroBom.email)),
    idade: Number(semEspaco(cadastroBom.idade)),
    cidade: semEspaco(cadastroBom.cidade),
  };

  console.log('\nnome  digitado : [' + cadastroBom.nome + ']');
  console.log('nome  gravado  : [' + prontoParaGravar.nome + ']');
  console.log('email digitado : [' + cadastroBom.email + ']');
  console.log('email gravado  : [' + prontoParaGravar.email + ']');
  console.log('idade: string virou ' + typeof prontoParaGravar.idade +
    ' -> ' + prontoParaGravar.idade);
  console.log('\nobjeto pronto para o banco:');
  console.log(JSON.stringify(prontoParaGravar, null, 2));
} else {
  console.log(resultadoBom.erros.join('; '));
}

Saída real

--- ENTRADA (o que chegou do formulário) ---
nome  : [  ana souza ]
email : [  [email protected] ]
idade : [30]
cidade: []

--- VALIDAÇÃO ---
Cadastro recusado. 1 problema(s):
  1. cidade: campo obrigatório

--- MESMO CÓDIGO, AGORA COM O CADASTRO PREENCHIDO ---
validado: true

nome  digitado : [  bia   carvalho ]
nome  gravado  : [Bia Carvalho]
email digitado : [ [email protected] ]
email gravado  : [[email protected]]
idade: string virou number -> 22

objeto pronto para o banco:
{
  "nome": "Bia Carvalho",
  "email": "[email protected]",
  "idade": 22,
  "cidade": "Olinda"
}
Aula 2

Desafio 2: manipular uma lista de notas

O que o desafio resolve

Uma lista de notas chega suja: o mesmo aluno-launchado duas vezes por engano, uma nota digitada fora da escala. O relatório que sai dela tem média, maior, menor, aprovados, reprovados e dois tipos de ordenação. A lista inteira é uma, e cada pergunta é um método de array diferente.

O programa é o índice das aulas de array: cada bloco do relatório usa um método que já foi apresentado, e a ordem das etapas — limpar, medir, ordenar, imprimir — é a ordem em que as perguntas devem ser feitas. O relatorio de notas que sai no fim é só a montagem desses blocos na ordem.

Entrada e limpeza

A lista crua é um array de objetos, que é como o dado real chega: de um formulário, de uma consulta, de um arquivo.

const notas = [
  { aluno: 'Ana',    materia: 'Matematica', nota: 8.5 },
  { aluno: 'Bruno',  materia: 'Matematica', nota: 5.0 },
  { aluno: 'Feca',   materia: 'Matematica', nota: 12.0 },  // fora da escala
];

Antes de calcular qualquer coisa, filter tira o que não presta. Notar que a nota inválida sai pela escala (0 a 10), e não pelo critério de aprovação (6): são duas regras diferentes e elas não podem virar a mesma comparação.

RegraCódigoO que remove
dentro da escalanota >= 0 && nota <= 10digitação errada, nota impossível
sem repetiçãofindIndex devolve o índiceo mesmo aluno na mesma matéria duas vezes

A repetição sai com findIndex dentro de filter, e o truque é comparar o índice devolvido com o índice atual: só a primeira ocorrência passa.

const semRepeticao = validas.filter((registro, indice) =>
  validas.findIndex((outro) =>
    outro.aluno === registro.aluno &&
    outro.materia === registro.materia) === indice);

Set faz o mesmo em uma linha — new Set(chaves).size — e Map resolve quando o registro inteiro é o dado a comparar.

Medir: média, maior e menor

A média tem três partes: extrair os números, somar, dividir pelo quantidade. Cada parte tem seu método. Calcular media é o primeiro bloco do relatório de notas, e o resultado — a estatistica do conjunto — vem antes de qualquer texto pronto.

PassoMétodoAssinaturaDevolve
extrairmapnotas.map((r) => r.nota)array só com as notas
somarreducereduce((soma, nota) => soma + nota, 0)um número
dividir—soma / lista.lengtha média
maiorMath.maxMath.max(...notas)o maior valor
menorMath.minMath.min(...notas)o menor valor

O 0 inicial no reduce não é opcional: sem ele, o primeiro elemento é o acumulador, e a soma sai errada quando a lista é vazia ou tem um elemento só.

const soNotas = semRepeticao.map((registro) => registro.nota);
const media = soNotas.reduce((soma, nota) => soma + nota, 0) / soNotas.length;

O Math.max(...notas) é o caminho curto, e o ... é obrigatório: sem ele, Math.max recebe um argumento, que é o array, e devolve NaN. A alternativa é reduce((maior, nota) => Math.max(maior, nota)), que funciona com qualquer tamanho de lista e não tem limite de argumentos.

Aprovado, reprovado e ordenação

Aprovado e reprovado são o mesmo filter com o sinal trocado, e é melhor calcular um e negar do que escrever a regra duas vezes.

As tarefas do relatório — quais entraram, quantas são, o maior e o menor valor, o texto final — saem todos daqui. É o mesmo princípio da aula anterior, com outra pergunta por cima.

const aprovados = semRepeticao.filter((r) => r.nota >= NOTA_MINIMA);
const reprovados = semRepeticao.filter((r) => r.nota < NOTA_MINIMA);
ChamadaEfeito
lista.sort((a, b) => a - b)número, crescente
lista.sort((a, b) => b - a)número, decrescente
lista.sort((a, b) => a.aluno.localeCompare(b.aluno))texto, por ordem alfabética
lista.sort()converte para texto e ordena por string

O sort sem argumento é a pegadinha que aparece em toda prova: "10" < "8" é true, porque a comparação passa a ser caractere a caractere. E o sort mexe na lista original; para preservar, use a cópia antes — [...lista].sort(...).

O localeCompare é o que ordena texto respeitando acentos: "arara".localeCompare("Árvore") põe o á onde o dicionário põe. O < entre strings ignora acento, e a ordem sai errada em qualquer lista com nome português.

Arredondar e a média vazia

toFixed(1) devolve texto, com ponto em vez de vírgula. Serve para imprimir e não para comparar, porque '8.5' > '7' compara caractere a caractere.

const umaCasa = (numero) => Math.round(numero * 10) / 10;   // número
const notaTexto = (numero) => umaCasa(numero).toFixed(1);    // texto, só para imprimir

A divisão por zero não é erro em JavaScript: devolve NaN, e o programa continua rodando como se nada tivesse acontecido. typeof NaN é 'number', o que faz o erro passar despercebido até chegar num gráfico ou numa soma.

ChecagemDevolve
Number.isIntegertrue se não tem casa decimal
Number.isFinitefalse para NaN, Infinity e -Infinity
Number.isNaNtrue só para NaN
x === xfalse quando x é NaN

A guarda vem antes da divisão, e não depois.

const mediaSegura = soNotas.length > 0
  ? soNotas.reduce((soma, nota) => soma + nota, 0) / soNotas.length
  : 0;

Reduzir a lista a um número no fim do reduce é o caminho curto e funciona, mas começa a doer quando o relatório ganha uma segunda métrica. Separar em map e depois reduce custa uma linha a mais e deixa cada número disponível para a próxima pergunta.

A lista original continua com os sete registros depois de todos os filter e sort. Isso não é sorte: filter, map e sort com cópia devolvem array novo, e nenhum deles altera a lista de entrada. O único que altera é o sort chamado direto na lista, e é por isso que a cópia vem antes dele.

Nota guardada como texto quebra o relatório inteiro sem erro nenhum: '10' > '9' é false, a média sai como concatenação ('0' + '8.5' dá '08.5') e o sort ordena por caractere. A conversão precisa acontecer na entrada do dado, e Number.isInteger(Number(valor)) é a forma de garantir que ela aconteceu de verdade.

Exemplo

'use strict';
// ============================================================
// AULA 2 - Desafio 2: manipular uma lista de notas
//
// O relatório inteiro: entra uma lista de notas com uma repetida e
// uma inválida, e sai média, maior, menor, aprovados, reprovados e
// ordenação. Cada etapa usa um método de array diferente, para o
// exemplo servir de índice das aulas de array e de objeto.
// ============================================================

// ------------------ 1. ENTRADA ------------------
// A lista crua, como viria de um cadastro ou de uma planilha:
// um aluno repetido por engano e uma nota fora da escala.
const notas = [
  { aluno: 'Ana', materia: 'Matematica', nota: 8.5 },
  { aluno: 'Bruno', materia: 'Matematica', nota: 5.0 },
  { aluno: 'Carla', materia: 'Matematica', nota: 9.5 },
  { aluno: 'Diego', materia: 'Matematica', nota: 7.0 },
  { aluno: 'Elis', materia: 'Matematica', nota: 10.0 },
  { aluno: 'Ana', materia: 'Matematica', nota: 8.5 },  // repetido
  { aluno: 'Feca', materia: 'Matematica', nota: 12.0 }, // fora da escala
];

const NOTA_MINIMA = 6;      // abaixo disso, reprovado
const NOTA_MAXIMA = 10;     // teto da escala
const ESCALA_MINIMA = 0;    // piso da escala: abaixo disso é digitado errado

console.log('--- ENTRADA ---');
console.log('registros recebidos:', notas.length);

// ------------------ 2. LIMPEZA ------------------
// `filter` tira o que não presta antes de calcular qualquer coisa.
const validas = notas.filter((registro) =>
  registro.nota >= ESCALA_MINIMA && registro.nota <= NOTA_MAXIMA);

// A repetição do mesmo aluno na mesma matéria sai aqui.
const semRepeticao = validas.filter((registro, indice) =>
  validas.findIndex((outro) =>
    outro.aluno === registro.aluno &&
    outro.materia === registro.materia) === indice);

console.log('depois de tirar a nota fora da escala:', validas.length);
console.log('depois de tirar a repetição:', semRepeticao.length);

// ------------------ 3. PROCESSAMENTO ------------------
// Várias respostas, uma pergunta só: como a nota se distribui.

const soNotas = semRepeticao.map((registro) => registro.nota);

const media = soNotas.reduce((soma, nota) => soma + nota, 0) / soNotas.length;
const maior = Math.max(...soNotas);
const menor = Math.min(...soNotas);

const aprovados = semRepeticao.filter((registro) => registro.nota >= NOTA_MINIMA);
const reprovados = semRepeticao.filter((registro) => registro.nota < NOTA_MINIMA);

// O `sort` MEXE na lista que recebe. A cópia com `[...lista]` é o que
// deixa o original intacto. Com `a - b` é número; com
// `a.localeCompare(b)` é texto. Passando só `a`, o JavaScript ordena
// como texto e "10" vem antes de "8".
const porNota = [...semRepeticao].sort((a, b) => b.nota - a.nota);
const porNome = [...semRepeticao].sort((a, b) => a.aluno.localeCompare(b.aluno));

// Uma casa decimal, arredondada no lugar certo.
// `toFixed` devolve TEXTO. Para somar e comparar, o número arredondado
// é este; a string serve só para imprimir alinhado na coluna.
const umaCasa = (numero) => Math.round(numero * 10) / 10;
const notaTexto = (numero) => umaCasa(numero).toFixed(1);

// ------------------ 4. SAÍDA ------------------
console.log('\n--- RELATÓRIO ---');
console.log('alunos considerados :', semRepeticao.length);
console.log('média da turma      :', notaTexto(media));
console.log('maior nota          :', notaTexto(maior));
console.log('menor nota          :', notaTexto(menor));
console.log('aprovados (>= ' + NOTA_MINIMA + ')  :', aprovados.length);
console.log('reprovados (< ' + NOTA_MINIMA + ')  :', reprovados.length);

console.log('\naprovados:');
aprovados.forEach((registro) => {
  console.log(`  ${registro.aluno.padEnd(7)} ${notaTexto(registro.nota)}`);
});

console.log('\nreprovados:');
reprovados.forEach((registro) => {
  console.log(`  ${registro.aluno.padEnd(7)} ${notaTexto(registro.nota)}`);
});

console.log('\nda maior nota para a menor:');
porNota.forEach((registro, i) => {
  console.log(`  ${i + 1}. ${registro.aluno} - ${notaTexto(registro.nota)}`);
});

console.log('\nem ordem alfabética:');
porNome.forEach((registro) => {
  console.log(`  ${registro.aluno}`);
});

// A prova de que o original não foi mexido: 7 registros, não 5.
console.log('\na lista original continua com', notas.length, 'registros');

// ------------------ 5. O MESMO CÓDIGO COM LISTA VAZIA ------------------
// Lista vazia é o caso que quebra a média. Não há exceção: dividir por
// zero em JavaScript devolve `NaN`, e o programa continua rodando como
// se nada tivesse acontecido. Por isso a guarda vem antes da divisão.
console.log('\n--- O QUE ACONTECE COM LISTA VAZIA ---');
const nenhuma = [];
const mediaVazia = nenhuma.reduce((soma, nota) => soma + nota, 0) / nenhuma.length;
console.log('média da lista vazia:', mediaVazia);
console.log('tipo:', typeof mediaVazia, '| Number.isFinite:', Number.isFinite(mediaVazia));

// A guarda que evita o `NaN`: sem lista, a média é zero.
const mediaSegura = nenhuma.length > 0
  ? nenhuma.reduce((soma, nota) => soma + nota, 0) / nenhuma.length
  : 0;
console.log('com a guarda antes da divisão:', mediaSegura);

Saída real

--- ENTRADA ---
registros recebidos: 7
depois de tirar a nota fora da escala: 6
depois de tirar a repetição: 5

--- RELATÓRIO ---
alunos considerados : 5
média da turma      : 8.0
maior nota          : 10.0
menor nota          : 5.0
aprovados (>= 6)  : 4
reprovados (< 6)  : 1

aprovados:
  Ana     8.5
  Carla   9.5
  Diego   7.0
  Elis    10.0

reprovados:
  Bruno   5.0

da maior nota para a menor:
  1. Elis - 10.0
  2. Carla - 9.5
  3. Ana - 8.5
  4. Diego - 7.0
  5. Bruno - 5.0

em ordem alfabética:
  Ana
  Bruno
  Carla
  Diego
  Elis

a lista original continua com 7 registros

--- O QUE ACONTECE COM LISTA VAZIA ---
média da lista vazia: NaN
tipo: number | Number.isFinite: false
com a guarda antes da divisão: 0