<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/10-print-mazes-with-ggplot2/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://tjmahr.github.io/10-print-mazes-with-ggplot2/"> Higher Order Functions</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>There is a celebrated Commodore 64 program that randomly prints outs <code>/</code> and <code>\</code><br>
characters and fills the screen with neat-looking maze designs. It is just one<br>
line of code, but there is <a rel="nofollow" href="https://10print.org/" target="_blank">a whole book</a> written about<br>
it.</p>
<div>
<div>
<pre><code>10 PRINT CHR$(205.5+RND(1)); : GOTO 10
</code></pre>
</div>
</div>
<figure>
<img alt="Screenshots of 10 PRINT in action" src="https://i0.wp.com/tjmahr.github.io/assets/images/2018-05-print10.png?w=456&ssl=1" data-recalc-dims="1"><figcaption>Screenshots of the 10 PRINT program in action. Images taken from the <a rel="nofollow" href="https://10print.org/" target="_blank"><em>10 PRINT</em> book</a>.<br>
</figcaption></figure>
<p>The basic idea, from my reading of the code, is that <code>CHR$(205)</code> is <code>\</code>,<br>
<code>CHR$(206)</code> is <code>/</code>, and the program randomly selects between the two by adding a<br>
random number to 205.5. Endlessly looping over this command fills the screen<br>
with that pleasing maze pattern.</p>
<p>In R, we could replicate this functionality with by randomly sampling the<br>
slashes:</p>
<div>
<div>
<pre><code><span>sample_n_slashes</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>n</span><span>)</span><span> </span><span>{</span><span>
</span><span>sample</span><span>(</span><span>c</span><span>(</span><span>&quot;/&quot;</span><span>,</span><span> </span><span>&quot;\\&quot;</span><span>),</span><span> </span><span>size</span><span> </span><span>=</span><span> </span><span>n</span><span>,</span><span> </span><span>replace</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span><span>
</span><span>}</span><span>
</span><span>withr</span><span>::</span><span>with_options</span><span>(</span><span>
</span><span>list</span><span>(</span><span>width</span><span> </span><span>=</span><span> </span><span>40</span><span>),</span><span> </span><span>cat</span><span>(</span><span>sample_n_slashes</span><span>(</span><span>800</span><span>),</span><span> </span><span>sep</span><span> </span><span>=</span><span> </span><span>&quot;&quot;</span><span>,</span><span> </span><span>fill</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span><span>
</span><span>)</span><span>
</span><span>#> //////\/\\/\/\/\/\\//\\\\//\//\/\//\///\</span><span>
</span><span>#> \\\/\//\\/\/////////////\\/\//\\\/\//\\\</span><span>
</span><span>#> /\\/\/\//\/\/\\/\\/\/\//\\\\//\/\\\/\///</span><span>
</span><span>#> \\//\/\\\/\///\\/\/\/////\//\///\/\/\//\</span><span>
</span><span>#> /\/\//\///\//\//\//\/\//\\/\\\\\/\\\//\/</span><span>
</span><span>#> //\\\\\//////\//\//\/\//\\////\/\\\/\/\/</span><span>
</span><span>#> \\////\/\\/\////\//////\\/\\/////\/////\</span><span>
</span><span>#> /\/\/\/\/\\///\/\\\\/\/\\//\/\\/\\\\\\//</span><span>
</span><span>#> //\\\/\///\///\/\\\//\//\\\\//\\/\\/\/\/</span><span>
</span><span>#> /\\/\//\\//\/\\\\\/\\\/\\\/\/\/\/\////\/</span><span>
</span><span>#> /\//\\//\////\\\///\//\/\\\/\\///\//\\\\</span><span>
</span><span>#> /\//\\////\/\\\//\\\//\/\///\\\\\/\/\\//</span><span>
</span><span>#> \\////\\/\\\\\\///\///\//\\\/\\\\//\////</span><span>
</span><span>#> \\\///\/\//\//\/\//\/\/\\\/\/\\///\/////</span><span>
</span><span>#> \\/\\//\\\\\\///\\\\/\\/\\//\//\\\/\\/\/</span><span>
</span><span>#> ////\\\////\/\\\\\/////\/\\\////\\///\\\</span><span>
</span><span>#> \//\\\//\///\/\\\\//\\\////\\//\\/\/\//\</span><span>
</span><span>#> \/\//\\//\\///\\\\\\//\///\/\\\\\\\\/\\/</span><span>
</span><span>#> ///\/\//\\/\/\\\\\\\\/\///\//\\///\\//\\</span><span>
</span><span>#> /////\\///\/\\/\/\\//\\//\/\\/\//\//\\\\</span><span>
</span></code></pre>
</div>
</div>
<p>where <code>withr::with_options()</code> lets us temporarily change the print width and<br>
<code>cat()</code> concatenates the slashes and prints out the characters as text.</p>
<p>We can also make this much prettier by drawing the patterns using ggplot2.</p>
<h2>Drawing line segments with ggplot2</h2>
<p>Instead of writing out slashes, we will draw a grid of diagonal line segments,<br>
some of which will be flipped at random. To draw a segment, we need a starting<br>
<em>x</em>–<em>y</em> coordinate and an ending <em>x</em>–<em>y</em> coordinate. <code>geom_segment()</code> will<br>
connect the two coordinates with a line. Here’s a small example where we draw<br>
four “slashes”.</p>
<div>
<div>
<pre><code><span>library</span><span>(</span><span>ggplot2</span><span>)</span><span>
</span><span>library</span><span>(</span><span>dplyr</span><span>)</span><span>
</span><span>data</span><span> </span><span>&lt;-</span><span> </span><span>tibble</span><span>::</span><span>tribble</span><span>(</span><span>
</span><span>~</span><span>row</span><span>,</span><span> </span><span>~</span><span>col</span><span>,</span><span> </span><span>~</span><span>x_start</span><span>,</span><span> </span><span>~</span><span>x_end</span><span>,</span><span> </span><span>~</span><span>y_start</span><span>,</span><span> </span><span>~</span><span>y_end</span><span>,</span><span>
</span><span>1</span><span>,</span><span> </span><span>1</span><span>,</span><span> </span><span>0</span><span>,</span><span> </span><span>1</span><span>,</span><span> </span><span>0</span><span>,</span><span> </span><span>1</span><span>,</span><span>
</span><span>1</span><span>,</span><span> </span><span>2</span><span>,</span><span> </span><span>1</span><span>,</span><span> </span><span>2</span><span>,</span><span> </span><span>1</span><span>,</span><span> </span><span>0</span><span>,</span><span> </span><span># flipped</span><span>
</span><span>2</span><span>,</span><span> </span><span>1</span><span>,</span><span> </span><span>0</span><span>,</span><span> </span><span>1</span><span>,</span><span> </span><span>1</span><span>,</span><span> </span><span>2</span><span>,</span><span>
</span><span>2</span><span>,</span><span> </span><span>2</span><span>,</span><span> </span><span>1</span><span>,</span><span> </span><span>2</span><span>,</span><span> </span><span>1</span><span>,</span><span> </span><span>2</span><span>)</span><span>
</span><span>ggplot</span><span>(</span><span>data</span><span>)</span><span> </span><span>+</span><span> </span><span>aes</span><span>(</span><span>x</span><span> </span><span>=</span><span> </span><span>x_start</span><span>,</span><span> </span><span>xend</span><span> </span><span>=</span><span> </span><span>x_end</span><span>,</span><span> </span><span>y</span><span> </span><span>=</span><span> </span><span>y_start</span><span>,</span><span> </span><span>yend</span><span> </span><span>=</span><span> </span><span>y_end</span><span>)</span><span> </span><span>+</span><span>
</span><span>geom_segment</span><span>()</span><span>
</span></code></pre>
</div>
</div>
<p><img alt="A simple demo of geom_segment()" title="A simple demo of geom_segment()" src="https://i1.wp.com/tjmahr.github.io/figs//2018-05-09-10-print-mazes-with-ggplot2/geom-segment-demo-1.png?w=50%25&ssl=1" data-recalc-dims="1"></p>
<p>The programming task now is to make giant grid of these slashes. Let’s start<br>
with an observation: To draw two slashes, we needed three <em>x</em><br>
values: 0, 1, 2. The first two served as segment starts and the last two<br>
as segment ends. The same idea applies to the <em>y</em> values. We can generate a<br>
bunch of starts and ends by taking a sequence of steps and removing the first<br>
and last elements.</p>
<div>
<div>
<pre><code><span># We want a 20 by 20 grid</span><span>
</span><span>rows</span><span> </span><span>&lt;-</span><span> </span><span>20</span><span>
</span><span>cols</span><span> </span><span>&lt;-</span><span> </span><span>20</span><span>
</span><span>x_points</span><span> </span><span>&lt;-</span><span> </span><span>seq</span><span>(</span><span>0</span><span>,</span><span> </span><span>1</span><span>,</span><span> </span><span>length.out</span><span> </span><span>=</span><span> </span><span>cols</span><span> </span><span>+</span><span> </span><span>1</span><span>)</span><span>
</span><span>x_starts</span><span> </span><span>&lt;-</span><span> </span><span>head</span><span>(</span><span>x_points</span><span>,</span><span> </span><span>-1</span><span>)</span><span>
</span><span>x_ends</span><span> </span><span>&lt;-</span><span> </span><span>tail</span><span>(</span><span>x_points</span><span>,</span><span> </span><span>-1</span><span>)</span><span>
</span><span>y_points</span><span> </span><span>&lt;-</span><span> </span><span>seq</span><span>(</span><span>0</span><span>,</span><span> </span><span>1</span><span>,</span><span> </span><span>length.out</span><span> </span><span>=</span><span> </span><span>rows</span><span> </span><span>+</span><span> </span><span>1</span><span>)</span><span>
</span><span>y_starts</span><span> </span><span>&lt;-</span><span> </span><span>head</span><span>(</span><span>y_points</span><span>,</span><span> </span><span>-1</span><span>)</span><span>
</span><span>y_ends</span><span> </span><span>&lt;-</span><span> </span><span>tail</span><span>(</span><span>y_points</span><span>,</span><span> </span><span>-1</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<p>Each <code>x_starts</code>–<code>x_ends</code> pair is a column in the grid, and each<br>
<code>y_starts</code>–<code>y_ends</code> is a row in the grid. To make a slash at each<br>
row–column combination, we have to map out all the combinations of the rows<br>
and columns. We can do this with <code>crossing()</code> which creates all <em>crossed</em><br>
combinations of values. (If it helps, you might think of <em>crossed</em> like <a rel="nofollow" href="https://en.wikipedia.org/wiki/Factorial_experiment" target="_blank">crossed<br>
experiments</a> or the<br>
<a rel="nofollow" href="https://en.wikipedia.org/wiki/Cartesian_product" target="_blank">Cartesian cross product</a> of<br>
sets.)</p>
<div>
<div>
<pre><code><span>grid</span><span> </span><span>&lt;-</span><span> </span><span>tidyr</span><span>::</span><span>crossing</span><span>(</span><span>
</span><span># columns</span><span>
</span><span>data_frame</span><span>(</span><span>x_start</span><span> </span><span>=</span><span> </span><span>x_starts</span><span>,</span><span> </span><span>x_end</span><span> </span><span>=</span><span> </span><span>x_ends</span><span>),</span><span>
</span><span># rows</span><span>
</span><span>data_frame</span><span>(</span><span>y_start</span><span> </span><span>=</span><span> </span><span>y_starts</span><span>,</span><span> </span><span>y_end</span><span> </span><span>=</span><span> </span><span>y_ends</span><span>))</span><span> </span><span>%>%</span><span>
</span><span># So values move left to right, bottom to top</span><span>
</span><span>arrange</span><span>(</span><span>y_start</span><span>,</span><span> </span><span>y_end</span><span>)</span><span>
</span><span># 400 rows because 20 rows x 20 columns</span><span>
</span><span>grid</span><span>
</span><span>#> # A tibble: 400 x 4</span><span>
</span><span>#> x_start x_end y_start y_end</span><span>
</span><span>#> </span></code></pre></div></div>