# Modifying algorithms. Part 1. Algorithms that change all elements of a sequence

### Contents

Search other resources:

##### 1. Algorithm for_each. Perform an operation on each element of the sequence.

The for_each algorithm allows you to perform a given operation on each element of a sequence. This operation is specified by a function. The general form of a common implementation of the algorithm is as follows

```template <class InputIterator, class Function>
Function for_each(
InputIterator first,
InputIterator last,
Function func);```

where

• first – input iterator pointing to the first element of the range to be operated on;
• last – input iterator pointing to the last element of the range on which the operation is to be performed;
• func – function that defines the operation.

Example 1.

In the example, each element of the vector is multiplied by 2. For multiplication, the Mult2() function is used.

```#include <iostream>
#include <vector>
#include <queue>
#include <list>
#include <algorithm>
#include <functional>
using namespace std;

void Mult2(int& value)
{
value = value * 2;
}

void main()
{
// Algorithm for_each. Perform an operation on each element of a sequence
// 1. Create dynamic array
vector<int> V = { 4, 8, 9, 2, 10, 15 };

// 2. Call the for_each algorithm
// Here the Mult2() function is used
for_each(V.begin(), V.end(), Mult2); // each element of the vector is multiplied by 2

// 3. Output the resulting array
vector<int>::iterator p1;

p1 = V.begin();
while (p1 != V.end())
{
cout << *p1 << " ";
p1++;
}

cout << endl;
}```

Example 2.

In our example, each line of list<string> is reversed using the for_each algorithm (Reverse() function).

```#include <iostream>
#include <list>
#include <algorithm>
#include <functional>
using namespace std;

// A function that reverses a string
void Reverse(string& s)
{
string s2 = "";
for (int i = 0; i < s.length(); i++)
{
s2 = s[i] + s2;
}
s.assign(s2);
}

void main()
{
// Algorithm for_each. Perform operation on each element of a sequence
// 1. Create a list of strings
list<string> L = {
"abc",
"def",
"ghi",
"jkl"
};

// 2. Call the for_each algorithm
// The Mult2() function is used here
for_each(L.begin(), L.end(), Reverse); // each element of the list is reversed

// 3. Display the resulting list
list<string>::iterator it;

it = L.begin();
while (it != L.end())
{
cout << *it << endl;
it++;
}

cout << endl;
}```

Result

```cba
fed
ihg
lkj```

### ⇑

##### 2. Algorithm transform. Perform action for each element of a sequence

The transform algorithm allows you to specify an operation to be performed on each element of a sequence or on a pair of elements in two output ranges. The operation can be specified as a unary or binary function. The declaration of the most common implementations of the algorithm is

```template <class InputIterator, class OutputIterator, class UnaryFunction>
OutputIterator transform(
InputIterator first1,
InputIterator last1,
OutputIterator result,
UnaryFunction func );

template <class InputIterator1, class InputIterator2, class OutputIterator, class BinaryFunction>
OutputIterator transform(
InputIterator1 first1,
InputIterator1 last1,
InputIterator2 first2,
OutputIterator result,
BinaryFunction func );```

where

• first1, last1 – input iterators specifying the first output range for processing;
• first2 – input iterator specifying the second range for processing;
• result – output iterator pointing to the position of the first element in the destination range;
• func – unary or binary function that specifies an operation to be performed on one element or on several elements.

Example.

```#include <iostream>
#include <list>
#include <algorithm>
using namespace std;

// A predicate that performs the operation on a single element of a sequence,
// multiply the value of the value parameter by 5
int Mult_5(int value)
{
return value * 5;
}

// A predicate that performs an operation on two distinct elements.
// These elements can be from different sequences.
int Mult_AB(int a, int b)
{
return a * b; // return the product of the elements
}

int main()
{
// The transform algorithm – execute a function for each element of this sequence

// 1. Using the algorithm in combination with the predicate.
// 1.1. Create a sequence of numbers and print it to the console.
list<int> L1 = { 2, 8, 1, 4, 3, 5, 7, 0, -2, 6, 3 };
cout << "L1 => ";
for (int i : L1)
cout << i << " ";
cout << endl;

// 1.2. Create another sequence the same size as the original one
list<int> L2(L1.size());

// 1.3. Call the transform algorithm for the L1 list based on the Mult_5 predicate,
// new L2 sequence is created
transform(L1.begin(), L1.end(), L2.begin(), Mult_5);

// 1.4. Output the resulting sequence L2
cout << "L2 => ";
for (int i : L2)
cout << i << " ";
cout << endl;

// 2. Using algorithm based on the lambda expression.
// 2.1. Create a sequence of L3 zero values of size L1.size()
list<int> L3(L1.size());

// 2.2. Create a second sequence, each element of which
//      is multiplied by 2 - call the transform algorithm
transform(L1.begin(), L1.end(), L3.begin(), [](int a) { return a * 2; });

// 2.3. Display the resulting sequence
cout << "L3 => ";
for (int i : L3)
cout << i << " ";
cout << endl;

// 3. Using the transform algorithm to perform operation on two sequences.
// It is necessary to multiply the elements of the sequence L1 by the elements of the sequence L2

// 3.1. Create a new sequence of size L1.size()
list<int> L4(L1.size());

// 3.2. Fill the L4 sequence with values L1[i]*L2[i]
transform(L1.begin(), L1.end(), L2.begin(), L4.begin(), Mult_AB);

// 3.3. Print the sequence L4
cout << "L1[i]*L2[i] => ";
for (int i : L4)
cout << i << " ";
cout << endl;

// 4. Using the transform algorithm to perform operation on two sequences based on a lambda expression.
// Get a new sequence in which the sequences L1 and L2 are added element by element.
// 4.1. Create a new L5 null sequence of size L1.size().
list<int> L5(L1.size());

// 4.2. Fill sequence L5 with values L1[i]+L2[i] based on lambda expression.
transform(
L1.begin(), // the begin of L1
L1.end(),   // the end of L1, L1.end()-L1.begin() => this is the length of the resulting sequence
L2.begin(), // the beginning of the second sequence, attached to L1
L5.begin(), // the beginning of the resulting sequence
[](int a, int b) { return a + b; } // lambda expression that returns the sum of a and b
);

// 4.3. Display the resulting sequence
cout << "L1[i]+L2[i] => ";
for (int i : L5)
cout << i << " ";
cout << endl;
}```

Result

```L1 => 2 8 1 4 3 5 7 0 -2 6 3
L2 => 10 40 5 20 15 25 35 0 -10 30 15
L3 => 4 16 2 8 6 10 14 0 -4 12 6
L1[i]*L2[i] => 20 320 5 80 45 125 245 0 20 180 45
L1[i]+L2[i] => 12 48 6 24 18 30 42 0 -12 36 18```

### ⇑

##### 3. Algorithm fill. Fill the range with the desired values

The fill algorithm is designed to assign a value to each element in a given range. The declaration of the algorithm is

```template <class ForwardIterator, class Type>
void fill(
ForwardIterator first,
ForwardIterator last,
const Type& value);```

here

• first, last – direct iterators used to set the range;
• value – value that fills the range.

Example.

```#include <iostream>
#include <queue>
#include <vector>
#include <list>
#include <functional>
#include <algorithm>
using namespace std;

int main()
{
// The fill algorithm - fill the range with the desired values

// 1. Declaring a 5-element vector
vector<int> V(5);

// 2. Fill the vector with value 10
fill(V.begin(), V.end(), 10);

// 3. Display the vector on the screen
cout << "V => ";
for (int i : V)
cout << i << " ";
cout << endl;

// 4. Declare a list of 10 elements
list<double> L(10);

// 5. Fill list with value 5.0
fill(L.begin(), L.end(), 5.0);

// 6. Display the list on the screen
cout << "L => ";
for (double d : L)
cout << d << " ";
cout << endl;
}```

Result

```V => 10 10 10 10 10
L => 5 5 5 5 5 5 5 5 5 5```

### ⇑

##### 4. Algorithm fill_n. Fill in the range with the required values.

The fill_n algorithm assigns a new value to a specified number of elements in a range, starting at a particular element.

A common implementation of the algorithm is as follows

```template <class OutputIterator, class Size, class Type>
OutputIterator fill_n(
OutputIterator first,
Size count,
const Type& value);```

where

• first – an iterator pointing to the beginning of the range;
• count – number of elements to be assigned;
• value – the value that is assigned to the elements of the range.

Example.

```#include <iostream>
#include <queue>
#include <vector>
#include <list>
#include <functional>
#include <algorithm>
using namespace std;

int main()
{
// The fill algorithm - fill the range with the desired values

// 1. Declare a vector of 5 elements
vector<int> V(5);

// 2. Fill the first 3 elements of the vector with the value 10
fill_n(V.begin(), 3, 10);

// 3. Display the vector on the screen
cout << "V => ";
for (int i : V)
cout << i << " ";
cout << endl;

// 4. Declare a list of 10 elements
list<double> L(10);

// 5. Fill the first 7 elements of the list with the value 1.0
fill_n(L.begin(), 7, 1.0);

// 6. Display the list on the screen
cout << "L => ";
for (double d : L)
cout << d << " ";
cout << endl;
}```

Result

```V => 10 10 10 0 0
L => 1 1 1 1 1 1 1 0 0 0```

### ⇑

##### 5. Algorithm generate. Perform operation on each element of a sequence

The generate algorithm assigns values to each element in the range generated by the function object. The general form of algorithm is as follows

```template <class ForwardIterator, class Generator>
void generate(
ForwardIterator first,
ForwardIterator last,
Generator gen);```

where

• first, last – iterators defining the range of processed values;
• gen – object of a function called with no arguments to generate values to be assigned to each element in the range.

Example 1.

The example uses a lambda expression to write the value “abcd” in each row of the list L.

```#include <list>
#include <algorithm>
#include <functional>
using namespace std;

void main()
{
// Algorithm generate. Perform an operation on each element of the sequence
// 1. Create a list of strings
list<string> L = {
"abc",
"def",
"ghi",
"jkl"
};

// 2. Call the algorithm generate
// Write "abcd" to each element of the list using a lambda expression.
generate(L.begin(), L.end(), []() { return "abcd"; });

// 3. Display the resulting string
list<string>::iterator it;

it = L.begin();
while (it != L.end())
{
cout << *it << endl;
it++;
}

cout << endl;
}```

Example 2.

The example generates an array of numbers 5.0 by calling the Get5() function.

```#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;

// A function that returns the number 5
double Get5()
{
return 5.0;
}

void main()
{
// Algorithm generate. Perform operation on each element of the sequence
// 1. Create array of 10 numbers
vector<double> V(10);

// 2. Call algorithm generate
// Write a number to each element of array using the Get5() function
generate(V.begin(), V.end(), Get5);

// 4. Display the resulting array
vector<double>::iterator it;

it = V.begin();
while (it != V.end())
{
cout << *it << " ";
it++;
}

cout << endl;
}```

Result

`5 5 5 5 5 5 5 5 5 5`

### ⇑

##### 6. Algorithm generate_n. Perform an operation on each element of the sequence

The generate_n algorithm assigns a value to a given number of sequence elements that were generated by the function object. The algorithm returns the position after the last value assigned

```template <class OutputIterator, class Diff, class Generator>
void generate_n(
OutputIterator first,
Diff count,
Generator gen);```

where

• first – iterator pointing to the beginning of the range;
• count – the number of elements to which a value is assigned;
• gen – function object without arguments, used to generate values.

Example 1.

```#include <iostream>
#include <list>
#include <algorithm>
#include <functional>
using namespace std;

void main()
{
// Algorithm generate_n. Perform an operation on each element of the sequence
// 1. Create a list of strings
list<string> L;

// 2. Create 5 empty strings
L.resize(5, "");

// 3. Call the generate_n algorithm
// Write "abcd" to each element of the list using a lambda expression
generate_n(L.begin(), L.size(), []() { return "abcd"; });

// 4. Display the resulting list
list<string>::iterator it;

it = L.begin();
while (it != L.end())
{
cout << *it << endl;
it++;
}

cout << endl;
}```

Example 2.

In the example, an array of random numbers is formed, the value of which lies in the range [1; 10].

```#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#include <time.h>
using namespace std;

// A function that returns a random number between 1 and 10 inclusive
int Get_1_10()
{
int value = rand() % 10 + 1;
return value;
}

void main()
{
// Algorithm generate_n. Perform an operation on each element of a sequence
// 1. Create an array of 10 numbers
vector<int> V(10);

// 2. Initialize the kernel to get random values
srand(time(NULL));

// 2. Call the generate_n algorithm
// Write a number to each array element using the Get_1_10() function
generate_n(V.begin(), V.size(), Get_1_10);

// 4. Display the resulting array
vector<int>::iterator it;

it = V.begin();
while (it != V.end())
{
cout << *it << " ";
it++;
}

cout << endl;
}```