This is a demo file for a working prototype of using pseudocode.js in a R Markdown document. Code could be downloaded using the upper right download button.
How to use pseudocode.js
This is what we need to include in the header of the doc:
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {
inlineMath: [['$','$'], ['\\(','\\)']],
displayMath: [['$$','$$'], ['\\[','\\]']],
processEscapes: true,
processEnvironments: true,
}
});
</script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/pseudocode@latest/build/pseudocode.min.css">
<script src="https://cdn.jsdelivr.net/npm/pseudocode@latest/build/pseudocode.min.js"></script>
This is in a file head.html
and we insert it using `yaml html_document: includes: in_header: head.html
Mathajx is already configured in a R Markdown doc but Mathjax config seems to be required for Math to work inside the algorithm environment
Elements containing the code are rendered based on a selector using a JS function. We’ll use the fenced code attributes features to render all pre
with an expected algorigthm
attributes. We’ll also set some options - this can be change.
This is will we’ll add this JS code using a js
knitr block:
window.addEventListener('load', (event) => {
elem = document.querySelectorAll(".algorithm")
elem.forEach(e => {
pseudocode.renderElement(e, {lineNumber: true, lineNumberPunc: ' '});
})
});
We could also add it in the previous head.html
. This will run pseudocode.renderElement()
on each element of class algorithm
and replace the whole element
With this, everything should work.
Mathjax is still working
A block \[
1+1
\]
or inline math like \(\alpha = x/y\)
Inserting an algorithm environment
You can use an algorithm code block using syntax from pseudocode.js by setting the fenced div attribute algorithm
as below
```{.algorithm}
% This quicksort algorithm is extracted from Chapter 7, Introduction to Algorithms (3rd edition)
\begin{algorithm}
\caption{Quicksort}
\begin{algorithmic}
\PROCEDURE{Quicksort}{$A, p, r$}
\IF{$p < r$}
\STATE $q = $ \CALL{Partition}{$A, p, r$}
\STATE \CALL{Quicksort}{$A, p, q - 1$}
\STATE \CALL{Quicksort}{$A, q + 1, r$}
\ENDIF
\ENDPROCEDURE
\PROCEDURE{Partition}{$A, p, r$}
\STATE $x = A[r]$
\STATE $i = p - 1$
\FOR{$j = p$ \TO $r - 1$}
\IF{$A[j] < x$}
\STATE $i = i + 1$
\STATE exchange
$A[i]$ with $A[j]$
\ENDIF
\STATE exchange $A[i]$ with $A[r]$
\ENDFOR
\ENDPROCEDURE
\end{algorithmic}
\end{algorithm}
```
This would render to
% This quicksort algorithm is extracted from Chapter 7, Introduction to Algorithms (3rd edition)
\begin{algorithm}
\caption{Quicksort}
\begin{algorithmic}
\PROCEDURE{Quicksort}{$A, p, r$}
\IF{$p < r$}
\STATE $q = $ \CALL{Partition}{$A, p, r$}
\STATE \CALL{Quicksort}{$A, p, q - 1$}
\STATE \CALL{Quicksort}{$A, q + 1, r$}
\ENDIF
\ENDPROCEDURE
\PROCEDURE{Partition}{$A, p, r$}
\STATE $x = A[r]$
\STATE $i = p - 1$
\FOR{$j = p$ \TO $r - 1$}
\IF{$A[j] < x$}
\STATE $i = i + 1$
\STATE exchange
$A[i]$ with $A[j]$
\ENDIF
\STATE exchange $A[i]$ with $A[r]$
\ENDFOR
\ENDPROCEDURE
\end{algorithmic}
\end{algorithm}
Another one
```{.algorithm}
\begin{algorithm}
\caption{The original \textsf{Relief} algorithm for ranking predictor variables in classification models with two classes.}
\begin{algorithmic}
\STATE Initialize the predictor scores $S_j$ to zero;
\FOR{$i = 1\ldots m$ randomly selected training set samples ($R_i$)}
\STATE Find the nearest miss and hit in the training set;
\FOR{$j = 1\ldots p$ predictor variables}
\STATE Adjust the score for each predictor based on the proximity of $R_j$ to the nearest miss and hit:\\
$S_j = S_j - diff_j(R_j, Hit)^2/m + diff_j(R_j, Miss)^2/m$;
\ENDFOR
\ENDFOR
\end{algorithmic}
\end{algorithm}
```
\begin{algorithm}
\caption{The original \textsf{Relief} algorithm for ranking predictor variables in classification models with two classes.}
\begin{algorithmic}
\STATE Initialize the predictor scores $S_j$ to zero;
\FOR{$i = 1\ldots m$ randomly selected training set samples ($R_i$)}
\STATE Find the nearest miss and hit in the training set;
\FOR{$j = 1\ldots p$ predictor variables}
\STATE Adjust the score for each predictor based on the proximity of $R_j$ to the nearest miss and hit:\\
$S_j = S_j - diff_j(R_j, Hit)^2/m + diff_j(R_j, Miss)^2/m$;
\ENDFOR
\ENDFOR
\end{algorithmic}
\end{algorithm}
LS0tDQp0aXRsZTogInRlc3QgcHNldWRvY29kZS5qcyINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIGluY2x1ZGVzOg0KICAgICAgaW5faGVhZGVyOiBoZWFkLmh0bWwNCi0tLQ0KDQpUaGlzIGlzIGEgZGVtbyBmaWxlIGZvciBhIHdvcmtpbmcgcHJvdG90eXBlIG9mIHVzaW5nIFtwc2V1ZG9jb2RlLmpzXShodHRwczovL2dpdGh1Yi5jb20vU2Fzd2F0UGFkaGkvcHNldWRvY29kZS5qcykgaW4gYSBSIE1hcmtkb3duIGRvY3VtZW50LiANCkNvZGUgY291bGQgYmUgZG93bmxvYWRlZCB1c2luZyB0aGUgdXBwZXIgcmlnaHQgZG93bmxvYWQgYnV0dG9uLg0KDQojIEhvdyB0byB1c2UgcHNldWRvY29kZS5qcw0KDQpUaGlzIGlzIHdoYXQgd2UgbmVlZCB0byBpbmNsdWRlIGluIHRoZSBoZWFkZXIgb2YgdGhlIGRvYzoNCg0KPCEtLSBjcmVhdGluZyBoZWFkZXIgZmlsZSB0byBpbnNlcnQgaW4taGVhZGVyLiBtYXRoamF4IGNvbmZpZyBzZWVtcyB0byBiZSByZXF1aXJlZCAtLT4NCmBgYHtjYXQsIGVuZ2luZS5vcHRzID0gbGlzdChmaWxlID0gImhlYWQuaHRtbCIpfQ0KPHNjcmlwdCB0eXBlPSJ0ZXh0L3gtbWF0aGpheC1jb25maWciPg0KICAgIE1hdGhKYXguSHViLkNvbmZpZyh7DQogICAgICAgIHRleDJqYXg6IHsNCiAgICAgICAgICAgIGlubGluZU1hdGg6IFtbJyQnLCckJ10sIFsnXFwoJywnXFwpJ11dLA0KICAgICAgICAgICAgZGlzcGxheU1hdGg6IFtbJyQkJywnJCQnXSwgWydcXFsnLCdcXF0nXV0sDQogICAgICAgICAgICBwcm9jZXNzRXNjYXBlczogdHJ1ZSwNCiAgICAgICAgICAgIHByb2Nlc3NFbnZpcm9ubWVudHM6IHRydWUsDQogICAgICAgIH0NCiAgICB9KTsNCjwvc2NyaXB0Pg0KPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL3BzZXVkb2NvZGVAbGF0ZXN0L2J1aWxkL3BzZXVkb2NvZGUubWluLmNzcyI+DQo8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L25wbS9wc2V1ZG9jb2RlQGxhdGVzdC9idWlsZC9wc2V1ZG9jb2RlLm1pbi5qcyI+PC9zY3JpcHQ+DQpgYGANCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgY29tbWVudCA9IE5BfQ0KeGZ1bjo6ZmlsZV9zdHJpbmcoImhlYWQuaHRtbCIpDQpgYGANCg0KVGhpcyBpcyBpbiBhIGZpbGUgYGhlYWQuaHRtbGAgYW5kIHdlIGluc2VydCBpdCB1c2luZyANCmBgYGB5YW1sDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgaW5jbHVkZXM6DQogICAgICBpbl9oZWFkZXI6IGhlYWQuaHRtbA0KYGBgDQoNCk1hdGhhanggaXMgYWxyZWFkeSBjb25maWd1cmVkIGluIGEgUiBNYXJrZG93biBkb2MgYnV0IE1hdGhqYXggY29uZmlnIHNlZW1zIHRvIGJlIHJlcXVpcmVkIGZvciBNYXRoIHRvIHdvcmsgaW5zaWRlIHRoZSBhbGdvcml0aG0gZW52aXJvbm1lbnQgDQoNCkVsZW1lbnRzIGNvbnRhaW5pbmcgdGhlIGNvZGUgYXJlIHJlbmRlcmVkIGJhc2VkIG9uIGEgc2VsZWN0b3IgdXNpbmcgYSBKUyBmdW5jdGlvbi4gDQpXZSdsbCB1c2UgdGhlIGZlbmNlZCBjb2RlIGF0dHJpYnV0ZXMgZmVhdHVyZXMgdG8gcmVuZGVyIGFsbCBgcHJlYCB3aXRoIGFuIGV4cGVjdGVkIGBhbGdvcmlndGhtYCBhdHRyaWJ1dGVzLiBXZSdsbCBhbHNvIHNldCBzb21lIG9wdGlvbnMgLSB0aGlzIGNhbiBiZSBjaGFuZ2UuIA0KDQpUaGlzIGlzIHdpbGwgd2UnbGwgYWRkIHRoaXMgSlMgY29kZSB1c2luZyBhIGBqc2Aga25pdHIgYmxvY2s6IA0KPCEtLSByZW5kZXJpbmcgdGhlIGFsZ28gYmxvY2sgLS0+DQpgYGB7anMsIGVjaG8gPSBUUlVFfQ0Kd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2xvYWQnLCAoZXZlbnQpID0+IHsNCiAgZWxlbSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoIi5hbGdvcml0aG0iKQ0KICBlbGVtLmZvckVhY2goZSA9PiB7DQogICAgcHNldWRvY29kZS5yZW5kZXJFbGVtZW50KGUsIHtsaW5lTnVtYmVyOiB0cnVlLCBsaW5lTnVtYmVyUHVuYzogJyAnfSk7DQogIH0pDQp9KTsNCmBgYA0KDQpXZSBjb3VsZCBhbHNvIGFkZCBpdCBpbiB0aGUgcHJldmlvdXMgYGhlYWQuaHRtbGAuIFRoaXMgd2lsbCBydW4gYHBzZXVkb2NvZGUucmVuZGVyRWxlbWVudCgpYCBvbiBlYWNoIGVsZW1lbnQgb2YgY2xhc3MgYGFsZ29yaXRobWAgYW5kIHJlcGxhY2UgdGhlIHdob2xlIGVsZW1lbnQNCg0KDQpXaXRoIHRoaXMsIGV2ZXJ5dGhpbmcgc2hvdWxkIHdvcmsuDQoNCiMgTWF0aGpheCBpcyBzdGlsbCB3b3JraW5nDQpBIGJsb2NrIA0KJCQNCjErMQ0KJCQNCg0Kb3IgaW5saW5lIG1hdGggbGlrZSAkXGFscGhhID0geC95JA0KDQojIyBJbnNlcnRpbmcgYW4gYWxnb3JpdGhtIGVudmlyb25tZW50DQoNCllvdSBjYW4gdXNlIGFuIGFsZ29yaXRobSBjb2RlIGJsb2NrIHVzaW5nIHN5bnRheCBmcm9tIFtwc2V1ZG9jb2RlLmpzXShodHRwczovL2dpdGh1Yi5jb20vU2Fzd2F0UGFkaGkvcHNldWRvY29kZS5qcykgYnkgc2V0dGluZyB0aGUgZmVuY2VkIGRpdiBhdHRyaWJ1dGUgYGFsZ29yaXRobWAgYXMgYmVsb3cNCg0KICAgIGBgYHsuYWxnb3JpdGhtfQ0KICAgICUgVGhpcyBxdWlja3NvcnQgYWxnb3JpdGhtIGlzIGV4dHJhY3RlZCBmcm9tIENoYXB0ZXIgNywgSW50cm9kdWN0aW9uIHRvIEFsZ29yaXRobXMgKDNyZCBlZGl0aW9uKQ0KICAgIFxiZWdpbnthbGdvcml0aG19DQogICAgXGNhcHRpb257UXVpY2tzb3J0fQ0KICAgIFxiZWdpbnthbGdvcml0aG1pY30NCiAgICBcUFJPQ0VEVVJFe1F1aWNrc29ydH17JEEsIHAsIHIkfQ0KICAgICAgICBcSUZ7JHAgPCByJH0gDQogICAgICAgICAgICBcU1RBVEUgJHEgPSAkIFxDQUxMe1BhcnRpdGlvbn17JEEsIHAsIHIkfQ0KICAgICAgICAgICAgXFNUQVRFIFxDQUxMe1F1aWNrc29ydH17JEEsIHAsIHEgLSAxJH0NCiAgICAgICAgICAgIFxTVEFURSBcQ0FMTHtRdWlja3NvcnR9eyRBLCBxICsgMSwgciR9DQogICAgICAgIFxFTkRJRg0KICAgIFxFTkRQUk9DRURVUkUNCiAgICBcUFJPQ0VEVVJFe1BhcnRpdGlvbn17JEEsIHAsIHIkfQ0KICAgICAgICBcU1RBVEUgJHggPSBBW3JdJA0KICAgICAgICBcU1RBVEUgJGkgPSBwIC0gMSQNCiAgICAgICAgXEZPUnskaiA9IHAkIFxUTyAkciAtIDEkfQ0KICAgICAgICAgICAgXElGeyRBW2pdIDwgeCR9DQogICAgICAgICAgICAgICAgXFNUQVRFICRpID0gaSArIDEkDQogICAgICAgICAgICAgICAgXFNUQVRFIGV4Y2hhbmdlDQogICAgICAgICAgICAgICAgJEFbaV0kIHdpdGggJEFbal0kDQogICAgICAgICAgICBcRU5ESUYNCiAgICAgICAgICAgIFxTVEFURSBleGNoYW5nZSAkQVtpXSQgd2l0aCAkQVtyXSQNCiAgICAgICAgXEVOREZPUg0KICAgIFxFTkRQUk9DRURVUkUNCiAgICBcZW5ke2FsZ29yaXRobWljfQ0KICAgIFxlbmR7YWxnb3JpdGhtfQ0KICAgIGBgYA0KICAgIA0KVGhpcyB3b3VsZCByZW5kZXIgdG8gDQoNCmBgYHsuYWxnb3JpdGhtfQ0KJSBUaGlzIHF1aWNrc29ydCBhbGdvcml0aG0gaXMgZXh0cmFjdGVkIGZyb20gQ2hhcHRlciA3LCBJbnRyb2R1Y3Rpb24gdG8gQWxnb3JpdGhtcyAoM3JkIGVkaXRpb24pDQpcYmVnaW57YWxnb3JpdGhtfQ0KXGNhcHRpb257UXVpY2tzb3J0fQ0KXGJlZ2lue2FsZ29yaXRobWljfQ0KXFBST0NFRFVSRXtRdWlja3NvcnR9eyRBLCBwLCByJH0NCiAgICBcSUZ7JHAgPCByJH0gDQogICAgICAgIFxTVEFURSAkcSA9ICQgXENBTEx7UGFydGl0aW9ufXskQSwgcCwgciR9DQogICAgICAgIFxTVEFURSBcQ0FMTHtRdWlja3NvcnR9eyRBLCBwLCBxIC0gMSR9DQogICAgICAgIFxTVEFURSBcQ0FMTHtRdWlja3NvcnR9eyRBLCBxICsgMSwgciR9DQogICAgXEVORElGDQpcRU5EUFJPQ0VEVVJFDQpcUFJPQ0VEVVJFe1BhcnRpdGlvbn17JEEsIHAsIHIkfQ0KICAgIFxTVEFURSAkeCA9IEFbcl0kDQogICAgXFNUQVRFICRpID0gcCAtIDEkDQogICAgXEZPUnskaiA9IHAkIFxUTyAkciAtIDEkfQ0KICAgICAgICBcSUZ7JEFbal0gPCB4JH0NCiAgICAgICAgICAgIFxTVEFURSAkaSA9IGkgKyAxJA0KICAgICAgICAgICAgXFNUQVRFIGV4Y2hhbmdlDQogICAgICAgICAgICAkQVtpXSQgd2l0aCAkQVtqXSQNCiAgICAgICAgXEVORElGDQogICAgICAgIFxTVEFURSBleGNoYW5nZSAkQVtpXSQgd2l0aCAkQVtyXSQNCiAgICBcRU5ERk9SDQpcRU5EUFJPQ0VEVVJFDQpcZW5ke2FsZ29yaXRobWljfQ0KXGVuZHthbGdvcml0aG19DQpgYGANCg0KIyMjIEFub3RoZXIgb25lIA0KDQogICAgYGBgey5hbGdvcml0aG19DQogICAgXGJlZ2lue2FsZ29yaXRobX0NCiAgICBcY2FwdGlvbntUaGUgb3JpZ2luYWwgXHRleHRzZntSZWxpZWZ9IGFsZ29yaXRobSBmb3IgcmFua2luZyBwcmVkaWN0b3IgdmFyaWFibGVzIGluIGNsYXNzaWZpY2F0aW9uIG1vZGVscyB3aXRoIHR3byBjbGFzc2VzLn0NCiAgICBcYmVnaW57YWxnb3JpdGhtaWN9DQogICAgXFNUQVRFIEluaXRpYWxpemUgdGhlIHByZWRpY3RvciBzY29yZXMgJFNfaiQgdG8gemVybzsNCiAgICBcRk9SeyRpID0gMVxsZG90cyBtJCByYW5kb21seSBzZWxlY3RlZCB0cmFpbmluZyBzZXQgc2FtcGxlcyAoJFJfaSQpfQ0KICAgIFxTVEFURSBGaW5kIHRoZSBuZWFyZXN0IG1pc3MgYW5kIGhpdCBpbiB0aGUgdHJhaW5pbmcgc2V0Ow0KICAgIFxGT1J7JGogPSAxXGxkb3RzIHAkIHByZWRpY3RvciB2YXJpYWJsZXN9DQogICAgICAgXFNUQVRFIEFkanVzdCB0aGUgc2NvcmUgZm9yIGVhY2ggcHJlZGljdG9yICBiYXNlZCBvbiB0aGUgcHJveGltaXR5IG9mICRSX2okIHRvIHRoZSBuZWFyZXN0IG1pc3MgYW5kIGhpdDpcXA0KICAgICAgICRTX2ogPSBTX2ogLSBkaWZmX2ooUl9qLCBIaXQpXjIvbSArIGRpZmZfaihSX2osIE1pc3MpXjIvbSQ7DQogICAgXEVOREZPUg0KICAgIFxFTkRGT1INCiAgICBcZW5ke2FsZ29yaXRobWljfQ0KICAgIFxlbmR7YWxnb3JpdGhtfQ0KICAgIGBgYA0KICAgIA0KYGBgey5hbGdvcml0aG19DQpcYmVnaW57YWxnb3JpdGhtfQ0KXGNhcHRpb257VGhlIG9yaWdpbmFsIFx0ZXh0c2Z7UmVsaWVmfSBhbGdvcml0aG0gZm9yIHJhbmtpbmcgcHJlZGljdG9yIHZhcmlhYmxlcyBpbiBjbGFzc2lmaWNhdGlvbiBtb2RlbHMgd2l0aCB0d28gY2xhc3Nlcy59DQpcYmVnaW57YWxnb3JpdGhtaWN9DQpcU1RBVEUgSW5pdGlhbGl6ZSB0aGUgcHJlZGljdG9yIHNjb3JlcyAkU19qJCB0byB6ZXJvOw0KXEZPUnskaSA9IDFcbGRvdHMgbSQgcmFuZG9tbHkgc2VsZWN0ZWQgdHJhaW5pbmcgc2V0IHNhbXBsZXMgKCRSX2kkKX0NClxTVEFURSBGaW5kIHRoZSBuZWFyZXN0IG1pc3MgYW5kIGhpdCBpbiB0aGUgdHJhaW5pbmcgc2V0Ow0KXEZPUnskaiA9IDFcbGRvdHMgcCQgcHJlZGljdG9yIHZhcmlhYmxlc30NCiAgIFxTVEFURSBBZGp1c3QgdGhlIHNjb3JlIGZvciBlYWNoIHByZWRpY3RvciAgYmFzZWQgb24gdGhlIHByb3hpbWl0eSBvZiAkUl9qJCB0byB0aGUgbmVhcmVzdCBtaXNzIGFuZCBoaXQ6XFwNCiAgICRTX2ogPSBTX2ogLSBkaWZmX2ooUl9qLCBIaXQpXjIvbSArIGRpZmZfaihSX2osIE1pc3MpXjIvbSQ7DQpcRU5ERk9SDQpcRU5ERk9SDQpcZW5ke2FsZ29yaXRobWljfQ0KXGVuZHthbGdvcml0aG19DQpgYGANCg0K