diff --git a/notebooks/07_STL_part2.ipynb b/notebooks/07_STL_part2.ipynb
index 8ab29aaf27b52f9aecd121e0c83462150f96ee7d..4d6b12709336d15a515e8c0a59fa05e8cefdc287 100644
--- a/notebooks/07_STL_part2.ipynb
+++ b/notebooks/07_STL_part2.ipynb
@@ -18,25 +18,10 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 2,
+   "execution_count": null,
    "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"
-     ]
-    }
-   ],
+   "outputs": [],
    "source": [
     "#include <iostream>\n",
     "#include <set>\n",
@@ -58,7 +43,7 @@
    "metadata": {},
    "source": [
     "**Remarks:**\n",
-    "- Although we inserted **4** twice it is only stored once in the set datastructure. Just like a mathematical set a ```std::set``` can contain a specific object only once.\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."
@@ -74,7 +59,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 3,
+   "execution_count": null,
    "id": "2213e98e",
    "metadata": {},
    "outputs": [],
@@ -97,9 +82,11 @@
    ]
   },
   {
-   "cell_type": "markdown",
-   "id": "e62cf3d6",
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "a84d9620",
    "metadata": {},
+   "outputs": [],
    "source": [
     "pairs.insert( myPair(1,2) );"
    ]
@@ -109,32 +96,24 @@
    "id": "2ee8f731",
    "metadata": {},
    "source": [
-    "What went wrong?\n",
+    "**What went wrong?**\n",
     "\n",
-    "As the set stores its elements in an **sorted** fashion it needs some way to **order** them.\n",
-    "By default a ```<``` relation is used.\n",
+    "As the set stores its elements in a **sorted** fashion it needs some way to **order** them.\n",
+    "By default that standard ```<``` relation is used.\n",
     "\n",
-    "That does not work for our ```pair``` datatype.\n",
+    "That does not work for our ```pair``` data type.\n",
     "\n",
-    "Need to define a comparison operator for the class.\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": 16,
+   "execution_count": null,
    "id": "e8c29594",
    "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Overwriting demo.cpp\n"
-     ]
-    }
-   ],
+   "outputs": [],
    "source": [
     "%%file demo.cpp\n",
     "\n",
@@ -147,8 +126,8 @@
     "  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",
+    "// our comparison function will return true, if the sum of the squares\n",
+    "// of the values 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",
@@ -166,7 +145,8 @@
     "    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",
-    "    // we can pass that info as a second template argument;\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",
@@ -174,13 +154,13 @@
     "    pairs.insert( p1 );\n",
     "    pairs.insert( p2 );\n",
     "\n",
-    "    std::cout << \"done with set demo\" << std::endl;\n",
+    "    std::cout << \"insertion successful\" << std::endl;\n",
     "}"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 17,
+   "execution_count": null,
    "id": "0a0207dd",
    "metadata": {},
    "outputs": [],
@@ -190,20 +170,10 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 18,
+   "execution_count": null,
    "id": "68e1df4b",
    "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "p1 < p2 is 1\n",
-      "p2 < p1 is 0\n",
-      "done with set demo\n"
-     ]
-    }
-   ],
+   "outputs": [],
    "source": [
     "!./a.out"
    ]
@@ -227,23 +197,17 @@
     "\n",
     "```pairs.insert( myPair(1,2) );```\n",
     "\n",
-    "again induced a copy operation. As with ```vector``` and ```list``` we could use ```emplace()``` instead."
+    "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": 37,
+   "execution_count": null,
    "id": "bdda6c33",
    "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Overwriting demo.cpp\n"
-     ]
-    }
-   ],
+   "outputs": [],
    "source": [
     "%%file demo.cpp\n",
     "\n",
@@ -279,7 +243,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 38,
+   "execution_count": null,
    "id": "8099d1a4",
    "metadata": {},
    "outputs": [],
@@ -289,20 +253,10 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 39,
+   "execution_count": null,
    "id": "5d491b27",
    "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "(1,2) constructed\n",
-      "(3,4) constructed\n",
-      "(1,2) constructed\n"
-     ]
-    }
-   ],
+   "outputs": [],
    "source": [
     "!./a.out"
    ]
@@ -314,9 +268,9 @@
    "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. Not to be confused with Associative Processors\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",
@@ -325,22 +279,387 @@
     ">-    modify an existing pair;\n",
     ">-    lookup a value associated with a particular key.\n",
     "\n",
-    "    \n",
-    "    "
+    "The STL also offers associative containers. An example is ```std::map```."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "a942d3bd",
+   "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": null,
-   "id": "f6269079",
+   "id": "59839aea",
    "metadata": {},
    "outputs": [],
-   "source": []
+   "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": null,
-   "id": "59839aea",
+   "id": "5847cc0d",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "!g++ ampel.cpp"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "6a1163c9",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "!./a.out"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e5b29324",
+   "metadata": {},
+   "source": [
+    "Another (neater) way is to associate the state with a corresponding string"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "e020ca91",
+   "metadata": {},
+   "outputs": [],
+   "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": null,
+   "id": "03890f8b",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "!g++ ampel.cpp"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "bfd20e03",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "!./a.out"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "2919cfda",
+   "metadata": {},
+   "source": [
+    "Another example, demonstrating additional features of ```std::map``` (converted from Gottschling, *Forschung mit modernem C++*)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "e46017ba",
+   "metadata": {},
+   "outputs": [],
+   "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": null,
+   "id": "c6102380",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "!g++ constants.cpp"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "2d71c79e",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "!./a.out"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "26214da5",
+   "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": "afd6c8a0",
+   "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": "fe55e848",
+   "metadata": {},
+   "source": [
+    "**Example 1:** Remove double entries from a sequence"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "a307aade",
+   "metadata": {},
+   "outputs": [],
+   "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": null,
+   "id": "f2e2c4d5",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "!g++ uniq.cpp"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "b90a9b8a",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "!./a.out"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "f52ee84c",
+   "metadata": {},
+   "source": [
+    "**Note:**\n",
+    "\n",
+    "Replacing ```vector``` by ```list``` via\n",
+    "\n",
+    "    using Container = std::vector<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": "e435d1ec",
+   "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": null,
+   "id": "ecfa4c0a",
+   "metadata": {},
+   "outputs": [],
+   "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": null,
+   "id": "c9c3cb86",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "!g++ accumulate.cpp"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "499d6af6",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "!./a.out"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "dc2715fd",
    "metadata": {},
    "outputs": [],
    "source": []