Lista 04 · std::vector¶
Exercícios da Semana 4 — std::vector.
Como resolver
Copie o bloco de código de cada exercício, cole no seu compilador online, preencha a parte marcada como ESCREVA SUA SOLUCAO AQUI e rode. A saída mostra quais testes passaram.
ex01¶
Escreva soma_vector, que recebe um std::vector<int> (por referência constante) e devolve a soma de todos os elementos.
// ex01 — versao de arquivo unico (gerada automaticamente,
// nao edite este arquivo direto: edite os fontes em exercicios/ e rode
// tools/gerar_single.py --todos de novo).
//
// Cole este arquivo inteiro no seu compilador online e rode.
#include <cassert>
#include <iostream>
#include <vector>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX01_H
#define EX01_H
// Retorna a soma de todos os elementos do vector.
int soma_vector(const std::vector<int>& v);
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
int soma_vector(const std::vector<int>& v) {
// TODO: percorra v somando os elementos.
return 0;
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
assert(soma_vector({1, 2, 3}) == 6);
assert(soma_vector({}) == 0);
assert(soma_vector({-5, 5}) == 0);
assert(soma_vector({10}) == 10);
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex02¶
Escreva maior_elemento, que recebe um std::vector<int> não vazio e devolve o maior valor.
// ex02 — versao de arquivo unico (gerada automaticamente,
// nao edite este arquivo direto: edite os fontes em exercicios/ e rode
// tools/gerar_single.py --todos de novo).
//
// Cole este arquivo inteiro no seu compilador online e rode.
#include <cassert>
#include <iostream>
#include <vector>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX02_H
#define EX02_H
// Retorna o maior elemento do vector (assume que v nao esta vazio).
int maior_elemento(const std::vector<int>& v);
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
int maior_elemento(const std::vector<int>& v) {
// TODO: percorra v guardando o maior valor visto ate agora.
return 0;
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
assert(maior_elemento({3, 9, 1, 7}) == 9);
assert(maior_elemento({-5, -1, -9}) == -1);
assert(maior_elemento({4}) == 4);
assert(maior_elemento({1, 1, 1}) == 1);
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex03¶
Escreva filtra_pares, que recebe um std::vector<int> e devolve um novo vector contendo só os elementos pares, na mesma ordem.
// ex03 — versao de arquivo unico (gerada automaticamente,
// nao edite este arquivo direto: edite os fontes em exercicios/ e rode
// tools/gerar_single.py --todos de novo).
//
// Cole este arquivo inteiro no seu compilador online e rode.
#include <cassert>
#include <iostream>
#include <vector>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX03_H
#define EX03_H
// Retorna um novo vector so com os elementos pares de v, na mesma ordem.
std::vector<int> filtra_pares(const std::vector<int>& v);
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
std::vector<int> filtra_pares(const std::vector<int>& v) {
// TODO: monte um novo vector so com os elementos pares de v (use push_back).
return {};
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
std::vector<int> esperado1 = {2, 4, 6};
assert(filtra_pares({1, 2, 3, 4, 5, 6}) == esperado1);
std::vector<int> esperado2 = {};
assert(filtra_pares({1, 3, 5}) == esperado2);
std::vector<int> esperado3 = {2, 4};
assert(filtra_pares({2, 4}) == esperado3);
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex04¶
Escreva inverte_vector, que recebe um std::vector<int>& e inverte a ordem dos elementos no próprio vector (não use std::reverse — pratique trocando elementos de posição na mão, como fez com string na Lista 01).
// ex04 — versao de arquivo unico (gerada automaticamente,
// nao edite este arquivo direto: edite os fontes em exercicios/ e rode
// tools/gerar_single.py --todos de novo).
//
// Cole este arquivo inteiro no seu compilador online e rode.
#include <cassert>
#include <iostream>
#include <vector>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX04_H
#define EX04_H
// Inverte a ordem dos elementos de v, alterando o proprio vector do chamador.
void inverte_vector(std::vector<int>& v);
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
void inverte_vector(std::vector<int>& v) {
// TODO: troque v[i] com v[v.size()-1-i] para i indo do inicio ate o meio.
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
std::vector<int> a = {1, 2, 3, 4};
inverte_vector(a);
std::vector<int> esperado_a = {4, 3, 2, 1};
assert(a == esperado_a);
std::vector<int> b = {1, 2, 3};
inverte_vector(b);
std::vector<int> esperado_b = {3, 2, 1};
assert(b == esperado_b);
std::vector<int> c = {};
inverte_vector(c);
assert(c.empty());
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex05¶
Escreva soma_matriz, que recebe uma "matriz" (std::vector<std::vector<int>>) e devolve a soma de todos os elementos, de todas as linhas.
// ex05 — versao de arquivo unico (gerada automaticamente,
// nao edite este arquivo direto: edite os fontes em exercicios/ e rode
// tools/gerar_single.py --todos de novo).
//
// Cole este arquivo inteiro no seu compilador online e rode.
#include <cassert>
#include <iostream>
#include <vector>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX05_H
#define EX05_H
// Retorna a soma de todos os elementos da matriz (vector de vector).
int soma_matriz(const std::vector<std::vector<int>>& matriz);
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
int soma_matriz(const std::vector<std::vector<int>>& matriz) {
// TODO: percorra cada linha e, dentro dela, cada elemento, somando tudo.
return 0;
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
assert(soma_matriz({{1, 2}, {3, 4}}) == 10);
assert(soma_matriz({{5}}) == 5);
assert(soma_matriz({}) == 0);
assert(soma_matriz({{1, 1, 1}, {1, 1, 1}}) == 6);
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex06¶
Dada a struct Aluno (campos nome e nota, já declarada), escreva media_turma, que recebe um std::vector<Aluno> não vazio e devolve a média das notas.
// ex06 — versao de arquivo unico (gerada automaticamente,
// nao edite este arquivo direto: edite os fontes em exercicios/ e rode
// tools/gerar_single.py --todos de novo).
//
// Cole este arquivo inteiro no seu compilador online e rode.
#include <cassert>
#include <iostream>
#include <cmath>
#include <string>
#include <vector>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX06_H
#define EX06_H
struct Aluno {
std::string nome;
double nota;
};
// Retorna a media das notas da turma (assume que turma nao esta vazia).
double media_turma(const std::vector<Aluno>& turma);
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
double media_turma(const std::vector<Aluno>& turma) {
// TODO: some as notas de cada Aluno em turma e divida pela quantidade.
return 0.0;
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
std::vector<Aluno> t1 = {{"Ana", 8.0}, {"Bruno", 6.0}};
assert(std::abs((media_turma(t1)) - (7.0)) <= (0.0001));
std::vector<Aluno> t2 = {{"Carla", 10.0}};
assert(std::abs((media_turma(t2)) - (10.0)) <= (0.0001));
std::vector<Aluno> t3 = {{"A", 5.0}, {"B", 5.0}, {"C", 5.0}};
assert(std::abs((media_turma(t3)) - (5.0)) <= (0.0001));
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex07¶
Um pico é um elemento estritamente maior que o anterior e estritamente maior que o seguinte. Escreva conta_picos, que recebe um std::vector<int> e devolve quantos picos ele tem.
O primeiro e o último elemento nunca são picos (falta vizinho de um dos lados), e um vector com menos de três elementos não tem pico nenhum.
conta_picos({1, 3, 2, 5, 4}) // -> 2 (o 3 e o 5)
conta_picos({1, 2, 3}) // -> 0 (o 3 nao tem sucessor)
conta_picos({5, 5, 5}) // -> 0 (precisa ser estritamente maior)
// ex07 — versao de arquivo unico (gerada automaticamente,
// nao edite este arquivo direto: edite os fontes em exercicios/ e rode
// tools/gerar_single.py --todos de novo).
//
// Cole este arquivo inteiro no seu compilador online e rode.
#include <cassert>
#include <iostream>
#include <vector>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX07_H
#define EX07_H
// Retorna quantos elementos sao estritamente maiores que o anterior
// e que o seguinte. Vectors com menos de 3 elementos nao tem picos.
int conta_picos(const std::vector<int>& v);
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
int conta_picos(const std::vector<int>& v) {
// TODO: percorra de i = 1 ate v.size() - 2 (assim i-1 e i+1 sempre existem)
// e conte quantas vezes v[i] > v[i-1] && v[i] > v[i+1].
return 0;
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
assert(conta_picos({1, 3, 2, 5, 4}) == 2);
assert(conta_picos({1, 2, 3}) == 0);
assert(conta_picos({5, 5, 5}) == 0);
assert(conta_picos({3, 1, 2}) == 0);
assert(conta_picos({1, 9, 1}) == 1);
assert(conta_picos({}) == 0);
assert(conta_picos({7}) == 0);
assert(conta_picos({7, 8}) == 0);
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex08¶
Escreva soma_diagonal, que recebe uma matriz quadrada (std::vector<std::vector<int>>) e devolve a soma dos elementos da diagonal principal — aqueles em que o índice da linha é igual ao índice da coluna.
soma_diagonal({{1, 2}, {3, 4}}) // -> 5 (1 + 4)
soma_diagonal({{1, 0, 0}, {0, 2, 0}, {0, 0, 3}}) // -> 6
// ex08 — versao de arquivo unico (gerada automaticamente,
// nao edite este arquivo direto: edite os fontes em exercicios/ e rode
// tools/gerar_single.py --todos de novo).
//
// Cole este arquivo inteiro no seu compilador online e rode.
#include <cassert>
#include <iostream>
#include <vector>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX08_H
#define EX08_H
// Retorna a soma dos elementos da diagonal principal de uma matriz quadrada
// (os elementos em que linha == coluna).
int soma_diagonal(const std::vector<std::vector<int>>& matriz);
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
int soma_diagonal(const std::vector<std::vector<int>>& matriz) {
// TODO: percorra i de 0 ate matriz.size() - 1 e acumule matriz[i][i].
return 0;
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
assert(soma_diagonal({{1, 2}, {3, 4}}) == 5);
assert(soma_diagonal({{1, 0, 0}, {0, 2, 0}, {0, 0, 3}}) == 6);
assert(soma_diagonal({{7}}) == 7);
assert(soma_diagonal({{-1, 5}, {5, -2}}) == -3);
assert(soma_diagonal({}) == 0);
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex09¶
Dada a struct Produto (campos nome, quantidade e preco, já declarada), escreva adiciona_produto, que recebe um std::vector<Produto>& (o inventário), um nome, uma quantidade e um preço:
- se já existir um produto com aquele nome, atualize a quantidade e o preço dele e devolva
false; - se não existir, acrescente um novo
Produtoao fim do vector e devolvatrue.
std::vector<Produto> estoque;
adiciona_produto(estoque, "resistor", 10, 0.25); // -> true (entrou um novo)
adiciona_produto(estoque, "resistor", 40, 0.30); // -> false (so atualizou)
// estoque tem 1 produto, com quantidade 40 e preco 0.30
// ex09 — versao de arquivo unico (gerada automaticamente,
// nao edite este arquivo direto: edite os fontes em exercicios/ e rode
// tools/gerar_single.py --todos de novo).
//
// Cole este arquivo inteiro no seu compilador online e rode.
#include <cassert>
#include <iostream>
#include <cmath>
#include <string>
#include <vector>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX09_H
#define EX09_H
struct Produto {
std::string nome;
int quantidade;
double preco;
};
// Se ja houver um produto com esse nome no inventario, atualiza quantidade e
// preco e retorna false. Caso contrario, acrescenta um novo e retorna true.
bool adiciona_produto(std::vector<Produto>& inventario,
const std::string& nome, int quantidade, double preco);
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
bool adiciona_produto(std::vector<Produto>& inventario,
const std::string& nome, int quantidade, double preco) {
// TODO: procure um produto com esse nome no inventario.
// Se achar, atualize os campos quantidade e preco dele e devolva false.
// Se nao achar, use push_back para acrescentar um Produto novo e devolva true.
return false;
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
std::vector<Produto> estoque;
assert(adiciona_produto(estoque, "resistor", 10, 0.25));
assert(estoque.size() == 1);
assert(estoque[0].quantidade == 10);
assert(!(adiciona_produto(estoque, "resistor", 40, 0.30)));
assert(estoque.size() == 1);
assert(estoque[0].quantidade == 40);
assert(std::abs((estoque[0].preco) - (0.30)) <= (0.0001));
assert(adiciona_produto(estoque, "capacitor", 5, 1.50));
assert(estoque.size() == 2);
assert(estoque[1].nome == std::string("capacitor"));
// O produto que ja existia nao pode ter sido alterado pela insercao do outro.
assert(estoque[0].quantidade == 40);
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex10¶
Escreva eh_ordenado, que devolve true se o vector estiver em ordem crescente. Elementos iguais lado a lado contam como ordenados. Um vector vazio ou com um único elemento está ordenado.
Este é um exercício de lógica: compare cada elemento com o seguinte, e devolva false assim que achar um par fora de ordem. Não use std::is_sorted — as ferramentas de <algorithm> chegam na Lista 08.
Cuidado com o limite do laço: quem percorre até o último elemento e lê v[i + 1] sai do vector.
// ex10 — versao de arquivo unico (gerada automaticamente,
// nao edite este arquivo direto: edite os fontes em exercicios/ e rode
// tools/gerar_single.py --todos de novo).
//
// Cole este arquivo inteiro no seu compilador online e rode.
#include <cassert>
#include <iostream>
#include <vector>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX10_H
#define EX10_H
// Retorna true se v estiver em ordem crescente (elementos iguais lado a
// lado sao aceitos). Um vector vazio ou de um elemento so esta ordenado.
bool eh_ordenado(const std::vector<int>& v);
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
bool eh_ordenado(const std::vector<int>& v) {
// TODO: compare cada elemento com o seguinte. Se achar um par fora de
// ordem, ja pode devolver false. Se o laco terminar, esta ordenado.
return false;
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
assert(eh_ordenado({1, 2, 3}));
assert(eh_ordenado({1, 1, 2}));
assert(!(eh_ordenado({3, 1, 2})));
assert(!(eh_ordenado({1, 2, 0})));
assert(eh_ordenado({7}));
assert(eh_ordenado({}));
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex11¶
Escreva ultima_ocorrencia, que recebe um std::vector<int> (por referência constante) e um valor alvo, e devolve o índice da última ocorrência de alvo no vector, ou -1 se ele não aparecer.
ultima_ocorrencia({5, 7, 5, 2}, 5) // -> 2 (a segunda aparicao do 5)
ultima_ocorrencia({5, 7, 5, 2}, 9) // -> -1
ultima_ocorrencia({}, 5) // -> -1
Dois pontos do capítulo 4 aparecem juntos aqui: o retorno é int, mas o índice de um vector é std::size_t; e a varredura mais direta é de trás para frente, que é exatamente onde um índice std::size_t nunca chega a ser negativo — o laço não termina. Guarde o tamanho num int com static_cast<int> antes do laço, e o problema some.
// ex11 — versao de arquivo unico (gerada automaticamente,
// nao edite este arquivo direto: edite os fontes em exercicios/ e rode
// tools/gerar_single.py --todos de novo).
//
// Cole este arquivo inteiro no seu compilador online e rode.
#include <cassert>
#include <iostream>
#include <vector>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX11_H
#define EX11_H
// Devolve o indice da ultima ocorrencia de alvo em v, ou -1 se nao houver.
int ultima_ocorrencia(const std::vector<int>& v, int alvo);
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
int ultima_ocorrencia(const std::vector<int>& v, int alvo) {
// TODO: guarde o tamanho em int n = static_cast<int>(v.size()) e percorra
// de n - 1 ate 0. Nao use std::size_t no indice: andando para tras ele
// nunca fica negativo, e o laco nao termina.
return -1;
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
assert(ultima_ocorrencia({5, 7, 5, 2}, 5) == 2);
assert(ultima_ocorrencia({5, 7, 5, 2}, 9) == -1);
assert(ultima_ocorrencia({5, 7, 5, 2}, 2) == 3);
assert(ultima_ocorrencia({5, 7, 5, 2}, 7) == 1);
assert(ultima_ocorrencia({}, 5) == -1);
assert(ultima_ocorrencia({4}, 4) == 0);
assert(ultima_ocorrencia({4}, 5) == -1);
assert(ultima_ocorrencia({-1, -1, -1}, -1) == 2);
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex12¶
Escreva aplica_desconto, que recebe um std::vector<double>& de preços e um percentual de desconto (double, com valor padrão 10.0), e reduz cada preço do próprio vector por esse percentual.
Note que o vector chega por referência não constante: a função não devolve nada, ela altera os preços do chamador. É o argumento padrão do capítulo 2 encontrando o vector do capítulo 4.
std::vector<double> precos = {100.0, 50.0};
aplica_desconto(precos); // usa 10% (padrao)
// precos agora e {90.0, 45.0}
aplica_desconto(precos, 50.0); // 50% sobre os novos valores
// precos agora e {45.0, 22.5}
// ex12 — versao de arquivo unico (gerada automaticamente,
// nao edite este arquivo direto: edite os fontes em exercicios/ e rode
// tools/gerar_single.py --todos de novo).
//
// Cole este arquivo inteiro no seu compilador online e rode.
#include <cassert>
#include <iostream>
#include <cmath>
#include <vector>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX12_H
#define EX12_H
// Reduz cada preco de "precos" pelo percentual informado (in-place).
void aplica_desconto(std::vector<double>& precos, double percentual = 10.0);
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
void aplica_desconto(std::vector<double>& precos, double percentual) {
// TODO: para cada preco p em "precos", atualize p para p * (1 - percentual/100).
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
std::vector<double> precos = {100.0, 50.0};
aplica_desconto(precos);
assert(std::abs((precos[0]) - (90.0)) <= (0.0001));
assert(std::abs((precos[1]) - (45.0)) <= (0.0001));
aplica_desconto(precos, 50.0);
assert(std::abs((precos[0]) - (45.0)) <= (0.0001));
assert(std::abs((precos[1]) - (22.5)) <= (0.0001));
std::vector<double> zero = {10.0};
aplica_desconto(zero, 0.0);
assert(std::abs((zero[0]) - (10.0)) <= (0.0001));
std::cout << "Todos os testes passaram!\n";
return 0;
}