diff --git a/puzzles/Crack_The_Code.ipynb b/puzzles/Crack_The_Code.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..d31ac401215ba4664482b4eef03d439218439331
--- /dev/null
+++ b/puzzles/Crack_The_Code.ipynb
@@ -0,0 +1,194 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Crack the Code Puzzle\n",
+    "\n",
+    "Use `:help` to get an overview for the jupyter notebook commands. If you need more insight on how to use this tool, consider reading *ProB Jupyter Notebook Overview*.\n",
+    "\n",
+    "A while ago a member of our team stumbled across this puzzle in a mailing list.\n",
+    "We took a look at it and found it was very suitable to be represented in a ProB Jupyter Notebook. \n",
+    "This is the puzzle: \n",
+    "\n",
+    "<img src=\"https://raw.githubusercontent.com/williamokano/lock-challenge-solver/master/assets/challenge.png\" width=400 height=400 />\n",
+    "\n",
+    "To solve this puzzle, we have to think about a way to represent this lock as a machine.\n",
+    "We chose to represent each digit of the code in a Digits function. This function enables us to place some assertions about the correct digits that we take from the hints on the picture. Additionally we make assertions about the correctly placed digits and ,eventually, we come to a solution that is stored in our Digits constant.\n",
+    "\n",
+    "To access the constant from the machine, we have to set it up with `:constants` and initialize the machine with `:init`."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "Loaded machine: LockChallenge"
+      ]
+     },
+     "execution_count": 1,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "::load \n",
+    "MACHINE LockChallenge\n",
+    "// https://stackoverflow.com/questions/42373479/lock-challenge-in-prolog/\n",
+    "CONSTANTS Digits\n",
+    "PROPERTIES\n",
+    " // A numeric Lock has a 3 digit key:\n",
+    " Digits : 1..3 --> 0..9 & \n",
+    "\n",
+    " // Hints \n",
+    " // [6,8,2] : one number is correct and well-placed\n",
+    " // [6,1,4]: one number is correct but wrongly placed\n",
+    " // [2,0,6]: two numbers are correct but wrongly placed\n",
+    " // [7,3,8]: nothing is correct\n",
+    " // [7,8,0]: one number is correct but wrongly placed\n",
+    " \n",
+    " // Assertions about correct digits:\n",
+    " card(ran(Digits) /\\ {6,8,2})=1 & \n",
+    " card(ran(Digits)/\\{6,1,4})=1 &\n",
+    " card(ran(Digits)/\\{2,0,6})=2 &\n",
+    " ran(Digits) /\\ {7,3,8} = {} &\n",
+    " card(ran(Digits)/\\{7,8,0})=1 &\n",
+    "\n",
+    " // Assertions about correctly placed digits\n",
+    " card(Digits /\\ [6,8,2])=1 &\n",
+    " (Digits /\\ [6,1,4])={} &\n",
+    " (Digits /\\ [2,0,6])={} &\n",
+    " (Digits /\\ [7,8,0])={}\n",
+    "END"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "Machine constants set up using operation 0: $setup_constants()"
+      ]
+     },
+     "execution_count": 8,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    ":constants"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "Machine initialised using operation 1: $initialise_machine()"
+      ]
+     },
+     "execution_count": 9,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    ":init"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "As we can see when we use the `:browse` functionality, our constant Digits can be called now, by simply typing it in."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "Machine: LockChallenge\n",
+       "Sets: (none)\n",
+       "Constants: Digits\n",
+       "Variables: (none)\n",
+       "Operations: "
+      ]
+     },
+     "execution_count": 10,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    ":browse"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/markdown": [
+       "$\\{(1\\mapsto 0),(2\\mapsto 4),(3\\mapsto 2)\\}$"
+      ],
+      "text/plain": [
+       "{(1↦0),(2↦4),(3↦2)}"
+      ]
+     },
+     "execution_count": 12,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "Digits"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "This means our solution for the crack the code puzzle is 0, 4, 2. If you are interested in the runtime of the operations, you can use `:time` before each operation to track it."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "ProB 2",
+   "language": "prob",
+   "name": "prob2"
+  },
+  "language_info": {
+   "codemirror_mode": "prob2_jupyter_repl",
+   "file_extension": ".prob",
+   "mimetype": "text/x-prob2-jupyter-repl",
+   "name": "prob"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}