# (C++) Exercise #9: No for-loops

Difficulty: 5/10

Date added: 29th of December 2009

In this exercise, you learn to replace for-loops by algorithms.

 ``` Prefer algorithms over loops  ```

This is easier said than done.

In this exercise you must replace for-loops by using a combination of all those algorithm things like std::for_each, std::transform, std::bind1st, std::bind2nd, std::multiplies and more of the likes. It is up to you to find the correct combination.

The exercises are unordered. Some require Boost, but will be in namespace std after the C++11 standard.

## Question #0: Triple

Replace the for-loop. You will need:

 ``` #include   void Triple(std::vector& v) {   const int sz = v.size();   for (int i=0; i!=sz; ++i)   {     v[i]*=3;   } } ```

Replace the for-loop. You will need:

 ``` #include   const std::vector AddTwo(const std::vector& v) {   std::vector v_new(v); //Copy original vector   const int sz = v.size();   for (int i=0; i!=sz; ++i)   {     v_new[i]+=2;   }   return v_new; } ```

## Question #2: Multiply

Replace the for-loop. You will need:

 ``` #include   void Multiply(std::vector& v, const int x) {   const int sz = v.size();   for (int i=0; i!=sz; ++i)   {     v[i]*=x;   } } ```

Replace the for-loop. You will need:

 ``` #include   const std::vector Add(const std::vector& v, const int x) {   std::vector v_new(v); //Copy original vector   const int sz = v.size();   for (int i=0; i!=sz; ++i)   {     v_new[i]+=x;   }   return v_new; } ```

## Question #4: Widget::DoIt on Widget

Replace the for-loop. You will need:

 ``` #include   struct Widget {   void DoIt() const { /* do it */ } };   void DoIt(const std::vector& v) {   const int sz = v.size();   for (int i=0; i!=sz; ++i)   {     v[i].DoIt();   } } ```

## Question #5: Widget::DoItOften on Widget

Replace the for-loop. You will need:

 ``` #include   struct Widget {   void DoItOften(const int n) const { /* do it n times */ } };   void DoItOften(const std::vector& v, const int n) {   const int sz = v.size();   for (int i=0; i!=sz; ++i)   {     v[i].DoItOften(n);   } } ```

## Question #6: Widget::DoIt on Widget*

Replace the for-loop. You will need:

 ``` #include   struct Widget {   void DoIt() const { /* do it */ } };   void DoIt(const std::vector& v) {   const int sz = v.size();   for (int i=0; i!=sz; ++i)   {     v[i]->DoIt();   } } ```

## Question #7: Widget::DoItOften on Widget*

Replace the for-loop. You will need:

 ``` #include   struct Widget {   void DoItOften(const int n) const { /* do it n times */ } };   void DoItOften(const std::vector& v, const int n) {   const int sz = v.size();   for (int i=0; i!=sz; ++i)   {     v[i]->DoItOften(n);   } } ```

## Question #8: GetSum

Replace the for-loop. You will need:

 ``` #include   const int GetSum(const std::vector& v) {   const int sz = v.size();   const int sum = 0;   for (int i=0; i!=sz; ++i)   {     sum+=v[i];   }   return sum; } ```

## Question #9: Product

Replace the for-loop. You will need:

 ``` #include   const int Product(const std::vector& v) {   const int sz = v.size();   const int product = 1;   for (int i=0; i!=sz; ++i)   {     product*=v[i];   }   return product; } ```

## Question #10: Widget::DoIt on boost::shared_ptr<Widget>

Replace the for-loop. You will need:

 ``` #include #include   struct Widget {   void DoIt() const { /* do it */ } };   void DoIt(const std::vector >& v) {   const std::size_t sz = v.size();   for (std::size_t i=0; i!=sz; ++i)   {     v[i]->DoIt();   } } ```

## Question #11: ReplaceZeroByOne

Replace the for-loop. You will need:

 ``` #include   void ReplaceZeroByOne(std::vector& v) {   const int sz = v.size();   for (int i=0; i!=sz; ++i)   {     if(v[i]==0) v[i]=1;   } } ```

## Question #12: ReplaceNegativeByZero

Replace the for-loop. You will need:

 ``` #include   void ReplaceNegativeByZero(std::vector& v) {   const int sz = v.size();   for (int i=0; i!=sz; ++i)   {     if(v[i]<0) v[i]=0;   } } ```

## Question #13: MakeAbs

Replace the for-loop. You will need:

 ``` #include #include   void MakeAbs(std::vector& v) {   const int sz = v.size();   for (int i=0; i!=sz; ++i)   {     v[i] = std::abs(v[i]);   } } ```

## Question #14: MakeSquare

Replace the for-loop. You will need:

 ``` #include   void MakeSquare(std::vector& v) {   const int sz = v.size();   for (int i=0; i!=sz; ++i)   {     v[i]*=v[i];   } } ```

## Question #15: CoutVector

Replace the for-loop. You will need:

 ``` #include   void CoutVector(std::vector& v) {   const int sz = v.size();   for (int i=0; i!=sz; ++i)   {     std::cout << v[i] << '\n';   } } ```

## Question #16: Reciprocal

Replace the for-loop. You will need:

 ``` #include   void Reciprocal(std::vector& v) {   const int sz = v.size();   for (int i=0; i!=sz; ++i)   {     v[i]=1.0/v[i];   } } ```

## Question #17: Halve

Replace the for-loop. You will need:

 ``` #include   void Halve(std::vector& v) {   const int sz = v.size();   for (int i=0; i!=sz; ++i)   {     v[i]/=2.0;   } } ```

## Question #18: SumPositives

Replace the for-loop. You will need:

 ``` int SumPositives(const std::vector& v) {   const size_t sz = v.size();   int sum = 0;   for (size_t i=0; i!=sz; ++i)   {     if (v[i]>0) sum+=v[i];   }   return sum; } ```

## Question #19: ProductNonZeroPositives

Replace the for-loop. You will need:

 ``` int ProductNonZeroPositives(const std::vector& v) {   const size_t sz = v.size();   int product = 0;   for (size_t i=0; i!=sz; ++i)   {     if (v[i]>0) product*=v[i];   }   return product; } ```

## Question #20: CountNonZeroPositives

Replace the for-loop. You will need:

 ``` #include int CountNonZeroPositives(const std::vector& v) {   int sum = 0;   const size_t sz = v.size();   for (size_t i = 0; i!=sz; ++i)   {     if (v[i]>0) sum+=v[i];   } } ```

## Question #21: CopyFirst

Replace the for-loop. You will need:

 ``` #include ///CopyFirst copies the first std::pair elements from a std::vector of std::pairs //From http://www.richelbilderbeek.nl/CppCopyFirst.htm template const std::vector CopyFirst(const std::vector >& v) {   std::vector w;   const int size = static_cast(v.size());   for (int i=0; i!=size; ++i)   {     w.push_back(v[i].first);   }   return w; } ```

## Question #22: CopySecond

Replace the for-loop. You will need:

 ``` #include ///CopySecond copies the second std::pair elements from a std::vector of std::pairs //From http://www.richelbilderbeek.nl/CppCopySecond.htm template const std::vector CopySecond(const std::vector >& v) {   std::vector w;   const int size = static_cast(v.size());   for (int i=0; i!=size; ++i)   {     w.push_back(v[i].second);   }   return w; } ```

## Question #23: SumFirst

Replace the for-loop. You will need:

 ``` int SumFirst(const std::vector >& v) {   const int size = static_cast(v.size());   int sum = 0;   for (int i=0; i!=size; ++i)   {     sum+=v[i].first;   }   return sum; } ```

## Question #24: SumSecond

Replace the for-loop. You will need:

 ``` int SumSecond(const std::vector >& v) {   const int size = static_cast(v.size());   int sum = 0;   for (int i=0; i!=size; ++i)   {     sum+=v[i].second;   }   return sum; } ```

## Question #25: HasMale on std::vector<Person*>

Replace the for-loop. You will need:

 ``` #include #include struct Person {   Person(const bool is_male) : m_is_male(is_male) {}   bool IsMale() const { return m_is_male; }   const bool m_is_male; }; bool HasMale(const std::vector& v) {   const int size = boost::numeric_cast(v.size());   for (int i=0; i!=size; ++i)   {     if (v[i]->IsMale()) return true;   }   return false; } ```

## Question #26: HasFemale on std::vector<Person*>

Replace the for-loop. You will need:

 ``` #include #include struct Person {   Person(const bool is_male) : m_is_male(is_male) {}   bool IsMale() const { return m_is_male; }   const bool m_is_male; }; bool HasFemale(const std::vector& v) {   const int size = boost::numeric_cast(v.size());   for (int i=0; i!=size; ++i)   {     if (!v[i]->IsMale()) return true;   }   return false; } ```

## Question #27: HasId on std::vector<Person*>

Replace the for-loop. You will need:

 ``` #include #include struct Person {   Person(const int id) : m_id(id) {}   int GetId() const { return m_id; }   const int m_id; }; bool HasId(const std::vector& v, const int id) {   const int size = boost::numeric_cast(v.size());   for (int i=0; i!=size; ++i)   {     if (v[i]->GetId() == id) return true;   }   return false; } ```

## Question #28: GetMaxId on std::vector<Person*>

Replace the for-loop. You will need:

 ``` #include #include #include struct Person {   Person(const int id) : m_id(id) {}   int GetId() const { return m_id; }   const int m_id; }; const Person * GetMaxId(const std::vector& v) {   assert(!v.empty());   const int size = boost::numeric_cast(v.size());   int max_id = v->GetId();   int index_max_id = 0;   for (int i=1; i!=size; ++i)   {     const int id = v[i]->GetId();     if (id > max_id)     {       max_id = id;       index_max_id = i;     }   }   return v[index_max_id]; } ```

## Question #29: GetAllTrue on std::map<int,bool>

Replace the BOOST_FOREACH. You will need:

 ``` #include #include #include ///Returns true if all bools are true bool GetAllTrue(const std::map& v) {   assert(!v.empty());   typedef std::pair Pair;   BOOST_FOREACH(const Pair& p,v)   {     if (p.second == false) return false;   }   return true; } ```

## Question #30: Get maximum value from std::map<const Person *,int>

Replace the for-loop. You will need:

 ``` #include #include #include #include struct Person { }; const Person * GetPersonWithMaxIdStl(const std::map& v) {   assert(!v.empty());   int max_id =  std::numeric_limits::min();   const Person * ptr = 0;   typedef std::pair Pair;   BOOST_FOREACH(const Pair& p,v)   {     if (p.second > max_id)     {       max_id = p.second;       ptr = p.first;     }   }   assert(ptr);   return ptr; } ```

## Question #31: Find an ID in a std::vector<const Person*>

Replace the for-loop. You will need:

 ``` #include #include struct Id {   Id(const int id) : m_id(id) { }   int Get() const { return m_id; }   private:   int m_id; }; struct Person {   Person(const int id) : m_id(new Id(id)) {}   const Id * GetId() const { return m_id.get(); }   private:   boost::scoped_ptr m_id; }; bool IsIdTaken(const std::vector& v, const int id) {   const int sz = static_cast(v.size());   for (int i=0; i!=sz; ++i)   {     if (v[i]->GetId()->Get() == id) return true;   }   return false; } ```

## Question #32: Sum all persons' money from a std::vector<const Person*>

Replace the for-loop. You will need:

 ``` #include struct Person {   Person(const int money) : m_money(money) {}   int GetMoney() const { return m_money; }   private:   int m_money; }; int SumMoney(const std::vector& v) {   int sum = 0;   const int sz = v.size();   for (int i=0; i!=sz; ++i)   {     sum+=v[i]->GetMoney();   }   return sum; } ```

## References

1. Bjarne Stroustrup. The C++ Programming Language (3rd edition). ISBN: 0-201-88954-4. Chapter 18.12.1 : 'Prefer algorithms over loops'
2. Herb Sutter and Andrei Alexandrescu. C++ coding standards: 101 rules, guidelines, and best practices. ISBN: 0-32-111358-6. Chapter 84: 'Prefer algorithm calls to handwritten loops.' 