Here’s an example of how I organize problem sets in a notebook (click to enlarge). I use one notebook for each section and embed them in a OneNote page with the problem descriptions, as well as any illustrations or written work.

Note that each problem occupies one cell—this is to facilitate the next point:

Put this in an initialization cell to scope variables to within one problem:

```
SetOptions[EvaluationNotebook[], CellContext -> CellGroup]
```

I usually want any values in the output to have names associated with them to keep everything straight. Put this in an initialization cell:

```
SetAttributes[saveSet, HoldAll];
saveSet[form : Set[var_, _]] := (lastSet = ToString@Unevaluated@var; form);
saveSet[form : ___] := (lastSet =.; form)
$Pre = saveSet;
$Post = (If[ValueQ@lastSet, Row[{lastSet, " = ", #}], #]) &;
```

Before

and after:

`Solve`

and `NSolve`

are amazingly useful; they’ll get you through a majority of problems in statics, dynamics, circuits—anything that ends up being a big linear system. We already know we can do algebra; let’s let the CS people flex on us with their work in the crazy-deep world of CASs (Wolfram has a short overview of how they handle algebra and calculus).

Mathematica’s functions (and their error messages) aren’t always the most user friendly, though. If they return anything, they always return a matrix with one solution per row. When I’m doing homework I usually paste a screenshot of the work in MMA into my notes, and a big Mathematica vector kind of ruins whatever kind of readability vibe we’re going for there.

A quick macro helps clean that up a lot. It doesn’t work for `Reduce`

, but if I end up needing something for that I’ll add it here.

```
Prett`y = (# // Flatten // Column) &;
NPrett`y = (# // N // Prett`y) &;
```

It took me a long time to realize that the above doesn’t align solutions at the arrows.

Try this instead:

```
Prett`y[sol_] := Grid[
(# /. (a_ -> c_) :> {a, "\[Rule]", c} &) /@ Flatten@sol,
Alignment -> {{Right, Left, Left}}
]
```

Also, my notebook template now includes the helpers `ENPrett`y`

and `SPrett`y`

to convert to engineering and scientific notation.

Why the funny name? I put these in an initialization cell, so they’re defined for the whole notebook; but then I set `CellContext→CellGroup`

, so they aren’t in scope for any of the problems. So we just use fully qualified names to get the `y`

function out of the `Prett`

namespace, mostly because I haven’t found another way to inject globals into each cell context. And `Prett`y`

is easy enough to type.

`Solve`

and `Reduce`

Ohh boy, this can go on and on. Coming soon

Make a workbook template (or download mine: QuizWorkbookTemplate.nb) and add the following lines to `$InstallationDirectory\SystemFiles\FrontEnd\TextResources\Windows\MenuSetup.tr`

:

```
Menu["Mathematica",
{
Menu["&File",
{
Menu["&New",
{
MenuItem["&Notebook", "New", MenuKey["n", Modifiers->{"Control"}]],
>> Delimiter,
>> MenuItem["&Quiz Workbook", KernelExecute[GenerateDocument["path\\to\\template.nb"]], MenuEvaluator -> Automatic, Method -> "Queued", MenuKey["q", Modifiers->{"Control"}]],
>> Delimiter,
MenuItem["St&yled Notebook...", FrontEndExecute[{FrontEnd`NotebookOpen[FrontEnd`FindFileOnPath["StylesheetChooser.nb", "PalettePath"]]}]],
```

(replace `"path\\to\\template.nb"`

in `GenerateDocument`

)

This adds a menu item accessible by `alt-f→n→q`

or `ctrl-q`

; you can change these shortcuts on the `MenuItem`

line.

The default `[esc] ... [esc]`

sequence for Greek letters and special symbols is too far away from the home row. Use this AutoHotkey script to move the `esc`

key under your fourth finger. This is great for Vim too, and probably the only thing my `capslock`

key has ever been used for.
(download script)

```
SetTitleMatchMode, 2 ; Select any window that partially matches
#IfWinActive, Wolfram Mathematica
Capslock::Esc
```

After you’ve installed AutoHotkey and saved the script somewhere, place a shortcut to it in one of the startup folders (Windows 10):

`C:\Users\<your account>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup`

or

`C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp`

See Wolfram.com for a complete list of aliases available by default. Many of these are more useful than just naming variables. Some of my favorites are

`deg`

to dimension an angle
`ee`

for Euler's number and `p`

for π
`inf`

inity
`sum`

s and `prod`

ucts
(use

`[ctrl-4]`

and `[ctrl-6]`

to enter the lower and upper limits)
`lim`

(use `[ctrl-4]`

to enter the independent variable)
`int`

and `dd`

for integrals and differentials
(

`[ctrl-5]`

and `[ctrl-6]`

for lower and upper limits)
`tr`

anspose
`cross`

product
The apostrophe and backtick characters are reserved in Mathematica, so we can’t directly type a variable name that includes a prime. We can, however, rebind the `[esc] ' [esc]`

(apostrophe) shortcut to enter the unicode character *Modifier Letter Apostrophe*, which isn’t reserved by the language. Thanks to Jens on StackExchange for this one.

```
SetOptions[EvaluationNotebook[],
InputAliases ->
DeleteDuplicates@
Join[{"'" -> FromCharacterCode[700]},
InputAliases /.
Quiet[Options[EvaluationNotebook[], InputAliases]] /.
InputAliases -> {}]]
```

A free bonus for using this character is that it doesn’t look like any reserved character in MMA’s default font, so it won’t hurt readability too much if you know it’s being used.

`Solve`

`Solve`

and its kin will output SI units by default, even if `$UnitSystem`

is set to `Imperial`

.

There are a couple of workarounds I’ve used for this:

```
Solve[{
...
}, {...}] /. q_Quantity -> UnitConvert[q, "Imperial"]
```

The `$Post`

variable is applied to every output expression before it’s displayed.

```
$Post = # /. q_Quantity -> UnitConvert[q, $UnitSystem] &;
Solve[...]
```

`$UnitSystem`

is derived from your locale; you can also use `"SI"`

, `"Metric"`

, or `"Imperial"`

.

In the previous section we echoed variable assignments with the name of the variable; here we combine that with automatic unit conversion for the whole notebook.

```
ShowVariableNames = (If[ValueQ@lastSet, Row[{lastSet, " = ", #}], #]) &;
$Post = (# /. q_Quantity -> UnitConvert[q, "Imperial"] \
/. Quantity[x_, "BTU"] -> UnitConvert[Quantity[x, "BTU"], "ft*lbf"] &) \
// ShowVariableNames;
```

Note that we also convert from `BTU`

to `ft·lbf`

.

If we put the following in an initialization cell then we can set a different automatic conversion for each problem:

```
Use`SI := $Post = (# /. q_Quantity -> UnitConvert[q, "SI"] &)
// ShowVariableNames;
Use`FPS := $Post = (# /. q_Quantity -> UnitConvert[q, "Imperial"]
/. Quantity[x_, "BTU"] -> UnitConvert[Quantity[x, "BTU"], "ft*lbf"] &)
// ShowVariableNames;
```

These macros are included in my quiz/homework template.

`Hz`^{2}

to `s`^{-2}

in accelerations
Using inverse seconds in equations of acceleration or derivatives can lead to funny output like `10 m Hz^2`

. When this happens I use

```
$Post = (# /. Quantity[x_, "Hertz"^(k_: 1)*y_] -> Quantity[x, "Seconds"^-k*y]) &;
```

Solving big linear systems is one of the more useful things Mathematica can do for engineering homework. I prefer to include units in these systems as a guard against certain easy mistakes. Entering units in MMA is a huge chore, though. The easiest method I’ve found is using `[ctrl-=]`

to use natural language processing through Wolfram Alpha; there’s also the Automatic Units package, but I think it’s still too verbose.

Using the natural language input in MMA is pretty clunky: one keystroke to open the entry, type the value and unit suffix, make sure you enter `12volt`

because `12V`

is an airport, press right, wait for the web request to return, press `[ctrl-shift-left]`

to select the block, and finally `[ctrl-shift-enter]`

to evaluate in place. And the box it renders is actually a container, so your arrow keys and text selection don’t work as you expect anymore: the cursor descends into the container instead of stepping over it, and if you click and drag from outside the box, you can’t select any part of the value or unit independently. When we’re doing huge systems for circuit analysis and every constant has a unit, we end up spending most of our time playing with the unit entry box.

The alias below lets you type a unit suffix that’s dissociated from its value, so it behaves like a character and doesn’t interrupt the flow of text navigation. The workflow for giving a value units of Ohms becomes `[esc] oh [esc]`

.

```
{"oh" -> InterpretationBox[
TemplateBox[{"\[NegativeThinSpace]",
"\"\[CapitalOmega]\"\[NegativeThinSpace]", "ohms"}, "Quantity"],
Quantity["Ohms"], Selectable -> False, Editable -> False,
SyntaxForm -> Mod]},
```

Let’s break it down:

`{"oh" -> ...}`

creates the rule for `oh`

to be replaced by our box; we’ll include this in our notebook’s `InputAliases`

to get access to the `[esc]oh[esc]`

shortcut.

`InterpretationBox`

defines a 2D renderable element that has one form when displayed and another form when evaluated.

`TemplateBox`

creates a `Quantity`

box with the first list as arguments (these are: value, unit symbol, tooltip string). This lets us use the built-in stylesheet so our box has the same standard form as `Quantity`

. Because it’s wrapped in an InterpretationBox, this `TemplateBox`

will never be evaluated and is just for styling.
The `\[NegativeThinSpace]`

hacks out the margins added by the stylesheet so our box fits more neatly into text.

The second argument to `InterpretationBox`

means that our box will be evaluated as a `Quantity`

with magnitude one.

Setting `Selectable`

and `Editable`

to false cause our box to behave as a single glyph; without these the cursor will descend into the container and the arrow keys won’t behave as you expect.

`SyntaxForm`

gives our box the same evaluation precedence as the actual `Quantity`

box.

We can include this with the alias for primed variables by adding the rules (in curly brackets) as arguments to `Join`

:

```
SetOptions[EvaluationNotebook[], InputAliases -> DeleteDuplicates@Join[
{"'" -> FromCharacterCode[700]},
{"oh" -> InterpretationBox[...]},
{"V" -> ...}
...
```

Units available in my quiz/homework template:

- oh → ohms
- koh → kilohms
- A → amperes
- mA → milliamperes
- V → volts
- mV → millivolts