There are two directives available to add exercises and solutions to your documents: (1) an exercise
directive; and (2) a solution
directive. The exercises are enumerated by default and can take in an optional title argument as well as be “gated” around Jupyter Notebook cells.
Same as Sphinx Exercise 🎉
The implementation and documentation for exercises and solutions is based on Sphinx Exercise, the syntax can be used interchangeably. We have reused the examples in that extension here to show off the various parts of the MyST extension.
Changes to the original extension include being able to click on the exercise label (e.g. “Exercise 1”), and having a link to that exercise anchor. We have also updated the styles from both Sphinx and Jupyter Book to be more distinct from admonitions.
You can also reference exercises with any cross-reference syntax (including the {ref}
and {numref}
roles). We recommend the markdown link syntax.
Exercise Directive¶
Example
MyST Syntax
```{exercise}
:label: my-exercise
Recall that $n!$ is read as "$n$ factorial" and defined as
$n! = n \times (n - 1) \times \cdots \times 2 \times 1$.
There are functions to compute this in various modules, but let's
write our own version as an exercise.
In particular, write a function `factorial` such that `factorial(n)` returns $n!$
for any positive integer $n$.
```
Source: QuantEcon
The following options for exercise and solution directives are supported:
label
: textA unique identifier for your exercise that you can use to reference it with a Markdown link or
{ref}
and{numref}
roles. Cannot contain spaces or special characters.class
: textValue of the exercise’s class attribute which can be used to add custom CSS or JavaScript. This can also be the optional
dropdown
class to initially hide the exercise.nonumber
: flag (empty)Turns off exercise auto numbering.
hidden
: flag (empty)Removes the directive from the final output.
Solution Directive¶
A solution directive can be included using the solution
pattern. It takes in the label of the directive it wants to link to as a required argument. Unlike the exercise
directive, the solution directive is not enumerable as it inherits numbering directly from the linked exercise. The argument for a solution is the label of the linked exercise, which is required.
Example
MyST Syntax
````{solution} my-exercise
:label: my-solution
Here's one solution.
```{code-block} python
def factorial(n):
k = 1
for i in range(n):
k = k * (i + 1)
return k
factorial(4)
```
````
Source: QuantEcon
The following options are also supported:
label
: textA unique identifier for your solution that you can use to reference it with
{ref}
. Cannot contain spaces or special characters.class
: textValue of the solution’s class attribute which can be used to add custom CSS or JavaScript.
hidden
: flag (empty)Removes the directive from the final output.
Referencing Exercises & Solutions¶
You can refer to an exercise using the standard link syntax:
[](#my-exercise)
, creates Exercise 1[{name}](#nfactorial)
[1] creates Factorial[{number}](#my-exercise)
creates 1[See Exercise](#my-exercise)
creates See Exercise
Compatibility with Sphinx Exercise
You can also refer to an exercise using the {ref}
role like {ref}`my-exercise`
, which will display the title of the exercise directive. In the event that directive does not have a title, the title will be the default “Exercise” or “Exercise {number}” like so: Exercise 1.
Enumerable directives can also be referenced through the {numref}
role like {numref}`my-exercise`
, which will display the number of the exercise directive. Referencing the above directive will display Exercise 1. In this case it displays the same result as the {ref}
role as exercise
notes are (by default) enumerated.
Furthermore, numref
can take in three additional placeholders for more customized titles:
- %s
- {number} which get replaced by the exercise number, and
- {name} by the exercise title.[1]
For example,{numref}`My custom {number} and {name} <my-exercise-label>`
.
Referencing Solutions¶
You can refer to a solution directly as well using a Markdown link or using the {ref}
role like: {ref}`my-solution`
the output of which depends on the attributes of the linked directive. If the linked directive is enumerable, the role will replace the solution reference with the linked directive type and its appropriate number like so: Solution to Exercise 1.
In the event that the directive being referenced is unenumerable, the reference will display its title: Solution to Exercise ( Factorial).
Named Exercise & Solution
If the title of the linked directive being reference does not exist, it will default to Solution to Exercise.
Unnumbered Exercise & Solution
Alternative Gated Syntax¶
To be able to be viewed as Jupyter Notebooks (e.g. in JupyterLab MyST) code-cell
directives must be at the root level of the document for them to be executed. This maintains direct compatibility with the jupyter notebook
and enables tools like jupytext
to convert between myst
and ipynb
files.
As a result executable code-cell
directives cannot be nested inside of exercises or solution directives.
The solution to this is to use the gated syntax.
Basic Syntax
```{exercise-start}
:label: ex1
```
```python
# Some code to explain the figure
```
and maybe you wish to add a figure
```{figure} https://github.com/rowanc1/pics/blob/main/beach.png
```
```{exercise-end}
```
This can also be completed for solutions with solution-start
and solution-end
directives. The solution-start
and exercise-start
directives have the same options as original directive.
Mismatched Start & End
If there are missing -start
and -end
directives, this will cause an extension error,
alongside feedback to diagnose the issue in document structure.
Hiding Directive Content¶
To visually hide the content, simply add :class: dropdown
as a directive option, similar to an admonition.
Example
Recall that is read as “ factorial” and defined as .
There are functions to compute this in various modules, but let’s write our own version as an exercise.
In particular, write a function factorial
such that factorial(n)
returns
for any positive integer .
MyST Syntax:
```{exercise}
:class: dropdown
Recall that $n!$ is read as "$n$ factorial" and defined as
$n! = n \times (n - 1) \times \cdots \times 2 \times 1$.
There are functions to compute this in various modules, but let's
write our own version as an exercise.
In particular, write a function `factorial` such that `factorial(n)` returns $n!$
for any positive integer $n$.
```
Remove Directives¶
Any specific directive can be hidden by introducing the :hidden:
option. For example, the following example will not be displayed
```{exercise}
:hidden:
This is a hidden exercise directive.
```