Desafio C++
Filtrar, transformar e acumular em pipeline
Enunciado
Dado um vetor de inteiros, use std::find_if para localizar o primeiro número maior que 5, depois use std::transform para converter todos os números a partir desse ponto em seus dobros, e finalmente std::accumulate para somar os valores transformados. Imprima o vetor original após a transformação e a soma.
Requisitos
- Use
std::find_ifpara achar o iterador do primeiro elemento > 5. - Use
std::transformpara dobrar os elementos do intervalo encontrado até o fim. - Use
std::accumulatepara somar os elementos transformados. - Imprima o vetor modificado e a soma no formato 'Soma: X'.
Código inicial
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
int main() {
std::vector<int> nums = {2, 8, 1, 6, 3, 9};
// TODO: encontre, transforme e acumule
return 0;
}
Saída esperada
Vetor modificado: 2 16 1 12 3 18
Soma: 46
Ver dica
O iterador retornado por find_if pode ser usado como início do intervalo em transform e accumulate.
Mostrar solução
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
int main() {
std::vector<int> nums = {2, 8, 1, 6, 3, 9};
// 1. Encontra o primeiro número maior que 5
auto it = std::find_if(nums.begin(), nums.end(),
[](int n) { return n > 5; });
if (it != nums.end()) {
// 2. Dobra todos os elementos a partir de 'it'
std::transform(it, nums.end(), it,
[](int n) { return n * 2; });
// 3. Soma os elementos transformados (de 'it' até o fim)
int soma = std::accumulate(it, nums.end(), 0);
std::cout << "Vetor modificado: ";
for (int n : nums) std::cout << n << ' ';
std::cout << '\n';
std::cout << "Soma: " << soma << '\n';
} else {
std::cout << "Nenhum número maior que 5\n";
}
return 0;
}
Passo a passo
- Incluímos os cabeçalhos necessários:
<algorithm>parafind_ifetransform,<numeric>paraaccumulate. std::find_ifpercorrenumse retorna um iterador para o primeiro valor > 5 (o8).- Verificamos se o iterador é válido (
it != nums.end()); se não for, não há o que transformar. std::transform(it, nums.end(), it, ...)aplican * 2no próprio vetor, do ponto encontrado até o fim. Isso modifica os elementos 8, 6 e 9 para 16, 12 e 18.std::accumulate(it, nums.end(), 0)soma apenas os elementos transformados: 16 + 12 + 18 = 46.- Imprimimos o vetor completo (modificado) e a soma.
Por que funciona
find_if fornece um iterador que delimita o início do subintervalo de interesse. transform e accumulate aceitam esse iterador como parte do intervalo, permitindo operar apenas nos elementos a partir dele. Isso mostra como algoritmos da STL se compõem naturalmente, sem laços manuais e sem índices propensos a erro.
Erros comuns
- Passar
itcomo destino emtransformsem verificar se é válido: seit == end(), o intervalo é vazio e nada acontece, mas é seguro; porém, se você tentar acessar*itantes, é comportamento indefinido. - Usar
std::accumulate(nums.begin(), nums.end(), 0)em vez de começar deit: somaria todos os elementos, não apenas os transformados. - Esquecer que
transformcom o mesmo iterador de entrada e saída é permitido e eficiente, mas exige que a operação não dependa de outros elementos.
Outra forma de resolver
Você poderia usar um laço for com iteradores para modificar e somar, mas perderia a clareza e a segurança dos algoritmos. Outra alternativa é usar std::for_each para modificar e depois accumulate, mas transform é mais direto para mapeamento.
Saída esperada
Vetor modificado: 2 16 1 12 3 18
Soma: 46