diff --git a/notebooks/07_STL_Set+Map+Algorithms.ipynb b/notebooks/07_STL_Set+Map+Algorithms.ipynb
index 1de53db632957153496c8406c757ac5c773284cd..2618e9618bbedada18c4c00d582462b30e94a19a 100644
--- a/notebooks/07_STL_Set+Map+Algorithms.ipynb
+++ b/notebooks/07_STL_Set+Map+Algorithms.ipynb
@@ -1 +1,887 @@
-{"metadata":{"orig_nbformat":4,"kernelspec":{"display_name":"C++14","language":"C++14","name":"xcpp14"},"language_info":{"codemirror_mode":"text/x-c++src","file_extension":".cpp","mimetype":"text/x-c++src","name":"c++","version":"14"}},"nbformat_minor":5,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# STL - Part 2 : More Containers & Algorithms","metadata":{},"id":"bac1d62f"},{"cell_type":"markdown","source":"#### Sets","metadata":{},"id":"efdc5616"},{"cell_type":"code","source":"#include <iostream>\n#include <set>\n\nstd::set< int > s = {1, 7, 4, 8, 2};   // create a set container and fill it\n\ns.insert(5);   // insert another element\ns.insert(4);\n\n// check how often an element is inside the set\nfor ( int i = 0; i < 8; ++i ) {\n    std::cout << i << \" appears \" << s.count( i ) << \" times\\n\";\n}","metadata":{"trusted":true},"execution_count":2,"outputs":[{"name":"stdout","text":"0 appears 0 times\n1 appears 1 times\n2 appears 1 times\n3 appears 0 times\n4 appears 1 times\n5 appears 1 times\n6 appears 0 times\n7 appears 1 times\n","output_type":"stream"}],"id":"c2848a05"},{"cell_type":"markdown","source":"**Remarks:**\n- Although we inserted **4** twice, it is only stored once in the set data structure. Just like a mathematical set a ```std::set``` can contain a specific object only once.\n- Hence, ```count()``` will always return either 0 or 1.\n- This shows that ```std::set``` is no sequence container.\n- Instead it stores its elements in a **sorted** fashion. This guarantees logarithmic complexity for element access.","metadata":{},"id":"44573775"},{"cell_type":"markdown","source":"Of course we can store various kinds of objects in a set ...","metadata":{},"id":"a415d236"},{"cell_type":"code","source":"struct myPair {\n  myPair( int fir, int sec ) : fir_( fir ), sec_( sec ) {};\n  int fir_;\n  int sec_;\n};\n\nstd::set< myPair > pairs; ","metadata":{"trusted":true},"execution_count":3,"outputs":[],"id":"2213e98e"},{"cell_type":"markdown","source":"... but there is a caveat. Check what happens, when we try to insert an object of type ```myPair``` into the set:","metadata":{},"id":"725387bc"},{"cell_type":"code","source":"pairs.insert( myPair(1,2) );","metadata":{"trusted":true},"execution_count":4,"outputs":[{"name":"stderr","text":"In file included from input_line_5:1:\nIn file included from /srv/conda/envs/notebook/include/xeus/xinterpreter.hpp:13:\nIn file included from /srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/9.4.0/functional:49:\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/9.4.0/bits/stl_function.h:386:20: error: invalid operands to binary expression ('const __cling_N54::myPair' and 'const __cling_N54::myPair')\n      { return __x < __y; }\n               ~~~ ^ ~~~\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/9.4.0/bits/stl_tree.h:2100:13: note: in instantiation of member function 'std::less<__cling_N54::myPair>::operator()' requested here\n          __comp = _M_impl._M_key_compare(__k, _S_key(__x));\n                   ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/9.4.0/bits/stl_tree.h:2153:4: note: in instantiation of member function 'std::_Rb_tree<__cling_N54::myPair, __cling_N54::myPair, std::_Identity<__cling_N54::myPair>, std::less<__cling_N54::myPair>, std::allocator<__cling_N54::myPair> >::_M_get_insert_unique_pos' requested here\n        = _M_get_insert_unique_pos(_KeyOfValue()(__v));\n          ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/9.4.0/bits/stl_set.h:521:9: note: in instantiation of function template specialization 'std::_Rb_tree<__cling_N54::myPair, __cling_N54::myPair, std::_Identity<__cling_N54::myPair>, std::less<__cling_N54::myPair>, std::allocator<__cling_N54::myPair> >::_M_insert_unique<__cling_N54::myPair>' requested here\n          _M_t._M_insert_unique(std::move(__x));\n               ^\ninput_line_12:2:8: note: in instantiation of member function 'std::set<__cling_N54::myPair, std::less<__cling_N54::myPair>, std::allocator<__cling_N54::myPair> >::insert' requested here\n pairs.insert( myPair(1,2) );\n       ^\nIn file included from input_line_5:1:\nIn file included from /srv/conda/envs/notebook/include/xeus/xinterpreter.hpp:17:\nIn file included from /srv/conda/envs/notebook/include/xeus/xcomm.hpp:15:\nIn file included from /srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/9.4.0/map:60:\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/9.4.0/bits/stl_tree.h:777:2: error: static_assert failed \"comparison object must be invocable with two arguments of key type\"\n        static_assert(__is_invocable<_Compare&, const _Key&, const _Key&>{},\n        ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/9.4.0/bits/stl_tree.h:2100:41: note: in instantiation of member function 'std::_Rb_tree<__cling_N54::myPair, __cling_N54::myPair, std::_Identity<__cling_N54::myPair>, std::less<__cling_N54::myPair>, std::allocator<__cling_N54::myPair> >::_S_key' requested here\n          __comp = _M_impl._M_key_compare(__k, _S_key(__x));\n                                               ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/9.4.0/bits/stl_tree.h:2153:4: note: in instantiation of member function 'std::_Rb_tree<__cling_N54::myPair, __cling_N54::myPair, std::_Identity<__cling_N54::myPair>, std::less<__cling_N54::myPair>, std::allocator<__cling_N54::myPair> >::_M_get_insert_unique_pos' requested here\n        = _M_get_insert_unique_pos(_KeyOfValue()(__v));\n          ^\n/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/9.4.0/bits/stl_set.h:521:9: note: in instantiation of function template specialization 'std::_Rb_tree<__cling_N54::myPair, __cling_N54::myPair, std::_Identity<__cling_N54::myPair>, std::less<__cling_N54::myPair>, std::allocator<__cling_N54::myPair> >::_M_insert_unique<__cling_N54::myPair>' requested here\n          _M_t._M_insert_unique(std::move(__x));\n               ^\ninput_line_12:2:8: note: in instantiation of member function 'std::set<__cling_N54::myPair, std::less<__cling_N54::myPair>, std::allocator<__cling_N54::myPair> >::insert' requested here\n pairs.insert( myPair(1,2) );\n       ^\n","output_type":"stream"},{"ename":"Interpreter Error","evalue":"","traceback":["Interpreter Error: "],"output_type":"error"}],"id":"51fd5597"},{"cell_type":"markdown","source":"**What went wrong?**\n\nAs the set stores its elements in a **sorted** fashion it needs some way to **order** them.\nBy default the standard ```<``` relation is used.\n\nThat does not work for our ```myPair``` data type.\n\nWe need to define our own comparison operator for the class.\n\nThere are plenty ways of doing that. Below we will use a free function for it.","metadata":{},"id":"2ee8f731"},{"cell_type":"code","source":"%%file demo.cpp\n\n#include <iostream>\n#include <set>\n\nstruct myPair {\n  myPair( int fir, int sec ) : fir_( fir ), sec_( sec ) {};\n  int fir_;\n  int sec_;\n};\n\n// our comparison function will return true, if the sum of the squares\n// of the values in left is smaller than that in right (problem with tie-breaking?)\nbool cmp( const myPair& left, const myPair& right ) {\n  int val1 = left.fir_ * left.fir_ + left.sec_ * left.sec_;\n  int val2 = right.fir_ * right.fir_ + right.sec_ * right.sec_;\n  return val1 < val2;\n}\n\nint main() {\n    \n    // create two objects\n    myPair p1( 1, 2 );\n    myPair p2( 3, 4 );\n\n    // compare them\n    std::cout << \"p1 < p2 is \" << cmp( p1, p2 ) << std::endl;\n    std::cout << \"p2 < p1 is \" << cmp( p2, p1 ) << std::endl;\n\n    // a free function in C/C++ is represented by the address of its machine code in memory;\n    // thus, the type of argument is a function pointer;\n    // we need to pass that info as a second template argument;\n    // decltype returns the type of an expression\n    std::set< myPair, decltype( cmp )* > pairs( cmp );\n\n    // alternatively we could do it ourselves; note that the (*) is important!\n    // but that way is not very C++-ish\n    // std::set< myPair, bool (*)( const myPair&, const myPair& ) > pairs( cmp );\n    \n    // now insertion will work\n    pairs.insert( p1 );\n    pairs.insert( p2 );\n\n    std::cout << \"insertion successful\" << std::endl;\n}","metadata":{"trusted":true},"execution_count":5,"outputs":[{"name":"stdout","text":"Writing demo.cpp\n","output_type":"stream"}],"id":"e8c29594"},{"cell_type":"code","source":"!g++ demo.cpp","metadata":{"trusted":true},"execution_count":6,"outputs":[],"id":"0a0207dd"},{"cell_type":"code","source":"!./a.out","metadata":{"trusted":true},"execution_count":7,"outputs":[{"name":"stdout","text":"p1 < p2 is 1\np2 < p1 is 0\ninsertion successful\n","output_type":"stream"}],"id":"68e1df4b"},{"cell_type":"markdown","source":"**Note:**  \nThe STL offers a variant **```std::unordered_set```** that stores its elements in an unsorted fashion. However, that would not solve our problem. Instead of a **comparison** we then would need to implement a **hashing function**.","metadata":{},"id":"f8b3109b"},{"cell_type":"markdown","source":"***\nThe way we added the new element in the example, i.e. via\n\n```pairs.insert( myPair(1,2) );```\n\nagain induced a copy operation. As with ```vector``` and ```list``` we could use ```emplace()``` instead.\n\nFor demonstration purposes we make the constructor of ```myPair``` verbose.","metadata":{},"id":"59ab93ca"},{"cell_type":"code","source":"%%file demo.cpp\n\n#include <iostream>\n#include <set>\n\nstruct myPair {\n  myPair( int fir, int sec ) : fir_( fir ), sec_( sec ) {\n      std::cout << \"(\" << fir_ << \",\" << sec_ << \") constructed\" << std::endl;\n  };\n \n  int fir_;\n  int sec_;\n};\n\n// our comparison function: will return true, if the square of the values\n// in left is smaller than that in right\nbool cmp( const myPair& left, const myPair& right ) {\n  int val1 = left.fir_ * left.fir_ + left.sec_ * left.sec_;\n  int val2 = right.fir_ * right.fir_ + right.sec_ * right.sec_;\n  return val1 < val2;\n}\n\nint main() {\n    \n    std::set< myPair, decltype( cmp )* > pairs( cmp );\n\n    pairs.emplace( 1, 2 );\n    pairs.emplace( 3, 4 );\n    pairs.emplace( 1, 2 );\n}","metadata":{"trusted":true},"execution_count":8,"outputs":[{"name":"stdout","text":"Overwriting demo.cpp\n","output_type":"stream"}],"id":"bdda6c33"},{"cell_type":"code","source":"!g++ demo.cpp","metadata":{"trusted":true},"execution_count":9,"outputs":[],"id":"8099d1a4"},{"cell_type":"code","source":"!./a.out","metadata":{"trusted":true},"execution_count":11,"outputs":[{"name":"stdout","text":"(1,2) constructed\n(3,4) constructed\n(1,2) constructed\n","output_type":"stream"}],"id":"5d491b27"},{"cell_type":"markdown","source":"#### Associative Containers\n\nQuoting Wikipedia:\n\n> In computer science, an **associative array**, **map**, **symbol table**, or **dictionary** is an abstract data type composed of a collection of **(key, value) pairs**, such that each possible key appears at most once in the collection.\n>\n> Operations associated with this data type allow to:\n>\n>-    add a pair to the collection;\n>-    remove a pair from the collection;\n>-    modify an existing pair;\n>-    lookup a value associated with a particular key.\n\nThe STL also offers associative containers. An example is ```std::map```.","metadata":{},"id":"8e256275"},{"cell_type":"markdown","source":"Return to our example with the traffic light. Assume that we want to print the currect state of a specific traffic light. How to do that?\n\nWell, using an enumeration for the state we can use the classical switch-case-construct:","metadata":{},"id":"fb3ef7bb"},{"cell_type":"code","source":"%%file ampel.cpp\n\n#include <iostream>\n\ntypedef enum{ GREEN, YELLOW, RED, YELLOW_RED } trafficLight;\n\nvoid ampel( trafficLight tf ) {\n\n  switch( tf ) {\n  case GREEN:\n    std::cout << \"Lights are green\" << std::endl;\n    break;\n  case YELLOW:\n    std::cout << \"Lights are yellow\" << std::endl;\n    break;\n  case RED:\n    std::cout << \"Lights are red\" << std::endl;\n    break;\n  case YELLOW_RED:\n    std::cout << \"Lights are yellow-red\" << std::endl;\n    break;\n  }\n\n}\n\nint main() {\n  trafficLight tf = GREEN;\n  ampel( tf );\n}","metadata":{"trusted":true},"execution_count":12,"outputs":[{"name":"stdout","text":"Writing ampel.cpp\n","output_type":"stream"}],"id":"59839aea"},{"cell_type":"code","source":"!g++ ampel.cpp","metadata":{"trusted":true},"execution_count":13,"outputs":[],"id":"76c8886d"},{"cell_type":"code","source":"!./a.out","metadata":{"trusted":true},"execution_count":14,"outputs":[{"name":"stdout","text":"Lights are green\n","output_type":"stream"}],"id":"731e7c94"},{"cell_type":"markdown","source":"Another (neater) way is to associate the state with a corresponding string","metadata":{},"id":"08b68b2b"},{"cell_type":"code","source":"%%file ampel.cpp\n\n#include <iostream>\n#include <map>\n\ntypedef enum{ GREEN, YELLOW, RED, YELLOW_RED } trafficLight;\n\nint main() {\n\n  std::map< trafficLight, std::string > tf2str =\n    { { GREEN, \"green\" }, { YELLOW, \"yellow\" }, { RED, \"red\" },\n      { YELLOW_RED, \"yellow-red\" } };\n\n  trafficLight tf = GREEN;\n\n  std::cout << \"Lights are \" << tf2str[ tf ] << std::endl;\n}","metadata":{"trusted":true},"execution_count":15,"outputs":[{"name":"stdout","text":"Overwriting ampel.cpp\n","output_type":"stream"}],"id":"8fe484bf"},{"cell_type":"code","source":"!g++ ampel.cpp","metadata":{"trusted":true},"execution_count":16,"outputs":[],"id":"74251bd8"},{"cell_type":"code","source":"!./a.out","metadata":{"trusted":true},"execution_count":17,"outputs":[{"name":"stdout","text":"Lights are green\n","output_type":"stream"}],"id":"5b919ca3"},{"cell_type":"markdown","source":"Another example, demonstrating additional features of ```std::map``` (converted from Gottschling, *Forschung mit modernem C++*)","metadata":{},"id":"b1718cdd"},{"cell_type":"code","source":"%%file constants.cpp\n\n#include <iostream>\n#include <string>\n#include <map>\n#include <cmath>\n\nint main() {\n\n  // create a map and fill it with some (key,value) pairs\n  std::map< std::string, double > constants = { {\"e\", std::exp(1.0)},\n      {\"pi\", 4.0*std::atan(1.0) }, {\"h\", 6.6e-34} };\n\n  // subscript operator is overloaded to allow access via a key\n  std::cout << \"Value of Planck constant is \" << constants[ \"h\" ] << '\\n';\n  constants[ \"c\" ] = 299792458;\n\n  // Hmmm, what happens here? No key \"k\" exists so far!\n  std::cout << \"Value of Coulomb constant is \" << constants[ \"k\" ] << '\\n';\n\n  // find() allows to check for existance of a key; returns an iterator\n  // to the pair, if it is found\n  std::cout << \"Value of pi is \" << constants.find( \"pi\" )->second << '\\n';\n\n  // if not it returns end\n  auto it_phi = constants.find( \"phi\" );\n  if ( it_phi != constants.end() ) {\n    std::cout << \"The golden ratio is \" << it_phi->second << '\\n';\n  }\n\n  // can use at(), if we know the pair to exists, returns value for key\n  // will throw an \"out_of_range\" exception, if we were wrong\n  std::cout << \"Value of Euler constant is \" << constants.at( \"e\" ) << \"\\n\\n\";\n\n  // range-based loop\n  for ( auto& c: constants ) {\n    std::cout << \"Value of \" << c.first << \" is \" << c.second << '\\n';\n  }\n}","metadata":{"trusted":true},"execution_count":24,"outputs":[{"name":"stdout","text":"Overwriting constants.cpp\n","output_type":"stream"}],"id":"52f631d4"},{"cell_type":"code","source":"!g++ constants.cpp","metadata":{"trusted":true},"execution_count":25,"outputs":[],"id":"aaba61ba"},{"cell_type":"code","source":"!./a.out","metadata":{"trusted":true},"execution_count":26,"outputs":[{"name":"stdout","text":"Value of Planck constant is 6.6e-34\nValue of Coulomb constant is 0\nValue of pi is 3.14159\nValue of Euler constant is 2.71828\n\nValue of c is 2.99792e+08\nValue of e is 2.71828\nValue of h is 6.6e-34\nValue of k is 0\nValue of pi is 3.14159\n","output_type":"stream"}],"id":"3f9362c9"},{"cell_type":"markdown","source":"**Note:**  \nAs with ```set``` there is also a variant of ```map``` that uses hashing instead of ordered storage and is called ```unordered_map```.","metadata":{},"id":"a7e8490c"},{"cell_type":"markdown","source":"#### Algorithm\n\nThe STL supports also various algorithms that work on the entries in a container. The advantage again is that these save us implementation and will (potentially) work for various kinds of containers.\n\nWe will briefly look at two examples.","metadata":{},"id":"2032e7f2"},{"cell_type":"markdown","source":"**Example 1:** Remove double entries from a sequence","metadata":{},"id":"4c239bfa"},{"cell_type":"code","source":"%%file uniq.cpp\n\n#include <algorithm>\n#include <vector>\n#include <iostream>\n\nusing Container = std::vector<int>;\n\nvoid print( const Container& box, const std::string& note ) {\n  std::cout << \"( \";\n  for( int w: box ) std::cout << w << ' ';\n  std::cout << \") \" << note << std::endl;\n}\n  \nint main() {\n\n  Container box{ 3, 5, 2, 4, 1, 2, 1 };\n  print( box, \"<- unsorted\" );\n\n  sort( box.begin(), box.end() );\n  print( box, \"<- sorted\" );\n\n  Container::iterator last = unique( begin(box), end(box) );\n  print( box, \"<- happened in-place\" );\n\n  box.resize( distance( box.begin(), last ) );\n  print( box, \"    <- truncated to new length\" );\n}","metadata":{"trusted":true},"execution_count":27,"outputs":[{"name":"stdout","text":"Writing uniq.cpp\n","output_type":"stream"}],"id":"aed454ce"},{"cell_type":"code","source":"!g++ uniq.cpp","metadata":{"trusted":true},"execution_count":28,"outputs":[],"id":"57c92377"},{"cell_type":"code","source":"!./a.out","metadata":{"trusted":true},"execution_count":29,"outputs":[{"name":"stdout","text":"( 3 5 2 4 1 2 1 ) <- unsorted\n( 1 1 2 2 3 4 5 ) <- sorted\n( 1 2 3 4 5 4 5 ) <- happened in-place\n( 1 2 3 4 5 )     <- truncated to new length\n","output_type":"stream"}],"id":"b190c1c6"},{"cell_type":"markdown","source":"**Note:**\n\nReplacing ```vector``` by ```list``` via\n\n    using Container = std::list<int>;\n\nwill not work in this example. ```std::sort()``` is implemented to work with a **random access iterator**, which list does not provide. Instead it has its own ```list::sort()```\nand ```list::unique()``` member functions.","metadata":{},"id":"e9140c15"},{"cell_type":"markdown","source":"***\n**Example 2:** Performing reductions on an array\n\nThe STL also provides some algorithms for performing numeric operations. For these we need to include ```<numeric>```.","metadata":{},"id":"7856aa32"},{"cell_type":"code","source":"%%file accumulate.cpp\n\n#include <numeric>\n#include <vector>\n#include <iostream>\n\nint alternate( int a, int b ) {\n  static bool odd = false;  // static preserves value of local variable\n  if( odd ) {\n    odd = false;\n    return a-b;\n  }\n  else {\n    odd = true;\n    return a+b;\n  }\n}\n\nint main() {\n\n  std::vector<int> v{1, 2, 3, 4, 5};\n \n  int gs = std::accumulate( v.begin(), v.end(), 0 );\n  std::cout << \"sum is \" << gs << std::endl;\n\n  int check = std::accumulate( v.begin(), v.end(), -15 );\n  if( check == 0 ) std::cout << \"checks out\" << std::endl;\n \n  int prod = std::accumulate( v.begin(), v.end(), 1, std::multiplies<int>() );\n  std::cout << \"5! = \" << prod << std::endl;\n\n  int alt = std::accumulate( v.begin(), v.end(), 0, alternate );\n  std::cout << \"Alternating sum gives \" << alt << std::endl;\n  // 0 + 1 - 2 + 3 - 4 + 5\n}","metadata":{"trusted":true},"execution_count":30,"outputs":[{"name":"stdout","text":"Writing accumulate.cpp\n","output_type":"stream"}],"id":"bed09ecd"},{"cell_type":"code","source":"!g++ accumulate.cpp","metadata":{"trusted":true},"execution_count":31,"outputs":[],"id":"16a6d2e8"},{"cell_type":"code","source":"!./a.out","metadata":{"trusted":true},"execution_count":32,"outputs":[{"name":"stdout","text":"sum is 15\nchecks out\n5! = 120\nAlternating sum gives 3\n","output_type":"stream"}],"id":"015eb80f"},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[],"id":"1efec163"}]}
\ No newline at end of file
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "bac1d62f",
+   "metadata": {},
+   "source": [
+    "# STL - Part 2 : More Containers & Algorithms"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "efdc5616",
+   "metadata": {},
+   "source": [
+    "#### Sets"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "id": "c2848a05",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "0 appears 0 times\n",
+      "1 appears 1 times\n",
+      "2 appears 1 times\n",
+      "3 appears 0 times\n",
+      "4 appears 1 times\n",
+      "5 appears 1 times\n",
+      "6 appears 0 times\n",
+      "7 appears 1 times\n"
+     ]
+    }
+   ],
+   "source": [
+    "#include <iostream>\n",
+    "#include <set>\n",
+    "\n",
+    "std::set< int > s = {1, 7, 4, 8, 2};   // create a set container and fill it\n",
+    "\n",
+    "s.insert(5);   // insert another element\n",
+    "s.insert(4);\n",
+    "\n",
+    "// check how often an element is inside the set\n",
+    "for ( int i = 0; i < 8; ++i ) {\n",
+    "    std::cout << i << \" appears \" << s.count( i ) << \" times\\n\";\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "44573775",
+   "metadata": {},
+   "source": [
+    "**Remarks:**\n",
+    "- Although we inserted **4** twice, it is only stored once in the set data structure. Just like a mathematical set a ```std::set``` can contain a specific object only once.\n",
+    "- Hence, ```count()``` will always return either 0 or 1.\n",
+    "- This shows that ```std::set``` is no sequence container.\n",
+    "- Instead it stores its elements in a **sorted** fashion. This guarantees logarithmic complexity for element access."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "a415d236",
+   "metadata": {},
+   "source": [
+    "Of course we can store various kinds of objects in a set ..."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "id": "2213e98e",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "struct myPair {\n",
+    "  myPair( int fir, int sec ) : fir_( fir ), sec_( sec ) {};\n",
+    "  int fir_;\n",
+    "  int sec_;\n",
+    "};\n",
+    "\n",
+    "std::set< myPair > pairs; "
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "725387bc",
+   "metadata": {},
+   "source": [
+    "... but there is a caveat. Check what happens, when we try to insert an object of type ```myPair``` into the set:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "id": "51fd5597",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "In file included from input_line_5:1:\n",
+      "In file included from /srv/conda/envs/notebook/include/xeus/xinterpreter.hpp:13:\n",
+      "In file included from /srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/9.4.0/functional:49:\n",
+      "/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/9.4.0/bits/stl_function.h:386:20: error: invalid operands to binary expression ('const __cling_N54::myPair' and 'const __cling_N54::myPair')\n",
+      "      { return __x < __y; }\n",
+      "               ~~~ ^ ~~~\n",
+      "/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/9.4.0/bits/stl_tree.h:2100:13: note: in instantiation of member function 'std::less<__cling_N54::myPair>::operator()' requested here\n",
+      "          __comp = _M_impl._M_key_compare(__k, _S_key(__x));\n",
+      "                   ^\n",
+      "/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/9.4.0/bits/stl_tree.h:2153:4: note: in instantiation of member function 'std::_Rb_tree<__cling_N54::myPair, __cling_N54::myPair, std::_Identity<__cling_N54::myPair>, std::less<__cling_N54::myPair>, std::allocator<__cling_N54::myPair> >::_M_get_insert_unique_pos' requested here\n",
+      "        = _M_get_insert_unique_pos(_KeyOfValue()(__v));\n",
+      "          ^\n",
+      "/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/9.4.0/bits/stl_set.h:521:9: note: in instantiation of function template specialization 'std::_Rb_tree<__cling_N54::myPair, __cling_N54::myPair, std::_Identity<__cling_N54::myPair>, std::less<__cling_N54::myPair>, std::allocator<__cling_N54::myPair> >::_M_insert_unique<__cling_N54::myPair>' requested here\n",
+      "          _M_t._M_insert_unique(std::move(__x));\n",
+      "               ^\n",
+      "input_line_12:2:8: note: in instantiation of member function 'std::set<__cling_N54::myPair, std::less<__cling_N54::myPair>, std::allocator<__cling_N54::myPair> >::insert' requested here\n",
+      " pairs.insert( myPair(1,2) );\n",
+      "       ^\n",
+      "In file included from input_line_5:1:\n",
+      "In file included from /srv/conda/envs/notebook/include/xeus/xinterpreter.hpp:17:\n",
+      "In file included from /srv/conda/envs/notebook/include/xeus/xcomm.hpp:15:\n",
+      "In file included from /srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/9.4.0/map:60:\n",
+      "/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/9.4.0/bits/stl_tree.h:777:2: error: static_assert failed \"comparison object must be invocable with two arguments of key type\"\n",
+      "        static_assert(__is_invocable<_Compare&, const _Key&, const _Key&>{},\n",
+      "        ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n",
+      "/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/9.4.0/bits/stl_tree.h:2100:41: note: in instantiation of member function 'std::_Rb_tree<__cling_N54::myPair, __cling_N54::myPair, std::_Identity<__cling_N54::myPair>, std::less<__cling_N54::myPair>, std::allocator<__cling_N54::myPair> >::_S_key' requested here\n",
+      "          __comp = _M_impl._M_key_compare(__k, _S_key(__x));\n",
+      "                                               ^\n",
+      "/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/9.4.0/bits/stl_tree.h:2153:4: note: in instantiation of member function 'std::_Rb_tree<__cling_N54::myPair, __cling_N54::myPair, std::_Identity<__cling_N54::myPair>, std::less<__cling_N54::myPair>, std::allocator<__cling_N54::myPair> >::_M_get_insert_unique_pos' requested here\n",
+      "        = _M_get_insert_unique_pos(_KeyOfValue()(__v));\n",
+      "          ^\n",
+      "/srv/conda/envs/notebook/bin/../lib/gcc/../../x86_64-conda-linux-gnu/include/c++/9.4.0/bits/stl_set.h:521:9: note: in instantiation of function template specialization 'std::_Rb_tree<__cling_N54::myPair, __cling_N54::myPair, std::_Identity<__cling_N54::myPair>, std::less<__cling_N54::myPair>, std::allocator<__cling_N54::myPair> >::_M_insert_unique<__cling_N54::myPair>' requested here\n",
+      "          _M_t._M_insert_unique(std::move(__x));\n",
+      "               ^\n",
+      "input_line_12:2:8: note: in instantiation of member function 'std::set<__cling_N54::myPair, std::less<__cling_N54::myPair>, std::allocator<__cling_N54::myPair> >::insert' requested here\n",
+      " pairs.insert( myPair(1,2) );\n",
+      "       ^\n"
+     ]
+    },
+    {
+     "ename": "Interpreter Error",
+     "evalue": "",
+     "output_type": "error",
+     "traceback": [
+      "Interpreter Error: "
+     ]
+    }
+   ],
+   "source": [
+    "pairs.insert( myPair(1,2) );"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "2ee8f731",
+   "metadata": {},
+   "source": [
+    "**What went wrong?**\n",
+    "\n",
+    "As the set stores its elements in a **sorted** fashion it needs some way to **order** them.\n",
+    "By default the standard ```<``` relation is used.\n",
+    "\n",
+    "That does not work for our ```myPair``` data type.\n",
+    "\n",
+    "We need to define our own comparison operator for the class.\n",
+    "\n",
+    "There are plenty ways of doing that. Below we will use a free function for it."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "id": "e8c29594",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Writing demo.cpp\n"
+     ]
+    }
+   ],
+   "source": [
+    "%%file demo.cpp\n",
+    "\n",
+    "#include <iostream>\n",
+    "#include <set>\n",
+    "\n",
+    "struct myPair {\n",
+    "  myPair( int fir, int sec ) : fir_( fir ), sec_( sec ) {};\n",
+    "  int fir_;\n",
+    "  int sec_;\n",
+    "};\n",
+    "\n",
+    "// our comparison function will return true, if the sum of the squares\n",
+    "// of the values in left is smaller than that in right (problem with tie-breaking?)\n",
+    "bool cmp( const myPair& left, const myPair& right ) {\n",
+    "  int val1 = left.fir_ * left.fir_ + left.sec_ * left.sec_;\n",
+    "  int val2 = right.fir_ * right.fir_ + right.sec_ * right.sec_;\n",
+    "  return val1 < val2;\n",
+    "}\n",
+    "\n",
+    "int main() {\n",
+    "    \n",
+    "    // create two objects\n",
+    "    myPair p1( 1, 2 );\n",
+    "    myPair p2( 3, 4 );\n",
+    "\n",
+    "    // compare them\n",
+    "    std::cout << std::boolalpha;\n",
+    "    std::cout << \"p1 < p2 is \" << cmp( p1, p2 ) << std::endl;\n",
+    "    std::cout << \"p2 < p1 is \" << cmp( p2, p1 ) << std::endl;\n",
+    "\n",
+    "    // a free function in C/C++ is represented by the address of its machine code in memory;\n",
+    "    // thus, the type of argument is a function pointer;\n",
+    "    // we need to pass that info as a second template argument;\n",
+    "    // decltype returns the type of an expression\n",
+    "    std::set< myPair, decltype( cmp )* > pairs( cmp );\n",
+    "\n",
+    "    // alternatively we could do it ourselves; note that the (*) is important!\n",
+    "    // but that way is not very C++-ish\n",
+    "    // std::set< myPair, bool (*)( const myPair&, const myPair& ) > pairs( cmp );\n",
+    "    \n",
+    "    // now insertion will work\n",
+    "    pairs.insert( p1 );\n",
+    "    pairs.insert( p2 );\n",
+    "\n",
+    "    std::cout << \"insertion successful\" << std::endl;\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "id": "0a0207dd",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "!g++ demo.cpp"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "id": "68e1df4b",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "p1 < p2 is true\n",
+      "p2 < p1 is false\n",
+      "insertion successful\n"
+     ]
+    }
+   ],
+   "source": [
+    "!./a.out"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "f8b3109b",
+   "metadata": {},
+   "source": [
+    "**Note:**  \n",
+    "The STL offers a variant **```std::unordered_set```** that stores its elements in an unsorted fashion. However, that would not solve our problem. Instead of a **comparison** we then would need to implement a **hashing function**."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "59ab93ca",
+   "metadata": {},
+   "source": [
+    "***\n",
+    "The way we added the new element in the example, i.e. via\n",
+    "\n",
+    "```pairs.insert( myPair(1,2) );```\n",
+    "\n",
+    "again induced a copy operation. As with ```vector``` and ```list``` we could use ```emplace()``` instead.\n",
+    "\n",
+    "For demonstration purposes we make the constructor of ```myPair``` verbose."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "id": "bdda6c33",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Overwriting demo.cpp\n"
+     ]
+    }
+   ],
+   "source": [
+    "%%file demo.cpp\n",
+    "\n",
+    "#include <iostream>\n",
+    "#include <set>\n",
+    "\n",
+    "struct myPair {\n",
+    "  myPair( int fir, int sec ) : fir_( fir ), sec_( sec ) {\n",
+    "      std::cout << \"(\" << fir_ << \",\" << sec_ << \") constructed\" << std::endl;\n",
+    "  };\n",
+    " \n",
+    "  int fir_;\n",
+    "  int sec_;\n",
+    "};\n",
+    "\n",
+    "// our comparison function: will return true, if the square of the values\n",
+    "// in left is smaller than that in right\n",
+    "bool cmp( const myPair& left, const myPair& right ) {\n",
+    "  int val1 = left.fir_ * left.fir_ + left.sec_ * left.sec_;\n",
+    "  int val2 = right.fir_ * right.fir_ + right.sec_ * right.sec_;\n",
+    "  return val1 < val2;\n",
+    "}\n",
+    "\n",
+    "int main() {\n",
+    "    \n",
+    "    std::set< myPair, decltype( cmp )* > pairs( cmp );\n",
+    "\n",
+    "    pairs.emplace( 1, 2 );\n",
+    "    pairs.emplace( 3, 4 );\n",
+    "    pairs.emplace( 1, 2 );\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "id": "8099d1a4",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "!g++ demo.cpp"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "id": "5d491b27",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(1,2) constructed\n",
+      "(3,4) constructed\n",
+      "(1,2) constructed\n"
+     ]
+    }
+   ],
+   "source": [
+    "!./a.out"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "8e256275",
+   "metadata": {},
+   "source": [
+    "#### Associative Containers\n",
+    "\n",
+    "Quoting Wikipedia:\n",
+    "\n",
+    "> In computer science, an **associative array**, **map**, **symbol table**, or **dictionary** is an abstract data type composed of a collection of **(key, value) pairs**, such that each possible key appears at most once in the collection.\n",
+    ">\n",
+    "> Operations associated with this data type allow to:\n",
+    ">\n",
+    ">-    add a pair to the collection;\n",
+    ">-    remove a pair from the collection;\n",
+    ">-    modify an existing pair;\n",
+    ">-    lookup a value associated with a particular key.\n",
+    "\n",
+    "The STL also offers associative containers. An example is ```std::map```."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "fb3ef7bb",
+   "metadata": {},
+   "source": [
+    "Return to our example with the traffic light. Assume that we want to print the currect state of a specific traffic light. How to do that?\n",
+    "\n",
+    "Well, using an enumeration for the state we can use the classical switch-case-construct:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "id": "59839aea",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Writing ampel.cpp\n"
+     ]
+    }
+   ],
+   "source": [
+    "%%file ampel.cpp\n",
+    "\n",
+    "#include <iostream>\n",
+    "\n",
+    "typedef enum{ GREEN, YELLOW, RED, YELLOW_RED } trafficLight;\n",
+    "\n",
+    "void ampel( trafficLight tf ) {\n",
+    "\n",
+    "  switch( tf ) {\n",
+    "  case GREEN:\n",
+    "    std::cout << \"Lights are green\" << std::endl;\n",
+    "    break;\n",
+    "  case YELLOW:\n",
+    "    std::cout << \"Lights are yellow\" << std::endl;\n",
+    "    break;\n",
+    "  case RED:\n",
+    "    std::cout << \"Lights are red\" << std::endl;\n",
+    "    break;\n",
+    "  case YELLOW_RED:\n",
+    "    std::cout << \"Lights are yellow-red\" << std::endl;\n",
+    "    break;\n",
+    "  }\n",
+    "\n",
+    "}\n",
+    "\n",
+    "int main() {\n",
+    "  trafficLight tf = GREEN;\n",
+    "  ampel( tf );\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 13,
+   "id": "76c8886d",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "!g++ ampel.cpp"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 14,
+   "id": "731e7c94",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Lights are green\n"
+     ]
+    }
+   ],
+   "source": [
+    "!./a.out"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "08b68b2b",
+   "metadata": {},
+   "source": [
+    "Another (neater) way is to associate the state with a corresponding string"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 15,
+   "id": "8fe484bf",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Overwriting ampel.cpp\n"
+     ]
+    }
+   ],
+   "source": [
+    "%%file ampel.cpp\n",
+    "\n",
+    "#include <iostream>\n",
+    "#include <map>\n",
+    "\n",
+    "typedef enum{ GREEN, YELLOW, RED, YELLOW_RED } trafficLight;\n",
+    "\n",
+    "int main() {\n",
+    "\n",
+    "  std::map< trafficLight, std::string > tf2str =\n",
+    "    { { GREEN, \"green\" }, { YELLOW, \"yellow\" }, { RED, \"red\" },\n",
+    "      { YELLOW_RED, \"yellow-red\" } };\n",
+    "\n",
+    "  trafficLight tf = GREEN;\n",
+    "\n",
+    "  std::cout << \"Lights are \" << tf2str[ tf ] << std::endl;\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 16,
+   "id": "74251bd8",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "!g++ ampel.cpp"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 17,
+   "id": "5b919ca3",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Lights are green\n"
+     ]
+    }
+   ],
+   "source": [
+    "!./a.out"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b1718cdd",
+   "metadata": {},
+   "source": [
+    "Another example, demonstrating additional features of ```std::map``` (converted from Gottschling, *Forschung mit modernem C++*)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 24,
+   "id": "52f631d4",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Overwriting constants.cpp\n"
+     ]
+    }
+   ],
+   "source": [
+    "%%file constants.cpp\n",
+    "\n",
+    "#include <iostream>\n",
+    "#include <string>\n",
+    "#include <map>\n",
+    "#include <cmath>\n",
+    "\n",
+    "int main() {\n",
+    "\n",
+    "  // create a map and fill it with some (key,value) pairs\n",
+    "  std::map< std::string, double > constants = { {\"e\", std::exp(1.0)},\n",
+    "      {\"pi\", 4.0*std::atan(1.0) }, {\"h\", 6.6e-34} };\n",
+    "\n",
+    "  // subscript operator is overloaded to allow access via a key\n",
+    "  std::cout << \"Value of Planck constant is \" << constants[ \"h\" ] << '\\n';\n",
+    "  constants[ \"c\" ] = 299792458;\n",
+    "\n",
+    "  // Hmmm, what happens here? No key \"k\" exists so far!\n",
+    "  std::cout << \"Value of Coulomb constant is \" << constants[ \"k\" ] << '\\n';\n",
+    "\n",
+    "  // find() allows to check for existance of a key; returns an iterator\n",
+    "  // to the pair, if it is found\n",
+    "  std::cout << \"Value of pi is \" << constants.find( \"pi\" )->second << '\\n';\n",
+    "\n",
+    "  // if not it returns end\n",
+    "  auto it_phi = constants.find( \"phi\" );\n",
+    "  if ( it_phi != constants.end() ) {\n",
+    "    std::cout << \"The golden ratio is \" << it_phi->second << '\\n';\n",
+    "  }\n",
+    "\n",
+    "  // can use at(), if we know the pair to exists, returns value for key\n",
+    "  // will throw an \"out_of_range\" exception, if we were wrong\n",
+    "  std::cout << \"Value of Euler constant is \" << constants.at( \"e\" ) << \"\\n\\n\";\n",
+    "\n",
+    "  // range-based loop\n",
+    "  for ( auto& c: constants ) {\n",
+    "    std::cout << \"Value of \" << c.first << \" is \" << c.second << '\\n';\n",
+    "  }\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 25,
+   "id": "aaba61ba",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "!g++ constants.cpp"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 26,
+   "id": "3f9362c9",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Value of Planck constant is 6.6e-34\n",
+      "Value of Coulomb constant is 0\n",
+      "Value of pi is 3.14159\n",
+      "Value of Euler constant is 2.71828\n",
+      "\n",
+      "Value of c is 2.99792e+08\n",
+      "Value of e is 2.71828\n",
+      "Value of h is 6.6e-34\n",
+      "Value of k is 0\n",
+      "Value of pi is 3.14159\n"
+     ]
+    }
+   ],
+   "source": [
+    "!./a.out"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "a7e8490c",
+   "metadata": {},
+   "source": [
+    "**Note:**  \n",
+    "As with ```set``` there is also a variant of ```map``` that uses hashing instead of ordered storage and is called ```unordered_map```."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "2032e7f2",
+   "metadata": {},
+   "source": [
+    "#### Algorithm\n",
+    "\n",
+    "The STL supports also various algorithms that work on the entries in a container. The advantage again is that these save us implementation and will (potentially) work for various kinds of containers.\n",
+    "\n",
+    "We will briefly look at two examples."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "4c239bfa",
+   "metadata": {},
+   "source": [
+    "**Example 1:** Remove double entries from a sequence"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 27,
+   "id": "aed454ce",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Writing uniq.cpp\n"
+     ]
+    }
+   ],
+   "source": [
+    "%%file uniq.cpp\n",
+    "\n",
+    "#include <algorithm>\n",
+    "#include <vector>\n",
+    "#include <iostream>\n",
+    "\n",
+    "using Container = std::vector<int>;\n",
+    "\n",
+    "void print( const Container& box, const std::string& note ) {\n",
+    "  std::cout << \"( \";\n",
+    "  for( int w: box ) std::cout << w << ' ';\n",
+    "  std::cout << \") \" << note << std::endl;\n",
+    "}\n",
+    "  \n",
+    "int main() {\n",
+    "\n",
+    "  Container box{ 3, 5, 2, 4, 1, 2, 1 };\n",
+    "  print( box, \"<- unsorted\" );\n",
+    "\n",
+    "  sort( box.begin(), box.end() );\n",
+    "  print( box, \"<- sorted\" );\n",
+    "\n",
+    "  Container::iterator last = unique( begin(box), end(box) );\n",
+    "  print( box, \"<- happened in-place\" );\n",
+    "\n",
+    "  box.resize( distance( box.begin(), last ) );\n",
+    "  print( box, \"    <- truncated to new length\" );\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 28,
+   "id": "57c92377",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "!g++ uniq.cpp"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 29,
+   "id": "b190c1c6",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "( 3 5 2 4 1 2 1 ) <- unsorted\n",
+      "( 1 1 2 2 3 4 5 ) <- sorted\n",
+      "( 1 2 3 4 5 4 5 ) <- happened in-place\n",
+      "( 1 2 3 4 5 )     <- truncated to new length\n"
+     ]
+    }
+   ],
+   "source": [
+    "!./a.out"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e9140c15",
+   "metadata": {},
+   "source": [
+    "**Note:**\n",
+    "\n",
+    "Replacing ```vector``` by ```list``` via\n",
+    "\n",
+    "    using Container = std::list<int>;\n",
+    "\n",
+    "will not work in this example. ```std::sort()``` is implemented to work with a **random access iterator**, which list does not provide. Instead it has its own ```list::sort()```\n",
+    "and ```list::unique()``` member functions."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "7856aa32",
+   "metadata": {},
+   "source": [
+    "***\n",
+    "**Example 2:** Performing reductions on an array\n",
+    "\n",
+    "The STL also provides some algorithms for performing numeric operations. For these we need to include ```<numeric>```."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 30,
+   "id": "bed09ecd",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Writing accumulate.cpp\n"
+     ]
+    }
+   ],
+   "source": [
+    "%%file accumulate.cpp\n",
+    "\n",
+    "#include <numeric>\n",
+    "#include <vector>\n",
+    "#include <iostream>\n",
+    "\n",
+    "int alternate( int a, int b ) {\n",
+    "  static bool odd = false;  // static preserves value of local variable\n",
+    "  if( odd ) {\n",
+    "    odd = false;\n",
+    "    return a-b;\n",
+    "  }\n",
+    "  else {\n",
+    "    odd = true;\n",
+    "    return a+b;\n",
+    "  }\n",
+    "}\n",
+    "\n",
+    "int main() {\n",
+    "\n",
+    "  std::vector<int> v{1, 2, 3, 4, 5};\n",
+    " \n",
+    "  int gs = std::accumulate( v.begin(), v.end(), 0 );\n",
+    "  std::cout << \"sum is \" << gs << std::endl;\n",
+    "\n",
+    "  int check = std::accumulate( v.begin(), v.end(), -15 );\n",
+    "  if( check == 0 ) std::cout << \"checks out\" << std::endl;\n",
+    " \n",
+    "  int prod = std::accumulate( v.begin(), v.end(), 1, std::multiplies<int>() );\n",
+    "  std::cout << \"5! = \" << prod << std::endl;\n",
+    "\n",
+    "  int alt = std::accumulate( v.begin(), v.end(), 0, alternate );\n",
+    "  std::cout << \"Alternating sum gives \" << alt << std::endl;\n",
+    "  // 0 + 1 - 2 + 3 - 4 + 5\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 31,
+   "id": "16a6d2e8",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "!g++ accumulate.cpp"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 32,
+   "id": "015eb80f",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "sum is 15\n",
+      "checks out\n",
+      "5! = 120\n",
+      "Alternating sum gives 3\n"
+     ]
+    }
+   ],
+   "source": [
+    "!./a.out"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "1efec163",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "C++14",
+   "language": "C++14",
+   "name": "xcpp14"
+  },
+  "language_info": {
+   "codemirror_mode": "text/x-c++src",
+   "file_extension": ".cpp",
+   "mimetype": "text/x-c++src",
+   "name": "c++",
+   "version": "14"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/notebooks/08_Functors+Lambdas.ipynb b/notebooks/08_Functors+Lambdas.ipynb
index 90682ed36058bfe3ae5ede117cf9de88b6b2dbc3..f0c89ded37556db41667ac172757a94fe5e6f42d 100644
--- a/notebooks/08_Functors+Lambdas.ipynb
+++ b/notebooks/08_Functors+Lambdas.ipynb
@@ -222,7 +222,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 8,
+   "execution_count": 11,
    "id": "856ee747",
    "metadata": {},
    "outputs": [
@@ -230,7 +230,7 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Writing functor.cpp\n"
+      "Overwriting functor.cpp\n"
      ]
     }
    ],
@@ -264,6 +264,7 @@
     "  myPair p1( 1, 2 );\n",
     "  myPair p2( 3, 4 );\n",
     "\n",
+    "  std::cout << std::boolalpha;\n",
     "  std::cout << \"p1 < p2 is \" << cmp( p1, p2 ) << std::endl;\n",
     "  std::cout << \"p2 < p1 is \" << cmp( p2, p1 ) << std::endl;\n",
     "\n",
@@ -277,7 +278,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 9,
+   "execution_count": 12,
    "id": "4adb7f0b",
    "metadata": {},
    "outputs": [],
@@ -287,7 +288,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 10,
+   "execution_count": 13,
    "id": "f9bfde7f",
    "metadata": {},
    "outputs": [
@@ -297,8 +298,8 @@
      "text": [
       "(1,2) constructed\n",
       "(3,4) constructed\n",
-      "p1 < p2 is 1\n",
-      "p2 < p1 is 0\n",
+      "p1 < p2 is true\n",
+      "p2 < p1 is false\n",
       "(3,4) constructed\n",
       "(5,6) constructed\n"
      ]