Practicing algorithms using Polyglot Notebooks - part 1 (setup)
Tags: csharp, dotnet, algorithms
Published: 2022-12-28 21:59:45

There are many ways to practice algorithms: using online editors or by writing console apps and even more complicated programs with unit tests. You can also practice it on LeetCode.

I would like to show you tools I use to write and resolve algorithmic problems. I hope you’ll find it useful too.

> I'm .NET developer and I will focus on C#/.NET, but you can use it for JavaScript as well.

## Polyglot Notebooks (formerly .NET Interactive)

![Polyglot Notebooks extension](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2751ymojfitj20s7lfsg.png)
Polyglot Notebooks can be used for practicing algorithms. In this article I will show you how to install, configure and troubleshoot Polyglot Notebooks.

## Installation

**Polyglot Notebooks** is a VS Code extension. To use it you need to:
1. Install the latest [.NET 7 SDK](https://dotnet.microsoft.com/en-us/download)
1. Install the **Polyglot Notebooks** extension from the [VS Code marketplace](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode).

## Getting started - create new notebook
To create a new polyglot notebook, open the Command Palette(`Ctrl+Shift+P`) on Windows or (`Cmd+Shift+P`) on MacOS, and select `Polyglot Notebook: Create new blank notebook` -> `Create as .dib` -> `C#`

In the new cell write: 
```csharp
$"Hello world at {DateTime.Now}".Display();
```
and press `CTRL+Enter` to execute it. You can also execute current cell by clicking the *play* icon.

The `.Display()` method is a special extension method which shows the result in an output cell. It’s available only in Polyglot Notebook. 
In the above example it is the same as writing 
```csharp
Console.WriteLine($"Hello world at {DateTime.Now}")
```

There are two types of cells: *code* and *markdown*.

![Polyglot notebook - code cell](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/662b8p2y656pv5qlf6zv.png)

You can add them by clicking + in the top bar buttons (1) or the one appearing on hover cell (2).

At the bottom right corner of each cell (3), you can see if this is a markdown cell or code cell with its language. 

### Reusing previous cells

Variables, methods and classes from previous cells can be accessed in next cells but only if you execute the previous cells first.


![polyglot notebooks - previous values](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wzhrj0ra7zn8m0zyknf8.png)

If you don't, variables will not be available. Similarly, if you change values or method implementation in previous cells without executing, then only old values will be available in next cells.

![polyglot notebooks - previous values error](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7lzped6n6zixmyfnsk9l.png)

## Configuration

The default configuration is good enough to start working with the notebooks.  Below, I share some overrides that I think will make your work with Polyglot Notebooks much easier.

### Create workspace

In the same folder where your notebook is placed, create a VS Code workspace file. I will name it `dotnet.code-workspace`. 
You can use [mine](https://gist.github.com/kkoziarski/a52091e8a72a638d53d3efacaf340425#file-dotnet-code-workspace):

```json
{
	"folders": [
		{
			"path": "."
		}
	],
	"settings": {
		"omnisharp.enableAsyncCompletion": true,
		"omnisharp.useModernNet": true,
		"interactiveWindow.collapseCellInputCode": "always",
		"notebook.showFoldingControls": "always",
		"notebook.cellToolbarVisibility": "hover",
		"notebook.cellFocusIndicator": "border",
		"notebook.diff.ignoreMetadata": false,
		"notebook.diff.ignoreOutputs": true,
		"notebook.dragAndDropEnabled": false,
		"notebook.lineNumbers": "on",
		"notebook.outline.showCodeCells": true,
		"notebook.diff.enablePreview": false,
		"notebook.consolidatedOutputButton": false,
		"notebook.compactView": false,
		"notebook.output.textLineLimit": 50,
		"vsicons.associations.files": [
			{ "icon": "pddl_happenings", "extensions": ["dib"], "format": "svg" }
		],
		"files.exclude": {
			"**/.gitattributes": true,
			"**/.gitignore": true,
			"**/*.code-workspace": true
		}
	},
	"extensions": {
		"recommendations": [
			"vscode-icons-team.vscode-icons",
			"ms-dotnettools.dotnet-interactive-vscode",
		]
	}
}
```
There are some settings for `notebook.*` that I prefer, but it's up to you to experiment with those settings.

As you can see, there is also a recommended `vscode-icons` extension. This is to set an icon for `.dib` files:
```json
"vsicons.associations.files": [
    { "icon": "pddl_happenings", "extensions": ["dib"], "format": "svg" }
]
```
The result will be: 
![polyglot notebook icon](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1vema6jw2cfocz2su9p6.png)

### Add some keyboard shortcuts

I recommend adding some keyboard shortcuts to make it easier to operate notebook cells. Open the Command Palette(`Ctrl+Shift+P`) on Windows or (`Cmd+Shift+P`) on MacOS, and type `Preferences: Open Keyboard Shortcuts (JSON)`, then add the following configuration

```json
{
    "key": "o",
    "command": "notebook.cell.collapseCellInput",
    "when": "notebookCellListFocused && !inputFocus && !notebookCellInputIsCollapsed"
},
{
    "key": "o",
    "command": "notebook.cell.expandCellInput",
    "when": "notebookCellInputIsCollapsed && notebookCellListFocused"
},
{
    "key": "q",
    "command": "notebook.cell.collapseCellInput",
    "when": "notebookCellListFocused && !inputFocus && !notebookCellInputIsCollapsed"
},
{
    "key": "q",
    "command": "notebook.cell.expandCellInput",
    "when": "notebookCellInputIsCollapsed && notebookCellListFocused"
},
{
    "key": "w",
    "command": "notebook.cell.clearOutputs",
    "when": "notebookCellEditable && notebookCellHasOutputs && notebookEditable && notebookEditorFocused && !inputFocus"
},
```
This will basically allow you collapse/expand cells by simply pressing `o` or `q` and clear cell output by pressing `w`

### .gitignore

Set line ending for `*.dib` files:

```git
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto

# Never modify line endings of dib files
*.dib text eol=lf
```


## Troubleshooting

### Infinity loop

While practicing algorithms, it is very likely that you will write an infinity loop like below.

![polyglot notebooks - infinity loop](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/00wg1dpqb2wycuenx2rh.png)

Unfortunately, the *stop* button (1) doesn't work in that case and will not stop executing the cell. To stop an execution, you need to click *Restart* button on the top (2) or open Command Palette(`Ctrl+Shift+P`) and type `Polyglot Notebook: Restart the current notebook's kernel`. In that case, variables from previous cells will not be available and you will need to execute the previous cells again.

### Broken layout
Sometimes when you open a bigger notebook with many code and markdown cells you can get a broken view like this:

![polyglot notebooks - broken layout](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pza4tubq3nl5m44lap72.png)

To fix this you need to collapse all cell inputs by opening Command Palette(`Ctrl+Shift+P`) and typing `Notebook: Collapse All Cell Inputs`. You can then expand all cell inputs if you need to.

Next post [Practicing algorithms using Polyglot Notebooks - part 2 - introduction](https://dev.to/kkoziarski/practicing-algorithms-using-polyglot-notebooks-part-2-introduction-1egd)

Gist for this article can be found [here](https://gist.github.com/kkoziarski/a52091e8a72a638d53d3efacaf340425)