diff --git a/book/_toc.yml b/book/_toc.yml
index 17ebf32850e43599db649aa095b71f5c8835c0b4..32719929f6bc5cb501bcb8db98ac25a470df7c52 100644
--- a/book/_toc.yml
+++ b/book/_toc.yml
@@ -67,6 +67,7 @@ parts:
       - file: cookbook/benchmarks/benchmark_load_dont_execute.ipynb
     - file: cookbook/widgets_dont_execute.ipynb
     - file: cookbook/exercise_checking_dont_execute.ipynb
+    - file: cookbook/example_gumbel_dont_execute.ipynb
   - caption: Old Material
     chapters:
     - file: old/blank
diff --git a/book/cookbook/example_gumbel.py b/book/cookbook/example_gumbel.py
new file mode 100644
index 0000000000000000000000000000000000000000..e8fa8cf322649f6d95a9205ec715860f97eac673
--- /dev/null
+++ b/book/cookbook/example_gumbel.py
@@ -0,0 +1,35 @@
+from grading import check
+from math import isclose
+
+tolerance = 0.001
+
+# Using rel_tol is more reliable in the face of aliasing, but to fit the instructions give we use abs_total
+check_float = lambda a, b: isclose(a, b, rel_tol=0, abs_tol=tolerance)
+
+# We have to pass in the globals object since we need to have access to changes as well
+@check
+def check_example(glob):
+	mu, beta = glob["mu"], glob["beta"]
+	if (check_float(mu, 5.0) and check_float(beta, 3.0)):
+		print(f"You got the parameters right, well done! (checked with tolerance {tolerance})")
+	else:
+		print(f"Your parameters are incorrect, your inverse won't be graded until these are right. (checked with tolerance {tolerance})")
+		return 
+
+	function = glob["find_x_with_probability_p"]
+	
+	test_inputs = [(0.1, 2.49790266426), (0.2, 3.57234501402), (0.9, 11.7511019819)]
+	failed = []
+
+	for x, out in test_inputs:
+		result = function(x)
+		if not check_float(result, out):
+			failed.append((x, out, result))
+
+	if len(failed) == 0:
+		print(f"Well done, your inverse function is correct! (checked with tolerance {tolerance})")	
+	else:
+		print(f"Your function failed some tests. Keep in mind the tolerance is {tolerance}")
+		print("Failed inputs:")
+		for case in failed:
+			print(f"{case[0]} gave {case[2]}, expected {case[1]}")
\ No newline at end of file
diff --git a/book/cookbook/example_gumbel_dont_execute.ipynb b/book/cookbook/example_gumbel_dont_execute.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..023869937a18e0f5c950e4189ee7b89d35b101b5
--- /dev/null
+++ b/book/cookbook/example_gumbel_dont_execute.ipynb
@@ -0,0 +1,143 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Gumbel Distribution Exercise"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "tags": [
+     "thebe-init"
+    ]
+   },
+   "outputs": [],
+   "source": [
+    "%pip install ipywidgets\n",
+    "\n",
+    "import matplotlib.pyplot as plt\n",
+    "from math import log, e\n",
+    "import numpy as np\n",
+    "from example_gumbel import check_example"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "tags": [
+     "thebe-init"
+    ]
+   },
+   "outputs": [],
+   "source": [
+    "x_1 = 4\n",
+    "p_e_1 = 0.7523186963342055\n",
+    "x_2 = 10\n",
+    "p_e_2 = 0.17211051260760846"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def gumbel_2_points(x_1, p_e_1, x_2, p_e_2): \n",
+    "    \"\"\"Compute Gumbel distribution parameters from two points of the CDF.\n",
+    "        Arguments:\n",
+    "            x_1   (float): point one\n",
+    "            p_e_1 (float): probability of exceedance for point one\n",
+    "            x_2   (float): point two\n",
+    "            p_e_2 (float): probability of exceedance for point two\n",
+    "    \"\"\"\n",
+    "\n",
+    "    # YOUR CODE GOES HERE #\n",
+    "    beta = _\n",
+    "    mu = _\n",
+    "    #######################\n",
+    "    return mu, beta"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "mu, beta = gumbel_2_points(x_1, p_e_1, x_2, p_e_2)\n",
+    "\n",
+    "print(f\"Your mu: {mu}\\nYour beta: {beta}\")\n",
+    "\n",
+    "gumbel_distribution = lambda x: e**(-e**(-(x-mu)/beta))\n",
+    "\n",
+    "plt.title(\"Gumbel distribution\")\n",
+    "plt.ylabel(\"Cumulative probability\")\n",
+    "plt.grid(color='black', linestyle='-', linewidth=0.1)\n",
+    "plt.plot(x_1, 1-p_e_1, 'ro')\n",
+    "plt.annotate(\"Point 1\", (x_1 + 0.4, 1-p_e_1-0.03))\n",
+    "plt.plot(x_2, 1-p_e_2, 'ro')\n",
+    "plt.annotate(\"Point 2\", (x_2 + 0.4, 1-p_e_2-0.03))\n",
+    "x_axis = np.arange(0, 20, 0.1)\n",
+    "plt.plot(x_axis, np.vectorize(gumbel_distribution)(x_axis))\n",
+    "plt.show()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def find_x_with_probability_p(p): \n",
+    "    \"\"\" Compute point in the gumbel distribution for which the CDF is p\n",
+    "        Use the global variables mu and beta defined above!\n",
+    "    \"\"\"\n",
+    "    # YOUR CODE GOES HERE #\n",
+    "    p = _\n",
+    "    #######################\n",
+    "    return p"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "tags": [
+     "thebe-remove-input-init"
+    ]
+   },
+   "outputs": [],
+   "source": [
+    "check_example(globals())"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3 (ipykernel)",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.11.2"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/book/cookbook/grading.py b/book/cookbook/grading.py
new file mode 100644
index 0000000000000000000000000000000000000000..a4c16360d38ae02c082c7103503958ceba948d7a
--- /dev/null
+++ b/book/cookbook/grading.py
@@ -0,0 +1,13 @@
+import ipywidgets as widgets
+from IPython.display import display
+
+def check(f):
+	def wrapper(*args, **kwargs):
+		output = widgets.Output()
+		button = widgets.Button(description="Check answer")
+		@output.capture(clear_output=True,wait=True)
+		def _inner_check(button):
+			f(*args, **kwargs)
+		button.on_click(_inner_check)
+		display(button, output)
+	return wrapper
\ No newline at end of file