Lista 06 · map e set¶
Exercícios da Semana 6 — map e set.
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 conta_caracteres, que recebe um texto e devolve um std::map<char, int> com a contagem de cada caractere que aparece.
// 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 <string>
#include <map>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX01_H
#define EX01_H
// Retorna um map com a contagem de cada caractere de texto.
std::map<char, int> conta_caracteres(const std::string& texto);
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
std::map<char, int> conta_caracteres(const std::string& texto) {
// TODO: percorra texto, usando contagem[c]++ para cada caractere c.
std::map<char, int> contagem;
return contagem;
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
std::map<char, int> esperado1 = {{'a', 2}, {'b', 1}};
assert(conta_caracteres("aab") == esperado1);
std::map<char, int> esperado2 = {};
assert(conta_caracteres("") == esperado2);
std::map<char, int> esperado3 = {{'x', 3}};
assert(conta_caracteres("xxx") == esperado3);
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex02¶
Escreva remove_duplicados, que recebe um std::vector<int> e devolve um std::vector<int> sem duplicatas, em ordem crescente. Use um std::set<int> como passo intermediário (ele já remove duplicatas e mantém ordem sozinho).
// 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>
#include <set>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX02_H
#define EX02_H
// Retorna os valores de v sem duplicatas, em ordem crescente.
std::vector<int> remove_duplicados(const std::vector<int>& v);
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
std::vector<int> remove_duplicados(const std::vector<int>& v) {
// TODO: insira todos os elementos de v num std::set<int> (remove duplicatas
// e ordena sozinho), depois monte um vector a partir do set.
return {};
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
std::vector<int> esperado1 = {1, 2, 3};
assert(remove_duplicados({3, 1, 2, 3, 1}) == esperado1);
std::vector<int> esperado2 = {};
assert(remove_duplicados({}) == esperado2);
std::vector<int> esperado3 = {5};
assert(remove_duplicados({5, 5, 5}) == esperado3);
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex03¶
Escreva existe_chave, que recebe um std::map<std::string, int> e uma chave, e devolve true se a chave existir — sem usar operator[] (isso criaria a chave se ela não existisse!). Use .count() ou .find().
std::map<std::string, int> m = {{"a", 1}, {"b", 2}};
existe_chave(m, "a") // -> true
existe_chave(m, "z") // -> false
// 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 <string>
#include <map>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX03_H
#define EX03_H
// Retorna true se "chave" existir em m, sem usar operator[].
bool existe_chave(const std::map<std::string, int>& m, const std::string& chave);
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
bool existe_chave(const std::map<std::string, int>& m, const std::string& chave) {
// TODO: use m.count(chave) ou m.find(chave) != m.end().
return false;
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
std::map<std::string, int> m = {{"a", 1}, {"b", 2}};
assert(existe_chave(m, "a"));
assert(!(existe_chave(m, "z")));
std::map<std::string, int> vazio = {};
assert(!(existe_chave(vazio, "a")));
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex04¶
Escreva interseccao, que recebe dois std::set<int> e devolve um novo std::set<int> só com os valores que aparecem nos dois conjuntos.
// 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 <set>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX04_H
#define EX04_H
// Retorna um set com os valores que aparecem em a e em b ao mesmo tempo.
std::set<int> interseccao(const std::set<int>& a, const std::set<int>& b);
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
std::set<int> interseccao(const std::set<int>& a, const std::set<int>& b) {
// TODO: percorra a; para cada elemento, se ele tambem estiver em b
// (use b.count(elemento)), insira no resultado.
std::set<int> resultado;
return resultado;
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
std::set<int> esperado1 = {2, 3};
assert(interseccao({1, 2, 3}, {2, 3, 4}) == esperado1);
std::set<int> esperado2 = {};
assert(interseccao({1, 2}, {3, 4}) == esperado2);
std::set<int> esperado3 = {1, 2};
assert(interseccao({1, 2}, {1, 2}) == esperado3);
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex05¶
Escreva chave_maior_valor, que recebe um std::map<std::string, int> não vazio e devolve a chave associada ao maior valor.
// 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 <string>
#include <map>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX05_H
#define EX05_H
// Retorna a chave associada ao maior valor em m (assume que m nao esta vazio).
std::string chave_maior_valor(const std::map<std::string, int>& m);
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
std::string chave_maior_valor(const std::map<std::string, int>& m) {
// TODO: percorra m com "for (const auto& [chave, valor] : m)" guardando
// a chave do maior valor visto ate agora.
return "";
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
std::map<std::string, int> m1 = {{"a", 3}, {"b", 9}, {"c", 1}};
assert(chave_maior_valor(m1) == std::string("b"));
std::map<std::string, int> m2 = {{"x", 5}};
assert(chave_maior_valor(m2) == std::string("x"));
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex06¶
Escreva palavras_unicas, que recebe um texto e devolve quantas palavras diferentes ele tem (ignorando repetições). Use std::istringstream para separar as palavras e um std::set<std::string> para contar só as diferentes.
// 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 <string>
#include <set>
#include <sstream>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX06_H
#define EX06_H
// Retorna quantas palavras diferentes existem em texto.
int palavras_unicas(const std::string& texto);
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
int palavras_unicas(const std::string& texto) {
// TODO: use std::istringstream para separar as palavras (stream >> palavra
// num while), insira cada uma num std::set<std::string>, e retorne o
// tamanho do set no final.
return 0;
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
assert(palavras_unicas("o rato roeu a roupa do rei de roma") == 9);
assert(palavras_unicas("oi oi oi") == 1);
assert(palavras_unicas("") == 0);
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex07¶
Escreva atualiza_estoque, que recebe um std::map<std::string, int>& (o estoque da loja, produto → quantidade) e um std::vector<std::string> com os produtos vendidos. Para cada venda, diminua 1 da quantidade daquele produto.
Se um produto vendido não estiver no estoque, ele deve entrar no map com valor 0 (a loja vendeu algo que não estava cadastrado — o registro precisa aparecer para o problema ser visível).
std::map<std::string, int> estoque = {{"cabo", 5}, {"fonte", 2}};
atualiza_estoque(estoque, {"cabo", "cabo", "led"});
// estoque: cabo -> 3, fonte -> 2, led -> 0
// 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 <string>
#include <vector>
#include <map>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX07_H
#define EX07_H
// Diminui 1 da quantidade de cada produto vendido. Produtos vendidos que nao
// estavam no estoque sao inseridos com quantidade 0.
void atualiza_estoque(std::map<std::string, int>& estoque,
const std::vector<std::string>& vendidos);
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
void atualiza_estoque(std::map<std::string, int>& estoque,
const std::vector<std::string>& vendidos) {
// TODO: para cada produto vendido, verifique com .count() se ele ja existe
// no estoque. Se existir, subtraia 1 da quantidade; se nao, insira com 0.
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
std::map<std::string, int> estoque = {{"cabo", 5}, {"fonte", 2}};
atualiza_estoque(estoque, {"cabo", "cabo", "led"});
assert(estoque["cabo"] == 3);
assert(estoque["fonte"] == 2);
assert(estoque.count("led") == 1);
assert(estoque["led"] == 0);
// Vender de novo um produto que entrou com 0 deixa a quantidade negativa:
// e o sinal de que a loja vendeu o que nao tinha.
atualiza_estoque(estoque, {"led"});
assert(estoque["led"] == -1);
std::map<std::string, int> intacto = {{"cabo", 5}};
atualiza_estoque(intacto, {});
assert(intacto["cabo"] == 5);
assert(intacto.size() == 1);
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex08¶
Escreva diferenca, que recebe dois std::set<int> e devolve um novo std::set<int> com os valores que estão no primeiro conjunto e não estão no segundo (a diferença de conjuntos a \ b).
No exercício ex04 você fez a interseção; a diferença é o mesmo padrão com a condição invertida.
// 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 <set>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX08_H
#define EX08_H
// Retorna os elementos que estao em a mas nao estao em b.
std::set<int> diferenca(const std::set<int>& a, const std::set<int>& b);
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
std::set<int> diferenca(const std::set<int>& a, const std::set<int>& b) {
// TODO: percorra a e insira no resultado cada valor que b.count(valor) == 0.
return {};
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
std::set<int> r1 = diferenca({1, 2, 3}, {2, 4});
assert(r1.size() == 2);
assert(r1.count(1) == 1);
assert(r1.count(3) == 1);
assert(r1.count(2) == 0);
assert(diferenca({1, 2}, {1, 2}).empty());
assert(diferenca({}, {1, 2}).empty());
std::set<int> r2 = diferenca({1, 2}, {});
assert(r2.size() == 2);
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex09¶
Escreva conta_comuns, que devolve quantos valores distintos aparecem nos dois vectors ao mesmo tempo.
A regra do exercício: sem set e sem map, só laço e comparação. Depois de resolver, compare com o ex04 desta mesma lista, que faz a interseção usando std::set: aqui você precisa cuidar da duplicata na mão ({1, 1, 2} contra {1, 2} dá 2, e não 3), enquanto o set cuidaria disso sozinho.
É esse contraste que mostra o que o container associativo está resolvendo.
conta_comuns({1, 2, 3}, {2, 3, 4}) // -> 2
conta_comuns({1, 1, 2}, {1, 2}) // -> 2 (o 1 conta uma vez so)
// 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 <vector>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX09_H
#define EX09_H
// Retorna quantos valores DISTINTOS aparecem nos dois vectors.
// Escreva sem usar set nem map: so laco e comparacao.
int conta_comuns(const std::vector<int>& a, const std::vector<int>& b);
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
int conta_comuns(const std::vector<int>& a, const std::vector<int>& b) {
// TODO: para cada valor de a, verifique se ele aparece em b.
// Cuidado: se o mesmo valor se repetir em a, ele nao pode ser contado
// duas vezes -- confira antes se ele ja apareceu em a mais cedo.
return 0;
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
assert(conta_comuns({1, 2, 3}, {2, 3, 4}) == 2);
assert(conta_comuns({1, 2}, {3, 4}) == 0);
assert(conta_comuns({1, 2}, {1, 2}) == 2);
// valor repetido em a conta uma vez so
assert(conta_comuns({1, 1, 2}, {1, 2}) == 2);
assert(conta_comuns({5, 5, 5}, {5}) == 1);
assert(conta_comuns({}, {1}) == 0);
assert(conta_comuns({1}, {}) == 0);
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex10¶
Escreva chaves_com_valor_zero, que recebe um std::map<std::string, int> (um estoque) e devolve um std::vector<std::string> com as chaves cujo valor é 0, em ordem crescente de chave.
Você não precisa ordenar nada: a própria iteração do map já entrega as chaves em ordem.
std::map<std::string, int> estoque = {{"parafuso", 0}, {"prego", 5}, {"arruela", 0}};
chaves_com_valor_zero(estoque) // -> {"arruela", "parafuso"}
// 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 <string>
#include <vector>
#include <map>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX10_H
#define EX10_H
// Retorna as chaves de "estoque" cujo valor e 0, em ordem crescente de chave.
std::vector<std::string> chaves_com_valor_zero(const std::map<std::string, int>& estoque);
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
std::vector<std::string> chaves_com_valor_zero(const std::map<std::string, int>& estoque) {
// TODO: percorra estoque com "for (const auto& [chave, valor] : estoque)"
// e adicione a chave ao resultado quando valor == 0.
return {};
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
std::map<std::string, int> estoque = {{"parafuso", 0}, {"prego", 5}, {"arruela", 0}};
auto resultado = chaves_com_valor_zero(estoque);
std::vector<std::string> esperado = {"arruela", "parafuso"};
assert(resultado == esperado);
std::map<std::string, int> vazio = {};
assert(chaves_com_valor_zero(vazio).empty());
std::cout << "Todos os testes passaram!\n";
return 0;
}