Regenerated docs.

This commit is contained in:
Simon Forman 2018-06-05 17:41:22 -07:00
parent 9a04534b05
commit be6387f1f6
19 changed files with 33823 additions and 694 deletions

View File

@ -22,12 +22,11 @@ it's "off the shelf" technology.)
.. code:: ipython2 .. code:: ipython2
J('1 2 3 clear') J('1 2 3 clear')
J('1 2 3 clear')
.. parsed-literal:: .. parsed-literal::
...
``dup`` ``dupd`` ``dup`` ``dupd``

View File

@ -12600,7 +12600,7 @@ $$4 k \left(k + 1\right) + 2$$
<div class="prompt input_prompt">In&nbsp;[19]:</div> <div class="prompt input_prompt">In&nbsp;[19]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="o">%</span><span class="n">time</span> <span class="n">rank_of</span><span class="p">(</span><span class="mi">23000000000000</span><span class="p">)</span> <span class="c1"># Compare runtime with rank_and_offset()!</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="o">%</span><span class="k">time</span> rank_of(23000000000000) # Compare runtime with rank_and_offset()!
</pre></div> </pre></div>
</div> </div>
@ -12645,7 +12645,7 @@ $$2397916$$
<div class="prompt input_prompt">In&nbsp;[20]:</div> <div class="prompt input_prompt">In&nbsp;[20]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="o">%</span><span class="n">time</span> <span class="n">rank_and_offset</span><span class="p">(</span><span class="mi">23000000000000</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="o">%</span><span class="k">time</span> rank_and_offset(23000000000000)
</pre></div> </pre></div>
</div> </div>
@ -12911,7 +12911,7 @@ $$\lfloor{\frac{1}{2} \sqrt{y - 1} - \frac{1}{2}}\rfloor + 1$$
<div class="prompt input_prompt">In&nbsp;[28]:</div> <div class="prompt input_prompt">In&nbsp;[28]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="o">%</span><span class="n">time</span> <span class="nb">int</span><span class="p">(</span><span class="n">F</span><span class="p">(</span><span class="mi">23000000000000</span><span class="p">))</span> <span class="c1"># The clear winner.</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="o">%</span><span class="k">time</span> int(F(23000000000000)) # The clear winner.
</pre></div> </pre></div>
</div> </div>
@ -12981,7 +12981,7 @@ $$2397916$$
<div class="prompt input_prompt">In&nbsp;[30]:</div> <div class="prompt input_prompt">In&nbsp;[30]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="o">%</span><span class="n">time</span> <span class="n">mrank_of</span><span class="p">(</span><span class="mi">23000000000000</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="o">%</span><span class="k">time</span> mrank_of(23000000000000)
</pre></div> </pre></div>
</div> </div>
@ -13227,7 +13227,7 @@ $$4572225$$
<div class="prompt input_prompt">In&nbsp;[37]:</div> <div class="prompt input_prompt">In&nbsp;[37]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="o">%</span><span class="n">time</span> <span class="n">aoc20173</span><span class="p">(</span><span class="mi">23000000000000000000000000</span><span class="p">)</span> <span class="c1"># Fast for large values.</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="o">%</span><span class="k">time</span> aoc20173(23000000000000000000000000) # Fast for large values.
</pre></div> </pre></div>
</div> </div>

View File

@ -11797,33 +11797,65 @@ div#notebook {
</div> </div>
<div class="inner_cell"> <div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html"> <div class="text_cell_render border-box-sizing rendered_html">
<p>Consider the <code>x</code> combinator <code>x == dup i</code>:</p> <p>Consider the <code>x</code> combinator:</p>
<pre><code>[a B] x <pre><code>x == dup i
[a B] a B
</code></pre> </code></pre>
<p>Let <code>B</code> <code>swap</code> the <code>a</code> with the quote and run some function <code>[C]</code> on it.</p> <p>We can apply it to a quoted program consisting of some value <code>a</code> and a function <code>B</code>:</p>
<pre><code>[a B] a B <pre><code>[a B] x
[a B] a B</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Let <code>B</code> function <code>swap</code> the <code>a</code> with the quote and run some function <code>C</code> on it to generate a new value <code>b</code>:</p>
<pre><code>B == swap [C] dip
[a B] a B
[a B] a swap [C] dip [a B] a swap [C] dip
a [a B] [C] dip a [a B] [C] dip
a C [a B] a C [a B]
b [a B]</code></pre>
</code></pre> </div>
<p>Now discard the quoted <code>a</code> with <code>rest</code> and <code>cons</code> the result of <code>C</code> on <code>a</code> whatever that is:</p> </div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Now discard the quoted <code>a</code> with <code>rest</code> then <code>cons</code> <code>b</code>:</p>
<pre><code>aC [a B] rest cons <pre><code>b [a B] rest cons
aC [B] cons b [B] cons
[aC B] [b B]</code></pre>
</code></pre> </div>
<p>Altogether, this is the definition of <code>B</code>:</p> </div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Putting it together, this is the definition of <code>B</code>:</p>
<pre><code>B == swap [C] dip rest cons <pre><code>B == swap [C] dip rest cons</code></pre>
</code></pre> </div>
<p>We can create a quoted program that generates the Natural numbers (integers 0, 1, 2, ...) by using <code>0</code> for <code>a</code> and <code>[dup ++]</code> for <code>[C]</code>:</p> </div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>We can create a quoted program that generates the Natural numbers (0, 1, 2, ...) by using <code>0</code> for <code>a</code> and <code>[dup ++]</code> for <code>[C]</code>:</p>
<pre><code>[0 swap [dup ++] dip rest cons] <pre><code>[0 swap [dup ++] dip rest cons]
@ -11983,16 +12015,19 @@ aC [B] cons
</div> </div>
<div class="inner_cell"> <div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html"> <div class="text_cell_render border-box-sizing rendered_html">
<h1 id="Generating-Generators">Generating Generators<a class="anchor-link" href="#Generating-Generators">&#182;</a></h1><p>We want to go from:</p> <h1 id="Making-Generators">Making Generators<a class="anchor-link" href="#Making-Generators">&#182;</a></h1><p>We want to define a function that accepts <code>a</code> and <code>[C]</code> and builds our quoted program:</p>
<pre><code>a [C] G <pre><code> a [C] G
-------------------------
[a swap [C] direco]</code></pre>
</code></pre> </div>
<p>to:</p> </div>
</div>
<pre><code>[a swap [C] direco] <div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
</code></pre> <div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Working in reverse:</p> <p>Working in reverse:</p>
<pre><code>[a swap [C] direco] cons <pre><code>[a swap [C] direco] cons
@ -12005,12 +12040,7 @@ a [C] [direco] cons [swap]
<p>Reading from the bottom up:</p> <p>Reading from the bottom up:</p>
<pre><code>G == [direco] cons [swap] swap concat cons <pre><code>G == [direco] cons [swap] swap concat cons
G == [direco] cons [swap] swoncat cons G == [direco] cons [swap] swoncat cons</code></pre>
</code></pre>
<p>We can try it out:</p>
<pre><code>0 [dup ++] G</code></pre>
</div> </div>
</div> </div>
@ -12027,13 +12057,22 @@ G == [direco] cons [swap] swoncat cons
</div> </div>
</div> </div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Let's try it out:</p>
</div>
</div>
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[7]:</div> <div class="prompt input_prompt">In&nbsp;[7]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">V</span><span class="p">(</span><span class="s1">&#39;0 [dup ++] G&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;0 [dup ++] G&#39;</span><span class="p">)</span>
</pre></div> </pre></div>
</div> </div>
@ -12050,17 +12089,7 @@ G == [direco] cons [swap] swoncat cons
<div class="output_subarea output_stream output_stdout output_text"> <div class="output_subarea output_stream output_stdout output_text">
<pre> . 0 [dup ++] G <pre>[0 swap [dup ++] direco]
0 . [dup ++] G
0 [dup ++] . G
0 [dup ++] . [direco] cons [swap] swoncat cons
0 [dup ++] [direco] . cons [swap] swoncat cons
0 [[dup ++] direco] . [swap] swoncat cons
0 [[dup ++] direco] [swap] . swoncat cons
0 [[dup ++] direco] [swap] . swap concat cons
0 [swap] [[dup ++] direco] . concat cons
0 [swap [dup ++] direco] . cons
[0 swap [dup ++] direco] .
</pre> </pre>
</div> </div>
</div> </div>
@ -12074,7 +12103,7 @@ G == [direco] cons [swap] swoncat cons
<div class="prompt input_prompt">In&nbsp;[8]:</div> <div class="prompt input_prompt">In&nbsp;[8]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">V</span><span class="p">(</span><span class="s1">&#39;0 [dup ++] G x&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;0 [dup ++] G x x x pop&#39;</span><span class="p">)</span>
</pre></div> </pre></div>
</div> </div>
@ -12091,28 +12120,7 @@ G == [direco] cons [swap] swoncat cons
<div class="output_subarea output_stream output_stdout output_text"> <div class="output_subarea output_stream output_stdout output_text">
<pre> . 0 [dup ++] G x <pre>0 1 2
0 . [dup ++] G x
0 [dup ++] . G x
0 [dup ++] . [direco] cons [swap] swoncat cons x
0 [dup ++] [direco] . cons [swap] swoncat cons x
0 [[dup ++] direco] . [swap] swoncat cons x
0 [[dup ++] direco] [swap] . swoncat cons x
0 [[dup ++] direco] [swap] . swap concat cons x
0 [swap] [[dup ++] direco] . concat cons x
0 [swap [dup ++] direco] . cons x
[0 swap [dup ++] direco] . x
[0 swap [dup ++] direco] . 0 swap [dup ++] direco
[0 swap [dup ++] direco] 0 . swap [dup ++] direco
0 [0 swap [dup ++] direco] . [dup ++] direco
0 [0 swap [dup ++] direco] [dup ++] . direco
0 [0 swap [dup ++] direco] [dup ++] . dip rest cons
0 . dup ++ [0 swap [dup ++] direco] rest cons
0 0 . ++ [0 swap [dup ++] direco] rest cons
0 1 . [0 swap [dup ++] direco] rest cons
0 1 [0 swap [dup ++] direco] . rest cons
0 1 [swap [dup ++] direco] . cons
0 [1 swap [dup ++] direco] .
</pre> </pre>
</div> </div>
</div> </div>
@ -12134,7 +12142,7 @@ G == [direco] cons [swap] swoncat cons
<div class="prompt input_prompt">In&nbsp;[9]:</div> <div class="prompt input_prompt">In&nbsp;[9]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;1 [dup 1 &lt;&lt;] G x x x x x x x x x&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;1 [dup 1 &lt;&lt;] G x x x x x x x x x pop&#39;</span><span class="p">)</span>
</pre></div> </pre></div>
</div> </div>
@ -12151,7 +12159,7 @@ G == [direco] cons [swap] swoncat cons
<div class="output_subarea output_stream output_stdout output_text"> <div class="output_subarea output_stream output_stdout output_text">
<pre>1 2 4 8 16 32 64 128 256 [512 swap [dup 1 &lt;&lt;] direco] <pre>1 2 4 8 16 32 64 128 256
</pre> </pre>
</div> </div>
</div> </div>
@ -12164,8 +12172,7 @@ G == [direco] cons [swap] swoncat cons
</div> </div>
<div class="inner_cell"> <div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html"> <div class="text_cell_render border-box-sizing rendered_html">
<h1 id="n-[x]-times"><code>n [x] times</code><a class="anchor-link" href="#n-[x]-times">&#182;</a></h1><p>If we have one of these quoted programs we can drive it using <code>times</code> with the <code>x</code> combinator.</p> <h3 id="[x]-times"><code>[x] times</code><a class="anchor-link" href="#[x]-times">&#182;</a></h3><p>If we have one of these quoted programs we can drive it using <code>times</code> with the <code>x</code> combinator.</p>
<p>Let's define a word <code>n_range</code> that takes a starting integer and a count and leaves that many consecutive integers on the stack. For example:</p>
</div> </div>
</div> </div>
@ -12175,7 +12182,7 @@ G == [direco] cons [swap] swoncat cons
<div class="prompt input_prompt">In&nbsp;[10]:</div> <div class="prompt input_prompt">In&nbsp;[10]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;23 [dup ++] G 5 [x] times pop&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;23 [dup ++] G 5 [x] times&#39;</span><span class="p">)</span>
</pre></div> </pre></div>
</div> </div>
@ -12192,140 +12199,7 @@ G == [direco] cons [swap] swoncat cons
<div class="output_subarea output_stream output_stdout output_text"> <div class="output_subarea output_stream output_stdout output_text">
<pre>23 24 25 26 27 <pre>23 24 25 26 27 [28 swap [dup ++] direco]
</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>We can use <code>dip</code> to untangle <code>[dup ++] G</code> from the arguments.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[11]:</div>
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;23 5 [[dup ++] G] dip [x] times pop&#39;</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="prompt"></div>
<div class="output_subarea output_stream output_stdout output_text">
<pre>23 24 25 26 27
</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Now that the givens (arguments) are on the left we have the definition we're looking for:</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[12]:</div>
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;n_range == [[dup ++] G] dip [x] times pop&#39;</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[13]:</div>
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;450 10 n_range&#39;</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="prompt"></div>
<div class="output_subarea output_stream output_stdout output_text">
<pre>450 451 452 453 454 455 456 457 458 459
</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>This is better just using the <code>times</code> combinator though...</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[14]:</div>
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;450 9 [dup ++] times&#39;</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="prompt"></div>
<div class="output_subarea output_stream output_stdout output_text">
<pre>450 451 452 453 454 455 456 457 458 459
</pre> </pre>
</div> </div>
</div> </div>
@ -12356,7 +12230,7 @@ G == [direco] cons [swap] swoncat cons
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[15]:</div> <div class="prompt input_prompt">In&nbsp;[11]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;PE1.1 == dup [3 &amp;] dip 2 &gt;&gt;&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;PE1.1 == dup [3 &amp;] dip 2 &gt;&gt;&#39;</span><span class="p">)</span>
@ -12369,7 +12243,7 @@ G == [direco] cons [swap] swoncat cons
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[16]:</div> <div class="prompt input_prompt">In&nbsp;[12]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">V</span><span class="p">(</span><span class="s1">&#39;14811 PE1.1&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">V</span><span class="p">(</span><span class="s1">&#39;14811 PE1.1&#39;</span><span class="p">)</span>
@ -12419,7 +12293,7 @@ G == [direco] cons [swap] swoncat cons
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[17]:</div> <div class="prompt input_prompt">In&nbsp;[13]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;14811 [PE1.1] G&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;14811 [PE1.1] G&#39;</span><span class="p">)</span>
@ -12447,37 +12321,6 @@ G == [direco] cons [swap] swoncat cons
</div> </div>
</div> </div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[18]:</div>
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[14811 swap [PE1.1] direco] x&#39;</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="prompt"></div>
<div class="output_subarea output_stream output_stdout output_text">
<pre>3 [3702 swap [PE1.1] direco]
</pre>
</div>
</div>
</div>
</div>
</div> </div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt"> <div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div> </div>
@ -12490,7 +12333,7 @@ G == [direco] cons [swap] swoncat cons
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[19]:</div> <div class="prompt input_prompt">In&nbsp;[14]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[14811 swap [PE1.1] direco] 7 [x] times&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[14811 swap [PE1.1] direco] 7 [x] times&#39;</span><span class="p">)</span>
@ -12530,7 +12373,7 @@ G == [direco] cons [swap] swoncat cons
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[20]:</div> <div class="prompt input_prompt">In&nbsp;[15]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;PE1.1.check == dup [pop 14811] [] branch&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;PE1.1.check == dup [pop 14811] [] branch&#39;</span><span class="p">)</span>
@ -12543,7 +12386,38 @@ G == [direco] cons [swap] swoncat cons
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[21]:</div> <div class="prompt input_prompt">In&nbsp;[16]:</div>
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;14811 [PE1.1.check PE1.1] G&#39;</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="prompt"></div>
<div class="output_subarea output_stream output_stdout output_text">
<pre>[14811 swap [PE1.1.check PE1.1] direco]
</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[17]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[14811 swap [PE1.1.check PE1.1] direco] 21 [x] times&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[14811 swap [PE1.1.check PE1.1] direco] 21 [x] times&#39;</span><span class="p">)</span>
@ -12571,6 +12445,15 @@ G == [direco] cons [swap] swoncat cons
</div> </div>
</div> </div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>(It would be more efficient to reset the int every seven cycles but that's a little beyond the scope of this article. This solution does extra work, but not much, and we're not using it "in production" as they say.)</p>
</div>
</div>
</div> </div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt"> <div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div> </div>
@ -12583,7 +12466,7 @@ G == [direco] cons [swap] swoncat cons
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[22]:</div> <div class="prompt input_prompt">In&nbsp;[18]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;7 66 * 4 +&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;7 66 * 4 +&#39;</span><span class="p">)</span>
@ -12623,10 +12506,10 @@ G == [direco] cons [swap] swoncat cons
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[23]:</div> <div class="prompt input_prompt">In&nbsp;[19]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[14811 swap [PE1.1.check PE1.1] dip rest cons] 466 [x] times&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[14811 swap [PE1.1.check PE1.1] direco] 466 [x] times&#39;</span><span class="p">)</span>
</pre></div> </pre></div>
</div> </div>
@ -12643,7 +12526,7 @@ G == [direco] cons [swap] swoncat cons
<div class="output_subarea output_stream output_stdout output_text"> <div class="output_subarea output_stream output_stdout output_text">
<pre>3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 [57 swap [PE1.1.check PE1.1] dip rest cons] <pre>3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 [57 swap [PE1.1.check PE1.1] direco]
</pre> </pre>
</div> </div>
</div> </div>
@ -12654,10 +12537,10 @@ G == [direco] cons [swap] swoncat cons
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[24]:</div> <div class="prompt input_prompt">In&nbsp;[20]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[14811 swap [PE1.1.check PE1.1] dip rest cons] 466 [x] times pop enstacken sum&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[14811 swap [PE1.1.check PE1.1] direco] 466 [x] times pop enstacken sum&#39;</span><span class="p">)</span>
</pre></div> </pre></div>
</div> </div>
@ -12693,7 +12576,7 @@ G == [direco] cons [swap] swoncat cons
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[25]:</div> <div class="prompt input_prompt">In&nbsp;[21]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;PE1.2 == + dup [+] dip&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;PE1.2 == + dup [+] dip&#39;</span><span class="p">)</span>
@ -12708,54 +12591,14 @@ G == [direco] cons [swap] swoncat cons
</div> </div>
<div class="inner_cell"> <div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html"> <div class="text_cell_render border-box-sizing rendered_html">
<p>Now we can add <code>PE1.2</code> to the quoted program given to <code>times</code>.</p> <p>Now we can add <code>PE1.2</code> to the quoted program given to <code>G</code>.</p>
</div> </div>
</div> </div>
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[26]:</div> <div class="prompt input_prompt">In&nbsp;[22]:</div>
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;0 0 [0 swap [PE1.1.check PE1.1] direco] 466 [x [PE1.2] dip] times popop&#39;</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="prompt"></div>
<div class="output_subarea output_stream output_stdout output_text">
<pre>233168
</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Or using <code>G</code> we can write:</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[27]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;0 0 0 [PE1.1.check PE1.1] G 466 [x [PE1.2] dip] times popop&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;0 0 0 [PE1.1.check PE1.1] G 466 [x [PE1.2] dip] times popop&#39;</span><span class="p">)</span>
@ -12791,73 +12634,135 @@ G == [direco] cons [swap] swoncat cons
<h1 id="A-generator-for-the-Fibonacci-Sequence.">A generator for the Fibonacci Sequence.<a class="anchor-link" href="#A-generator-for-the-Fibonacci-Sequence.">&#182;</a></h1><p>Consider:</p> <h1 id="A-generator-for-the-Fibonacci-Sequence.">A generator for the Fibonacci Sequence.<a class="anchor-link" href="#A-generator-for-the-Fibonacci-Sequence.">&#182;</a></h1><p>Consider:</p>
<pre><code>[b a F] x <pre><code>[b a F] x
[b a F] b a F [b a F] b a F</code></pre>
</code></pre> </div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>The obvious first thing to do is just add <code>b</code> and <code>a</code>:</p> <p>The obvious first thing to do is just add <code>b</code> and <code>a</code>:</p>
<pre><code>[b a F] b a + <pre><code>[b a F] b a +
[b a F] b+a [b a F] b+a</code></pre>
</code></pre> </div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>From here we want to arrive at:</p> <p>From here we want to arrive at:</p>
<pre><code>b [b+a b F] <pre><code>b [b+a b F]</code></pre>
</code></pre> </div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Let's start with <code>swons</code>:</p> <p>Let's start with <code>swons</code>:</p>
<pre><code>[b a F] b+a swons <pre><code>[b a F] b+a swons
[b+a b a F] [b+a b a F]</code></pre>
</code></pre> </div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Considering this quote as a stack:</p> <p>Considering this quote as a stack:</p>
<pre><code>F a b b+a <pre><code>F a b b+a</code></pre>
</code></pre> </div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>We want to get it to:</p> <p>We want to get it to:</p>
<pre><code>F b b+a b <pre><code>F b b+a b</code></pre>
</code></pre> </div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>So:</p> <p>So:</p>
<pre><code>F a b b+a popdd over <pre><code>F a b b+a popdd over
F b b+a b F b b+a b</code></pre>
</code></pre> </div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>And therefore:</p> <p>And therefore:</p>
<pre><code>[b+a b a F] [popdd over] infra <pre><code>[b+a b a F] [popdd over] infra
[b b+a b F] [b b+a b F]</code></pre>
</code></pre> </div>
<p>And lastly:</p> </div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>But we can just use <code>cons</code> to carry <code>b+a</code> into the quote:</p>
<pre><code>[b a F] b+a [popdd over] cons infra
[b a F] [b+a popdd over] infra
[b b+a b F]</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Lastly:</p>
<pre><code>[b b+a b F] uncons <pre><code>[b b+a b F] uncons
b [b+a b F] b [b+a b F]</code></pre>
</code></pre> </div>
<p>Done.</p> </div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Putting it all together:</p> <p>Putting it all together:</p>
<pre><code>F == + swons [popdd over] infra uncons <pre><code>F == + [popdd over] cons infra uncons
fib_gen == [1 1 F]</code></pre>
</code></pre>
<p>And:</p>
<pre><code>fib_gen == [1 1 F]</code></pre>
</div> </div>
</div> </div>
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[28]:</div> <div class="prompt input_prompt">In&nbsp;[23]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;fib == + swons [popdd over] infra uncons&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;fib == + [popdd over] cons infra uncons&#39;</span><span class="p">)</span>
</pre></div> </pre></div>
</div> </div>
@ -12867,7 +12772,7 @@ b [b+a b F]
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[29]:</div> <div class="prompt input_prompt">In&nbsp;[24]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;fib_gen == [1 1 fib]&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;fib_gen == [1 1 fib]&#39;</span><span class="p">)</span>
@ -12880,7 +12785,7 @@ b [b+a b F]
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[30]:</div> <div class="prompt input_prompt">In&nbsp;[25]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;fib_gen 10 [x] times&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;fib_gen 10 [x] times&#39;</span><span class="p">)</span>
@ -12914,7 +12819,8 @@ b [b+a b F]
<div class="inner_cell"> <div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html"> <div class="text_cell_render border-box-sizing rendered_html">
<h3 id="Project-Euler-Problem-Two">Project Euler Problem Two<a class="anchor-link" href="#Project-Euler-Problem-Two">&#182;</a></h3> <h3 id="Project-Euler-Problem-Two">Project Euler Problem Two<a class="anchor-link" href="#Project-Euler-Problem-Two">&#182;</a></h3>
<pre><code>By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms. <pre><code>By considering the terms in the Fibonacci sequence whose values do not exceed four million,
find the sum of the even-valued terms.
</code></pre> </code></pre>
<p>Now that we have a generator for the Fibonacci sequence, we need a function that adds a term in the sequence to a sum if it is even, and <code>pop</code>s it otherwise.</p> <p>Now that we have a generator for the Fibonacci sequence, we need a function that adds a term in the sequence to a sum if it is even, and <code>pop</code>s it otherwise.</p>
@ -12924,7 +12830,7 @@ b [b+a b F]
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[31]:</div> <div class="prompt input_prompt">In&nbsp;[26]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;PE2.1 == dup 2 % [+] [pop] branch&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;PE2.1 == dup 2 % [+] [pop] branch&#39;</span><span class="p">)</span>
@ -12946,7 +12852,7 @@ b [b+a b F]
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[32]:</div> <div class="prompt input_prompt">In&nbsp;[27]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;&gt;4M == 4000000 &gt;&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;&gt;4M == 4000000 &gt;&#39;</span><span class="p">)</span>
@ -12968,7 +12874,7 @@ b [b+a b F]
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[33]:</div> <div class="prompt input_prompt">In&nbsp;[28]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;PE2 == 0 fib_gen x [pop &gt;4M] [popop] [[PE2.1] dip x] primrec&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;PE2 == 0 fib_gen x [pop &gt;4M] [popop] [[PE2.1] dip x] primrec&#39;</span><span class="p">)</span>
@ -12981,7 +12887,7 @@ b [b+a b F]
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[34]:</div> <div class="prompt input_prompt">In&nbsp;[29]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;PE2&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;PE2&#39;</span><span class="p">)</span>
@ -13052,7 +12958,7 @@ o + e = o
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[35]:</div> <div class="prompt input_prompt">In&nbsp;[30]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[1 0 fib] x x x&#39;</span><span class="p">)</span> <span class="c1"># To start the sequence with 1 1 2 3 instead of 1 2 3.</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[1 0 fib] x x x&#39;</span><span class="p">)</span> <span class="c1"># To start the sequence with 1 1 2 3 instead of 1 2 3.</span>
@ -13092,7 +12998,7 @@ o + e = o
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[36]:</div> <div class="prompt input_prompt">In&nbsp;[31]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[1 0 fib] x x x [popop] dipd&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[1 0 fib] x x x [popop] dipd&#39;</span><span class="p">)</span>
@ -13123,7 +13029,7 @@ o + e = o
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[37]:</div> <div class="prompt input_prompt">In&nbsp;[32]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;PE2.2 == x x x [popop] dipd&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;PE2.2 == x x x [popop] dipd&#39;</span><span class="p">)</span>
@ -13136,7 +13042,7 @@ o + e = o
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[38]:</div> <div class="prompt input_prompt">In&nbsp;[33]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[1 0 fib] 10 [PE2.2] times&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;[1 0 fib] 10 [PE2.2] times&#39;</span><span class="p">)</span>
@ -13176,7 +13082,7 @@ o + e = o
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[39]:</div> <div class="prompt input_prompt">In&nbsp;[34]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;0 [1 0 fib] PE2.2 [pop &gt;4M] [popop] [[PE2.1] dip PE2.2] primrec&#39;</span><span class="p">)</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;0 [1 0 fib] PE2.2 [pop &gt;4M] [popop] [[PE2.1] dip PE2.2] primrec&#39;</span><span class="p">)</span>
@ -13213,6 +13119,115 @@ o + e = o
</div> </div>
</div> </div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h1 id="An-Interesting-Variation">An Interesting Variation<a class="anchor-link" href="#An-Interesting-Variation">&#182;</a></h1>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[35]:</div>
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;codireco == cons dip rest cons&#39;</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[36]:</div>
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">V</span><span class="p">(</span><span class="s1">&#39;[0 [dup ++] codireco] x&#39;</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="prompt"></div>
<div class="output_subarea output_stream output_stdout output_text">
<pre> . [0 [dup ++] codireco] x
[0 [dup ++] codireco] . x
[0 [dup ++] codireco] . 0 [dup ++] codireco
[0 [dup ++] codireco] 0 . [dup ++] codireco
[0 [dup ++] codireco] 0 [dup ++] . codireco
[0 [dup ++] codireco] 0 [dup ++] . cons dip rest cons
[0 [dup ++] codireco] [0 dup ++] . dip rest cons
. 0 dup ++ [0 [dup ++] codireco] rest cons
0 . dup ++ [0 [dup ++] codireco] rest cons
0 0 . ++ [0 [dup ++] codireco] rest cons
0 1 . [0 [dup ++] codireco] rest cons
0 1 [0 [dup ++] codireco] . rest cons
0 1 [[dup ++] codireco] . cons
0 [1 [dup ++] codireco] .
</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[37]:</div>
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">define</span><span class="p">(</span><span class="s1">&#39;G == [codireco] cons cons&#39;</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[38]:</div>
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s1">&#39;230 [dup ++] G 5 [x] times pop&#39;</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="prompt"></div>
<div class="output_subarea output_stream output_stdout output_text">
<pre>230 231 232 233 234
</pre>
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -8,29 +8,36 @@ Cf. jp-reprod.html
from notebook_preamble import J, V, define from notebook_preamble import J, V, define
``` ```
Consider the `x` combinator `x == dup i`: Consider the `x` combinator:
x == dup i
We can apply it to a quoted program consisting of some value `a` and a function `B`:
[a B] x [a B] x
[a B] a B [a B] a B
Let `B` `swap` the `a` with the quote and run some function `[C]` on it. Let `B` function `swap` the `a` with the quote and run some function `C` on it to generate a new value `b`:
B == swap [C] dip
[a B] a B [a B] a B
[a B] a swap [C] dip [a B] a swap [C] dip
a [a B] [C] dip a [a B] [C] dip
a C [a B] a C [a B]
b [a B]
Now discard the quoted `a` with `rest` and `cons` the result of `C` on `a` whatever that is: Now discard the quoted `a` with `rest` then `cons` `b`:
aC [a B] rest cons b [a B] rest cons
aC [B] cons b [B] cons
[aC B] [b B]
Altogether, this is the definition of `B`: Putting it together, this is the definition of `B`:
B == swap [C] dip rest cons B == swap [C] dip rest cons
We can create a quoted program that generates the Natural numbers (integers 0, 1, 2, ...) by using `0` for `a` and `[dup ++]` for `[C]`: We can create a quoted program that generates the Natural numbers (0, 1, 2, ...) by using `0` for `a` and `[dup ++]` for `[C]`:
[0 swap [dup ++] dip rest cons] [0 swap [dup ++] dip rest cons]
@ -92,13 +99,11 @@ V('[0 swap [dup ++] direco] x')
0 [1 swap [dup ++] direco] . 0 [1 swap [dup ++] direco] .
# Generating Generators # Making Generators
We want to go from: We want to define a function that accepts `a` and `[C]` and builds our quoted program:
a [C] G a [C] G
-------------------------
to:
[a swap [C] direco] [a swap [C] direco]
Working in reverse: Working in reverse:
@ -114,118 +119,48 @@ Reading from the bottom up:
G == [direco] cons [swap] swap concat cons G == [direco] cons [swap] swap concat cons
G == [direco] cons [swap] swoncat cons G == [direco] cons [swap] swoncat cons
We can try it out:
0 [dup ++] G
```python ```python
define('G == [direco] cons [swap] swoncat cons') define('G == [direco] cons [swap] swoncat cons')
``` ```
Let's try it out:
```python ```python
V('0 [dup ++] G') J('0 [dup ++] G')
``` ```
. 0 [dup ++] G [0 swap [dup ++] direco]
0 . [dup ++] G
0 [dup ++] . G
0 [dup ++] . [direco] cons [swap] swoncat cons
0 [dup ++] [direco] . cons [swap] swoncat cons
0 [[dup ++] direco] . [swap] swoncat cons
0 [[dup ++] direco] [swap] . swoncat cons
0 [[dup ++] direco] [swap] . swap concat cons
0 [swap] [[dup ++] direco] . concat cons
0 [swap [dup ++] direco] . cons
[0 swap [dup ++] direco] .
```python ```python
V('0 [dup ++] G x') J('0 [dup ++] G x x x pop')
``` ```
. 0 [dup ++] G x 0 1 2
0 . [dup ++] G x
0 [dup ++] . G x
0 [dup ++] . [direco] cons [swap] swoncat cons x
0 [dup ++] [direco] . cons [swap] swoncat cons x
0 [[dup ++] direco] . [swap] swoncat cons x
0 [[dup ++] direco] [swap] . swoncat cons x
0 [[dup ++] direco] [swap] . swap concat cons x
0 [swap] [[dup ++] direco] . concat cons x
0 [swap [dup ++] direco] . cons x
[0 swap [dup ++] direco] . x
[0 swap [dup ++] direco] . 0 swap [dup ++] direco
[0 swap [dup ++] direco] 0 . swap [dup ++] direco
0 [0 swap [dup ++] direco] . [dup ++] direco
0 [0 swap [dup ++] direco] [dup ++] . direco
0 [0 swap [dup ++] direco] [dup ++] . dip rest cons
0 . dup ++ [0 swap [dup ++] direco] rest cons
0 0 . ++ [0 swap [dup ++] direco] rest cons
0 1 . [0 swap [dup ++] direco] rest cons
0 1 [0 swap [dup ++] direco] . rest cons
0 1 [swap [dup ++] direco] . cons
0 [1 swap [dup ++] direco] .
### Powers of 2 ### Powers of 2
```python ```python
J('1 [dup 1 <<] G x x x x x x x x x') J('1 [dup 1 <<] G x x x x x x x x x pop')
``` ```
1 2 4 8 16 32 64 128 256 [512 swap [dup 1 <<] direco] 1 2 4 8 16 32 64 128 256
# `n [x] times` ### `[x] times`
If we have one of these quoted programs we can drive it using `times` with the `x` combinator. If we have one of these quoted programs we can drive it using `times` with the `x` combinator.
Let's define a word `n_range` that takes a starting integer and a count and leaves that many consecutive integers on the stack. For example:
```python ```python
J('23 [dup ++] G 5 [x] times pop') J('23 [dup ++] G 5 [x] times')
``` ```
23 24 25 26 27 23 24 25 26 27 [28 swap [dup ++] direco]
We can use `dip` to untangle `[dup ++] G` from the arguments.
```python
J('23 5 [[dup ++] G] dip [x] times pop')
```
23 24 25 26 27
Now that the givens (arguments) are on the left we have the definition we're looking for:
```python
define('n_range == [[dup ++] G] dip [x] times pop')
```
```python
J('450 10 n_range')
```
450 451 452 453 454 455 456 457 458 459
This is better just using the `times` combinator though...
```python
J('450 9 [dup ++] times')
```
450 451 452 453 454 455 456 457 458 459
# Generating Multiples of Three and Five # Generating Multiples of Three and Five
@ -273,14 +208,6 @@ J('14811 [PE1.1] G')
[14811 swap [PE1.1] direco] [14811 swap [PE1.1] direco]
```python
J('[14811 swap [PE1.1] direco] x')
```
3 [3702 swap [PE1.1] direco]
...we get a generator that works for seven cycles before it reaches zero: ...we get a generator that works for seven cycles before it reaches zero:
@ -300,6 +227,14 @@ define('PE1.1.check == dup [pop 14811] [] branch')
``` ```
```python
J('14811 [PE1.1.check PE1.1] G')
```
[14811 swap [PE1.1.check PE1.1] direco]
```python ```python
J('[14811 swap [PE1.1.check PE1.1] direco] 21 [x] times') J('[14811 swap [PE1.1.check PE1.1] direco] 21 [x] times')
``` ```
@ -307,6 +242,8 @@ J('[14811 swap [PE1.1.check PE1.1] direco] 21 [x] times')
3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 [0 swap [PE1.1.check PE1.1] direco] 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 [0 swap [PE1.1.check PE1.1] direco]
(It would be more efficient to reset the int every seven cycles but that's a little beyond the scope of this article. This solution does extra work, but not much, and we're not using it "in production" as they say.)
### Run 466 times ### Run 466 times
In the PE1 problem we are asked to sum all the multiples of three and five less than 1000. It's worked out that we need to use all seven numbers sixty-six times and then four more. In the PE1 problem we are asked to sum all the multiples of three and five less than 1000. It's worked out that we need to use all seven numbers sixty-six times and then four more.
@ -322,15 +259,15 @@ If we drive our generator 466 times and sum the stack we get 999.
```python ```python
J('[14811 swap [PE1.1.check PE1.1] dip rest cons] 466 [x] times') J('[14811 swap [PE1.1.check PE1.1] direco] 466 [x] times')
``` ```
3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 [57 swap [PE1.1.check PE1.1] dip rest cons] 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 [57 swap [PE1.1.check PE1.1] direco]
```python ```python
J('[14811 swap [PE1.1.check PE1.1] dip rest cons] 466 [x] times pop enstacken sum') J('[14811 swap [PE1.1.check PE1.1] direco] 466 [x] times pop enstacken sum')
``` ```
999 999
@ -343,17 +280,7 @@ J('[14811 swap [PE1.1.check PE1.1] dip rest cons] 466 [x] times pop enstacken su
define('PE1.2 == + dup [+] dip') define('PE1.2 == + dup [+] dip')
``` ```
Now we can add `PE1.2` to the quoted program given to `times`. Now we can add `PE1.2` to the quoted program given to `G`.
```python
J('0 0 [0 swap [PE1.1.check PE1.1] direco] 466 [x [PE1.2] dip] times popop')
```
233168
Or using `G` we can write:
```python ```python
@ -401,24 +328,25 @@ And therefore:
[b+a b a F] [popdd over] infra [b+a b a F] [popdd over] infra
[b b+a b F] [b b+a b F]
And lastly: But we can just use `cons` to carry `b+a` into the quote:
[b a F] b+a [popdd over] cons infra
[b a F] [b+a popdd over] infra
[b b+a b F]
Lastly:
[b b+a b F] uncons [b b+a b F] uncons
b [b+a b F] b [b+a b F]
Done.
Putting it all together: Putting it all together:
F == + swons [popdd over] infra uncons F == + [popdd over] cons infra uncons
And:
fib_gen == [1 1 F] fib_gen == [1 1 F]
```python ```python
define('fib == + swons [popdd over] infra uncons') define('fib == + [popdd over] cons infra uncons')
``` ```
@ -435,7 +363,8 @@ J('fib_gen 10 [x] times')
### Project Euler Problem Two ### Project Euler Problem Two
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms. By considering the terms in the Fibonacci sequence whose values do not exceed four million,
find the sum of the even-valued terms.
Now that we have a generator for the Fibonacci sequence, we need a function that adds a term in the sequence to a sum if it is even, and `pop`s it otherwise. Now that we have a generator for the Fibonacci sequence, we need a function that adds a term in the sequence to a sum if it is even, and `pop`s it otherwise.
@ -536,3 +465,44 @@ J('0 [1 0 fib] PE2.2 [pop >4M] [popop] [[PE2.1] dip PE2.2] primrec')
# How to compile these? # How to compile these?
You would probably start with a special version of `G`, and perhaps modifications to the default `x`? You would probably start with a special version of `G`, and perhaps modifications to the default `x`?
# An Interesting Variation
```python
define('codireco == cons dip rest cons')
```
```python
V('[0 [dup ++] codireco] x')
```
. [0 [dup ++] codireco] x
[0 [dup ++] codireco] . x
[0 [dup ++] codireco] . 0 [dup ++] codireco
[0 [dup ++] codireco] 0 . [dup ++] codireco
[0 [dup ++] codireco] 0 [dup ++] . codireco
[0 [dup ++] codireco] 0 [dup ++] . cons dip rest cons
[0 [dup ++] codireco] [0 dup ++] . dip rest cons
. 0 dup ++ [0 [dup ++] codireco] rest cons
0 . dup ++ [0 [dup ++] codireco] rest cons
0 0 . ++ [0 [dup ++] codireco] rest cons
0 1 . [0 [dup ++] codireco] rest cons
0 1 [0 [dup ++] codireco] . rest cons
0 1 [[dup ++] codireco] . cons
0 [1 [dup ++] codireco] .
```python
define('G == [codireco] cons cons')
```
```python
J('230 [dup ++] G 5 [x] times pop')
```
230 231 232 233 234

View File

@ -8,41 +8,49 @@ Cf. jp-reprod.html
from notebook_preamble import J, V, define from notebook_preamble import J, V, define
Consider the ``x`` combinator ``x == dup i``: Consider the ``x`` combinator:
::
x == dup i
We can apply it to a quoted program consisting of some value ``a`` and a
function ``B``:
:: ::
[a B] x [a B] x
[a B] a B [a B] a B
Let ``B`` ``swap`` the ``a`` with the quote and run some function Let ``B`` function ``swap`` the ``a`` with the quote and run some
``[C]`` on it. function ``C`` on it to generate a new value ``b``:
:: ::
B == swap [C] dip
[a B] a B [a B] a B
[a B] a swap [C] dip [a B] a swap [C] dip
a [a B] [C] dip a [a B] [C] dip
a C [a B] a C [a B]
b [a B]
Now discard the quoted ``a`` with ``rest`` and ``cons`` the result of Now discard the quoted ``a`` with ``rest`` then ``cons`` ``b``:
``C`` on ``a`` whatever that is:
:: ::
aC [a B] rest cons b [a B] rest cons
aC [B] cons b [B] cons
[aC B] [b B]
Altogether, this is the definition of ``B``: Putting it together, this is the definition of ``B``:
:: ::
B == swap [C] dip rest cons B == swap [C] dip rest cons
We can create a quoted program that generates the Natural numbers We can create a quoted program that generates the Natural numbers (0, 1,
(integers 0, 1, 2, ...) by using ``0`` for ``a`` and ``[dup ++]`` for 2, ...) by using ``0`` for ``a`` and ``[dup ++]`` for ``[C]``:
``[C]``:
:: ::
@ -113,19 +121,16 @@ After one application of ``x`` the quoted program contains ``1`` and
0 [1 swap [dup ++] direco] . 0 [1 swap [dup ++] direco] .
Generating Generators Making Generators
===================== =================
We want to go from: We want to define a function that accepts ``a`` and ``[C]`` and builds
our quoted program:
:: ::
a [C] G a [C] G
-------------------------
to:
::
[a swap [C] direco] [a swap [C] direco]
Working in reverse: Working in reverse:
@ -145,65 +150,30 @@ Reading from the bottom up:
G == [direco] cons [swap] swap concat cons G == [direco] cons [swap] swap concat cons
G == [direco] cons [swap] swoncat cons G == [direco] cons [swap] swoncat cons
We can try it out:
::
0 [dup ++] G
.. code:: ipython2 .. code:: ipython2
define('G == [direco] cons [swap] swoncat cons') define('G == [direco] cons [swap] swoncat cons')
Let's try it out:
.. code:: ipython2 .. code:: ipython2
V('0 [dup ++] G') J('0 [dup ++] G')
.. parsed-literal:: .. parsed-literal::
. 0 [dup ++] G [0 swap [dup ++] direco]
0 . [dup ++] G
0 [dup ++] . G
0 [dup ++] . [direco] cons [swap] swoncat cons
0 [dup ++] [direco] . cons [swap] swoncat cons
0 [[dup ++] direco] . [swap] swoncat cons
0 [[dup ++] direco] [swap] . swoncat cons
0 [[dup ++] direco] [swap] . swap concat cons
0 [swap] [[dup ++] direco] . concat cons
0 [swap [dup ++] direco] . cons
[0 swap [dup ++] direco] .
.. code:: ipython2 .. code:: ipython2
V('0 [dup ++] G x') J('0 [dup ++] G x x x pop')
.. parsed-literal:: .. parsed-literal::
. 0 [dup ++] G x 0 1 2
0 . [dup ++] G x
0 [dup ++] . G x
0 [dup ++] . [direco] cons [swap] swoncat cons x
0 [dup ++] [direco] . cons [swap] swoncat cons x
0 [[dup ++] direco] . [swap] swoncat cons x
0 [[dup ++] direco] [swap] . swoncat cons x
0 [[dup ++] direco] [swap] . swap concat cons x
0 [swap] [[dup ++] direco] . concat cons x
0 [swap [dup ++] direco] . cons x
[0 swap [dup ++] direco] . x
[0 swap [dup ++] direco] . 0 swap [dup ++] direco
[0 swap [dup ++] direco] 0 . swap [dup ++] direco
0 [0 swap [dup ++] direco] . [dup ++] direco
0 [0 swap [dup ++] direco] [dup ++] . direco
0 [0 swap [dup ++] direco] [dup ++] . dip rest cons
0 . dup ++ [0 swap [dup ++] direco] rest cons
0 0 . ++ [0 swap [dup ++] direco] rest cons
0 1 . [0 swap [dup ++] direco] rest cons
0 1 [0 swap [dup ++] direco] . rest cons
0 1 [swap [dup ++] direco] . cons
0 [1 swap [dup ++] direco] .
Powers of 2 Powers of 2
@ -211,73 +181,28 @@ Powers of 2
.. code:: ipython2 .. code:: ipython2
J('1 [dup 1 <<] G x x x x x x x x x') J('1 [dup 1 <<] G x x x x x x x x x pop')
.. parsed-literal:: .. parsed-literal::
1 2 4 8 16 32 64 128 256 [512 swap [dup 1 <<] direco] 1 2 4 8 16 32 64 128 256
``n [x] times`` ``[x] times``
=============== ~~~~~~~~~~~~~
If we have one of these quoted programs we can drive it using ``times`` If we have one of these quoted programs we can drive it using ``times``
with the ``x`` combinator. with the ``x`` combinator.
Let's define a word ``n_range`` that takes a starting integer and a
count and leaves that many consecutive integers on the stack. For
example:
.. code:: ipython2 .. code:: ipython2
J('23 [dup ++] G 5 [x] times pop') J('23 [dup ++] G 5 [x] times')
.. parsed-literal:: .. parsed-literal::
23 24 25 26 27 23 24 25 26 27 [28 swap [dup ++] direco]
We can use ``dip`` to untangle ``[dup ++] G`` from the arguments.
.. code:: ipython2
J('23 5 [[dup ++] G] dip [x] times pop')
.. parsed-literal::
23 24 25 26 27
Now that the givens (arguments) are on the left we have the definition
we're looking for:
.. code:: ipython2
define('n_range == [[dup ++] G] dip [x] times pop')
.. code:: ipython2
J('450 10 n_range')
.. parsed-literal::
450 451 452 453 454 455 456 457 458 459
This is better just using the ``times`` combinator though...
.. code:: ipython2
J('450 9 [dup ++] times')
.. parsed-literal::
450 451 452 453 454 455 456 457 458 459
Generating Multiples of Three and Five Generating Multiples of Three and Five
@ -338,16 +263,6 @@ If we plug ``14811`` and ``[PE1.1]`` into our generator form...
[14811 swap [PE1.1] direco] [14811 swap [PE1.1] direco]
.. code:: ipython2
J('[14811 swap [PE1.1] direco] x')
.. parsed-literal::
3 [3702 swap [PE1.1] direco]
...we get a generator that works for seven cycles before it reaches ...we get a generator that works for seven cycles before it reaches
zero: zero:
@ -371,6 +286,16 @@ if so.
define('PE1.1.check == dup [pop 14811] [] branch') define('PE1.1.check == dup [pop 14811] [] branch')
.. code:: ipython2
J('14811 [PE1.1.check PE1.1] G')
.. parsed-literal::
[14811 swap [PE1.1.check PE1.1] direco]
.. code:: ipython2 .. code:: ipython2
J('[14811 swap [PE1.1.check PE1.1] direco] 21 [x] times') J('[14811 swap [PE1.1.check PE1.1] direco] 21 [x] times')
@ -381,6 +306,11 @@ if so.
3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 [0 swap [PE1.1.check PE1.1] direco] 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 [0 swap [PE1.1.check PE1.1] direco]
(It would be more efficient to reset the int every seven cycles but
that's a little beyond the scope of this article. This solution does
extra work, but not much, and we're not using it "in production" as they
say.)
Run 466 times Run 466 times
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
@ -402,17 +332,17 @@ If we drive our generator 466 times and sum the stack we get 999.
.. code:: ipython2 .. code:: ipython2
J('[14811 swap [PE1.1.check PE1.1] dip rest cons] 466 [x] times') J('[14811 swap [PE1.1.check PE1.1] direco] 466 [x] times')
.. parsed-literal:: .. parsed-literal::
3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 [57 swap [PE1.1.check PE1.1] dip rest cons] 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 [57 swap [PE1.1.check PE1.1] direco]
.. code:: ipython2 .. code:: ipython2
J('[14811 swap [PE1.1.check PE1.1] dip rest cons] 466 [x] times pop enstacken sum') J('[14811 swap [PE1.1.check PE1.1] direco] 466 [x] times pop enstacken sum')
.. parsed-literal:: .. parsed-literal::
@ -427,19 +357,7 @@ Project Euler Problem One
define('PE1.2 == + dup [+] dip') define('PE1.2 == + dup [+] dip')
Now we can add ``PE1.2`` to the quoted program given to ``times``. Now we can add ``PE1.2`` to the quoted program given to ``G``.
.. code:: ipython2
J('0 0 [0 swap [PE1.1.check PE1.1] direco] 466 [x [PE1.2] dip] times popop')
.. parsed-literal::
233168
Or using ``G`` we can write:
.. code:: ipython2 .. code:: ipython2
@ -507,30 +425,31 @@ And therefore:
[b+a b a F] [popdd over] infra [b+a b a F] [popdd over] infra
[b b+a b F] [b b+a b F]
And lastly: But we can just use ``cons`` to carry ``b+a`` into the quote:
::
[b a F] b+a [popdd over] cons infra
[b a F] [b+a popdd over] infra
[b b+a b F]
Lastly:
:: ::
[b b+a b F] uncons [b b+a b F] uncons
b [b+a b F] b [b+a b F]
Done.
Putting it all together: Putting it all together:
:: ::
F == + swons [popdd over] infra uncons F == + [popdd over] cons infra uncons
And:
::
fib_gen == [1 1 F] fib_gen == [1 1 F]
.. code:: ipython2 .. code:: ipython2
define('fib == + swons [popdd over] infra uncons') define('fib == + [popdd over] cons infra uncons')
.. code:: ipython2 .. code:: ipython2
@ -551,7 +470,8 @@ Project Euler Problem Two
:: ::
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms. By considering the terms in the Fibonacci sequence whose values do not exceed four million,
find the sum of the even-valued terms.
Now that we have a generator for the Fibonacci sequence, we need a Now that we have a generator for the Fibonacci sequence, we need a
function that adds a term in the sequence to a sum if it is even, and function that adds a term in the sequence to a sum if it is even, and
@ -673,3 +593,47 @@ How to compile these?
You would probably start with a special version of ``G``, and perhaps You would probably start with a special version of ``G``, and perhaps
modifications to the default ``x``? modifications to the default ``x``?
An Interesting Variation
========================
.. code:: ipython2
define('codireco == cons dip rest cons')
.. code:: ipython2
V('[0 [dup ++] codireco] x')
.. parsed-literal::
. [0 [dup ++] codireco] x
[0 [dup ++] codireco] . x
[0 [dup ++] codireco] . 0 [dup ++] codireco
[0 [dup ++] codireco] 0 . [dup ++] codireco
[0 [dup ++] codireco] 0 [dup ++] . codireco
[0 [dup ++] codireco] 0 [dup ++] . cons dip rest cons
[0 [dup ++] codireco] [0 dup ++] . dip rest cons
. 0 dup ++ [0 [dup ++] codireco] rest cons
0 . dup ++ [0 [dup ++] codireco] rest cons
0 0 . ++ [0 [dup ++] codireco] rest cons
0 1 . [0 [dup ++] codireco] rest cons
0 1 [0 [dup ++] codireco] . rest cons
0 1 [[dup ++] codireco] . cons
0 [1 [dup ++] codireco] .
.. code:: ipython2
define('G == [codireco] cons cons')
.. code:: ipython2
J('230 [dup ++] G 5 [x] times pop')
.. parsed-literal::
230 231 232 233 234

View File

@ -13729,7 +13729,7 @@ tails == [] [not] [rest swons] [rest] paramorphism</code></pre>
<li>A predicate <code>P :: A -&gt; Bool</code> to detect the base case</li> <li>A predicate <code>P :: A -&gt; Bool</code> to detect the base case</li>
<li>A base case value <code>c :: B</code></li> <li>A base case value <code>c :: B</code></li>
</ul> </ul>
<h3 id="Hylo--Ana-,-Cata-">Hylo- Ana-, Cata-<a class="anchor-link" href="#Hylo--Ana-,-Cata-">&#182;</a></h3> <h3 id="Hylo-,-Ana-,-Cata-">Hylo-, Ana-, Cata-<a class="anchor-link" href="#Hylo-,-Ana-,-Cata-">&#182;</a></h3>
<pre><code>w/ G :: A -&gt; (A, B) <pre><code>w/ G :: A -&gt; (A, B)
H == [P ] [pop c ] [G ] [dip F ] genrec H == [P ] [pop c ] [G ] [dip F ] genrec
@ -13854,7 +13854,7 @@ H == c swap [P] [pop] [ [F] dupdip G] [i] genrec
</div> </div>
<div class="inner_cell"> <div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html"> <div class="text_cell_render border-box-sizing rendered_html">
<h3 id="4">4<a class="anchor-link" href="#4">&#182;</a></h3><p>And, last but not least, if you can combine as you go, starting with c, and the combiner needs to work on the current item this is the form:</p> <h3 id="4">4<a class="anchor-link" href="#4">&#182;</a></h3><p>And, last but not least, if you can combine as you go, starting with c, and the combiner needs to work on the current item, this is the form:</p>
<pre><code>W == c swap [P] [pop] [[F] dupdip G] primrec <pre><code>W == c swap [P] [pop] [[F] dupdip G] primrec

View File

@ -1432,7 +1432,7 @@ Our story so far...
- A base case value `c :: B` - A base case value `c :: B`
### Hylo- Ana-, Cata- ### Hylo-, Ana-, Cata-
w/ G :: A -> (A, B) w/ G :: A -> (A, B)
@ -1526,7 +1526,7 @@ If the combiner and the generator both need to work on the current value then `d
... c a'' F a' F a F ... c a'' F a' F a F
### 4 ### 4
And, last but not least, if you can combine as you go, starting with c, and the combiner needs to work on the current item this is the form: And, last but not least, if you can combine as you go, starting with c, and the combiner needs to work on the current item, this is the form:
W == c swap [P] [pop] [[F] dupdip G] primrec W == c swap [P] [pop] [[F] dupdip G] primrec

View File

@ -1571,8 +1571,8 @@ Our story so far...
- A predicate ``P :: A -> Bool`` to detect the base case - A predicate ``P :: A -> Bool`` to detect the base case
- A base case value ``c :: B`` - A base case value ``c :: B``
Hylo- Ana-, Cata- Hylo-, Ana-, Cata-
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
:: ::
@ -1706,7 +1706,7 @@ one item instead of two (the b is instead the duplicate of a.)
~ ~
And, last but not least, if you can combine as you go, starting with c, And, last but not least, if you can combine as you go, starting with c,
and the combiner needs to work on the current item this is the form: and the combiner needs to work on the current item, this is the form:
:: ::

14553
docs/Ordered_Binary_Trees.html Normal file

File diff suppressed because it is too large Load Diff

1285
docs/Ordered_Binary_Trees.md Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -11920,10 +11920,10 @@ key left-keys right-keys
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[1]:</div> <div class="prompt input_prompt">In&nbsp;[6]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="kn">from</span> <span class="nn">notebook_preamble</span> <span class="kn">import</span> <span class="n">J</span><span class="p">,</span> <span class="n">V</span><span class="p">,</span> <span class="n">define</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="kn">from</span> <span class="nn">notebook_preamble</span> <span class="kn">import</span> <span class="n">D</span><span class="p">,</span> <span class="n">J</span><span class="p">,</span> <span class="n">V</span><span class="p">,</span> <span class="n">define</span><span class="p">,</span> <span class="n">DefinitionWrapper</span>
</pre></div> </pre></div>
</div> </div>
@ -13008,7 +13008,7 @@ E == pop swap roll&lt; rest rest cons cons
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
<div class="prompt input_prompt">In&nbsp;[30]:</div> <div class="prompt input_prompt">In&nbsp;[11]:</div>
<div class="inner_cell"> <div class="inner_cell">
<div class="input_area"> <div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="kn">from</span> <span class="nn">joy.library</span> <span class="kn">import</span> <span class="n">FunctionWrapper</span> <div class=" highlight hl-ipython2"><pre><span></span><span class="kn">from</span> <span class="nn">joy.library</span> <span class="kn">import</span> <span class="n">FunctionWrapper</span>
@ -13018,6 +13018,22 @@ E == pop swap roll&lt; rest rest cons cons
<span class="nd">@FunctionWrapper</span> <span class="nd">@FunctionWrapper</span>
<span class="k">def</span> <span class="nf">cmp_</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span><span class="p">):</span> <span class="k">def</span> <span class="nf">cmp_</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span><span class="p">):</span>
<span class="sd">&#39;&#39;&#39;</span>
<span class="sd"> cmp takes two values and three quoted programs on the stack and runs</span>
<span class="sd"> one of the three depending on the results of comparing the two values:</span>
<span class="sd"> a b [G] [E] [L] cmp</span>
<span class="sd"> ------------------------- a &gt; b</span>
<span class="sd"> G</span>
<span class="sd"> a b [G] [E] [L] cmp</span>
<span class="sd"> ------------------------- a = b</span>
<span class="sd"> E</span>
<span class="sd"> a b [G] [E] [L] cmp</span>
<span class="sd"> ------------------------- a &lt; b</span>
<span class="sd"> L</span>
<span class="sd"> &#39;&#39;&#39;</span>
<span class="n">L</span><span class="p">,</span> <span class="p">(</span><span class="n">E</span><span class="p">,</span> <span class="p">(</span><span class="n">G</span><span class="p">,</span> <span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">stack</span><span class="p">))))</span> <span class="o">=</span> <span class="n">stack</span> <span class="n">L</span><span class="p">,</span> <span class="p">(</span><span class="n">E</span><span class="p">,</span> <span class="p">(</span><span class="n">G</span><span class="p">,</span> <span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">stack</span><span class="p">))))</span> <span class="o">=</span> <span class="n">stack</span>
<span class="n">expression</span> <span class="o">=</span> <span class="n">pushback</span><span class="p">(</span><span class="n">G</span> <span class="k">if</span> <span class="n">a</span> <span class="o">&gt;</span> <span class="n">b</span> <span class="k">else</span> <span class="n">L</span> <span class="k">if</span> <span class="n">a</span> <span class="o">&lt;</span> <span class="n">b</span> <span class="k">else</span> <span class="n">E</span><span class="p">,</span> <span class="n">expression</span><span class="p">)</span> <span class="n">expression</span> <span class="o">=</span> <span class="n">pushback</span><span class="p">(</span><span class="n">G</span> <span class="k">if</span> <span class="n">a</span> <span class="o">&gt;</span> <span class="n">b</span> <span class="k">else</span> <span class="n">L</span> <span class="k">if</span> <span class="n">a</span> <span class="o">&lt;</span> <span class="n">b</span> <span class="k">else</span> <span class="n">E</span><span class="p">,</span> <span class="n">expression</span><span class="p">)</span>
<span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span> <span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span>
@ -13030,6 +13046,59 @@ E == pop swap roll&lt; rest rest cons cons
</div> </div>
</div> </div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[14]:</div>
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="kn">from</span> <span class="nn">joy.library</span> <span class="kn">import</span> <span class="n">FunctionWrapper</span><span class="p">,</span> <span class="n">S_ifte</span>
<span class="nd">@FunctionWrapper</span>
<span class="k">def</span> <span class="nf">cond</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span><span class="p">):</span>
<span class="sd">&#39;&#39;&#39;</span>
<span class="sd"> like a case statement; works by rewriting into a chain of ifte.</span>
<span class="sd"> [..[[Bi] Ti]..[D]] -&gt; ...</span>
<span class="sd"> [[[B0] T0] [[B1] T1] [D]] cond</span>
<span class="sd"> -----------------------------------------</span>
<span class="sd"> [B0] [T0] [[B1] [T1] [D] ifte] ifte</span>
<span class="sd"> &#39;&#39;&#39;</span>
<span class="n">conditions</span><span class="p">,</span> <span class="n">stack</span> <span class="o">=</span> <span class="n">stack</span>
<span class="k">if</span> <span class="n">conditions</span><span class="p">:</span>
<span class="n">expression</span> <span class="o">=</span> <span class="n">_cond</span><span class="p">(</span><span class="n">conditions</span><span class="p">,</span> <span class="n">expression</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="c1"># Attempt to preload the args to first ifte.</span>
<span class="p">(</span><span class="n">P</span><span class="p">,</span> <span class="p">(</span><span class="n">T</span><span class="p">,</span> <span class="p">(</span><span class="n">E</span><span class="p">,</span> <span class="n">expression</span><span class="p">)))</span> <span class="o">=</span> <span class="n">expression</span>
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
<span class="c1"># If, for any reason, the argument to cond should happen to contain</span>
<span class="c1"># only the default clause then this optimization will fail.</span>
<span class="k">pass</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">stack</span> <span class="o">=</span> <span class="p">(</span><span class="n">E</span><span class="p">,</span> <span class="p">(</span><span class="n">T</span><span class="p">,</span> <span class="p">(</span><span class="n">P</span><span class="p">,</span> <span class="n">stack</span><span class="p">)))</span>
<span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span>
<span class="k">def</span> <span class="nf">_cond</span><span class="p">(</span><span class="n">conditions</span><span class="p">,</span> <span class="n">expression</span><span class="p">):</span>
<span class="p">(</span><span class="n">clause</span><span class="p">,</span> <span class="n">rest</span><span class="p">)</span> <span class="o">=</span> <span class="n">conditions</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">rest</span><span class="p">:</span> <span class="c1"># clause is [D]</span>
<span class="k">return</span> <span class="n">clause</span>
<span class="n">P</span><span class="p">,</span> <span class="n">T</span> <span class="o">=</span> <span class="n">clause</span>
<span class="k">return</span> <span class="p">(</span><span class="n">P</span><span class="p">,</span> <span class="p">(</span><span class="n">T</span><span class="p">,</span> <span class="p">(</span><span class="n">_cond</span><span class="p">(</span><span class="n">rest</span><span class="p">,</span> <span class="p">()),</span> <span class="p">(</span><span class="n">S_ifte</span><span class="p">,</span> <span class="n">expression</span><span class="p">))))</span>
<span class="n">D</span><span class="p">[</span><span class="s1">&#39;cond&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">cond</span>
</pre></div>
</div>
</div>
</div>
</div> </div>
<div class="cell border-box-sizing code_cell rendered"> <div class="cell border-box-sizing code_cell rendered">
<div class="input"> <div class="input">
@ -13726,15 +13795,15 @@ BTree-get == [pop not] swap [] [P [T&gt;] [E] [T&lt;] cmp] genrec</code></pre>
</div> </div>
<div class="inner_cell"> <div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html"> <div class="text_cell_render border-box-sizing rendered_html">
<h1 id="TODO:-BTree-delete">TODO: BTree-delete<a class="anchor-link" href="#TODO:-BTree-delete">&#182;</a></h1><p>Then, once we have add, get, and delete we can see about abstracting them.</p> <h1 id="BTree-delete">BTree-delete<a class="anchor-link" href="#BTree-delete">&#182;</a></h1><p>Now let's write a function that can return a tree datastructure with a key, value pair deleted:</p>
<pre><code> tree key [E] BTree-delete <pre><code> tree key BTree-delete
---------------------------- key in tree ---------------------------
tree tree
tree key [E] BTree-delete
---------------------------- key not in tree </code></pre>
tree key E</code></pre> <p>If the key is not in tree it just returns the tree unchanged.</p>
</div> </div>
</div> </div>
@ -13745,18 +13814,7 @@ BTree-get == [pop not] swap [] [P [T&gt;] [E] [T&lt;] cmp] genrec</code></pre>
<div class="text_cell_render border-box-sizing rendered_html"> <div class="text_cell_render border-box-sizing rendered_html">
<p>So:</p> <p>So:</p>
<pre><code>BTree-delete == [pop not] [] [R0] [R1] genrec <pre><code>BTree-Delete == [pop not] swap [R0] [R1] genrec</code></pre>
</code></pre>
<p>And:</p>
<pre><code>[n_key n_value left right] key R0 [BTree-get] R1
[n_key n_value left right] key [dup first] dip [BTree-get] R1
[n_key n_value left right] n_key key [BTree-get] R1
[n_key n_value left right] n_key key [BTree-get] roll&gt; [T&gt;] [E] [T&lt;] cmp
[n_key n_value left right] [BTree-get] n_key key [T&gt;] [E] [T&lt;] cmp
BTree-delete == [pop not] swap [[dup first] dip] [roll&gt; [T&gt;] [E] [T&lt;] cmp] genrec</code></pre>
</div> </div>
</div> </div>
@ -13766,9 +13824,9 @@ BTree-delete == [pop not] swap [[dup first] dip] [roll&gt; [T&gt;] [E] [T&lt;] c
<div class="inner_cell"> <div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html"> <div class="text_cell_render border-box-sizing rendered_html">
<pre><code>[n_key n_value left right] [BTree-get] T&gt; <pre><code> [Er] BTree-delete
[n_key n_value left right] [BTree-get] E -------------------------------------
[n_key n_value left right] [BTree-get] T&lt;</code></pre> [pop not] [Er] [R0] [R1] genrec</code></pre>
</div> </div>
</div> </div>
@ -13782,6 +13840,633 @@ BTree-delete == [pop not] swap [[dup first] dip] [roll&gt; [T&gt;] [E] [T&lt;] c
[n_key n_value left right] [BTree-get] E [n_key n_value left right] [BTree-get] E
[n_key n_value left right] [BTree-get] T&lt;</code></pre> [n_key n_value left right] [BTree-get] T&lt;</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Now we get to figure out the recursive case:</p>
<pre><code>w/ D == [pop not] [Er] [R0] [R1] genrec
[node_key node_value left right] key R0 [D] R1
[node_key node_value left right] key over first swap dup [D] R1
[node_key node_value left right] node_key key key [D] R1
</code></pre>
<p>And then:</p>
<pre><code>[node_key node_value left right] node_key key key [D] R1
[node_key node_value left right] node_key key key [D] cons roll&gt; [T&gt;] [E] [T&lt;] cmp
[node_key node_value left right] node_key key [key D] roll&gt; [T&gt;] [E] [T&lt;] cmp
[node_key node_value left right] [key D] node_key key [T&gt;] [E] [T&lt;] cmp</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Now this:;</p>
<pre><code>[node_key node_value left right] [key D] node_key key [T&gt;] [E] [T&lt;] cmp
</code></pre>
<p>Becomes one of these three:;</p>
<pre><code>[node_key node_value left right] [key D] T&gt;
[node_key node_value left right] [key D] E
[node_key node_value left right] [key D] T&lt;</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="Greater-than-case-and-less-than-case">Greater than case and less than case<a class="anchor-link" href="#Greater-than-case-and-less-than-case">&#182;</a></h3>
<pre><code> [node_key node_value left right] [key D] T&gt;
-------------------------------------------------
[node_key node_value left key D right]</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>First:</p>
<pre><code>right left node_value node_key [key D] dipd
right left key D node_value node_key
right left' node_value node_key</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Ergo:</p>
<pre><code>[node_key node_value left right] [key D] [dipd] cons infra</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>So:</p>
<pre><code>T&gt; == [dipd] cons infra
T&lt; == [dipdd] cons infra</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="The-else-case">The else case<a class="anchor-link" href="#The-else-case">&#182;</a></h3>
<pre><code>[node_key node_value left right] [key D] E
</code></pre>
<p>We have to handle three cases, so let's use <code>cond</code>.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>The first two cases are symmetrical, if we only have one non-empty child node return it.</p>
<pre><code>E == [
[[pop third not] pop fourth]
[[pop fourth not] pop third]
[default]
] cond</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>(If both child nodes are empty return an empty node.)</p>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>The initial structure of the default function:</p>
<pre><code>default == [E'] cons infra
[node_key node_value left right] [key D] default
[node_key node_value left right] [key D] [E'] cons infra
[node_key node_value left right] [[key D] E'] infra
right left node_value node_key [key D] E'</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>If both child nodes are non-empty, we find the highest node in our lower sub-tree, take its key and value to replace (delete) our own, then get rid of it by recursively calling delete() on our lower sub-node with our new key.</p>
<p>(We could also find the lowest node in our higher sub-tree and take its key and value and delete it. I only implemented one of these two symmetrical options. Over a lot of deletions this might make the tree more unbalanced. Oh well.)</p>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>First things first, we no longer need this node's key and value:</p>
<pre><code>right left node_value node_key [key D] roll&gt; popop E''
right left [key D] node_value node_key popop E''
right left [key D] E''</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Then we have to we find the highest (right-most) node in our lower (left) sub-tree:</p>
<pre><code>right left [key D] E''</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Ditch the key:</p>
<pre><code>right left [key D] rest E'''
right left [D] E'''</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Find the right-most node:</p>
<pre><code>right left [D] [dup W] dip E''''
right left dup W [D] E''''
right left left W [D] E''''</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Consider:</p>
<pre><code>left W</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>We know left is not empty:</p>
<pre><code>[L_key L_value L_left L_right] W</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>We want to keep extracting the right node as long as it is not empty:</p>
<pre><code>left [P] [B] while W'</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>The predicate:</p>
<pre><code>[L_key L_value L_left L_right] P
[L_key L_value L_left L_right] fourth
L_right
</code></pre>
<p>(This has a bug, can run on <code>[]</code> so must be guarded:</p>
<pre><code>if_not_empty == [] swap [] ifte
?fourth == [fourth] if_not_empty
W.rightmost == [?fourth] [fourth] while</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>The body is also <code>fourth</code>:</p>
<pre><code>left [fourth] [fourth] while W'
rightest W'</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>We know rightest is not empty:</p>
<pre><code>[R_key R_value R_left R_right] W'
[R_key R_value R_left R_right] uncons uncons pop
R_key [R_value R_left R_right] uncons pop
R_key R_value [R_left R_right] pop
R_key R_value</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>So:</p>
<pre><code>W == [fourth] [fourth] while uncons uncons pop</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>And:</p>
<pre><code>right left left W [D] E''''
right left R_key R_value [D] E''''</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Final stretch. We want to end up with something like:</p>
<pre><code>right left [R_key D] i R_value R_key
right left R_key D R_value R_key
right left' R_value R_key</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>If we adjust our definition of <code>W</code> to include <code>over</code> at the end:</p>
<pre><code>W == [fourth] [fourth] while uncons uncons pop over</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>That will give us:</p>
<pre><code>right left R_key R_value R_key [D] E''''
right left R_key R_value R_key [D] cons dipdd E'''''
right left R_key R_value [R_key D] dipdd E'''''
right left R_key D R_key R_value E'''''
right left' R_key R_value E'''''
right left' R_key R_value swap
right left' R_value R_key</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>So:</p>
<pre><code>E' == roll&gt; popop E''
E'' == rest E'''
E''' == [dup W] dip E''''
E'''' == cons dipdd swap</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Substituting:</p>
<pre><code>W == [fourth] [fourth] while uncons uncons pop over
E' == roll&gt; popop rest [dup W] dip cons dipdd swap
E == [
[[pop third not] pop fourth]
[[pop fourth not] pop third]
[[E'] cons infra]
] cond</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Minor rearrangement:</p>
<pre><code>W == dup [fourth] [fourth] while uncons uncons pop over
E' == roll&gt; popop rest [W] dip cons dipdd swap
E == [
[[pop third not] pop fourth]
[[pop fourth not] pop third]
[[E'] cons infra]
] cond</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="Refactoring">Refactoring<a class="anchor-link" href="#Refactoring">&#182;</a></h3>
<pre><code>W.rightmost == [fourth] [fourth] while
W.unpack == uncons uncons pop
E.clear_stuff == roll&gt; popop rest
E.delete == cons dipdd
W == dup W.rightmost W.unpack over
E.0 == E.clear_stuff [W] dip E.delete swap
E == [
[[pop third not] pop fourth]
[[pop fourth not] pop third]
[[E.0] cons infra]
] cond
T&gt; == [dipd] cons infra
T&lt; == [dipdd] cons infra
R0 == over first swap dup
R1 == cons roll&gt; [T&gt;] [E] [T&lt;] cmp
BTree-Delete == [pop not] swap [R0] [R1] genrec
</code></pre>
<p>By the standards of the code I've written so far, this is a <em>huge</em> Joy program.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[20]:</div>
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">DefinitionWrapper</span><span class="o">.</span><span class="n">add_definitions</span><span class="p">(</span><span class="s1">&#39;&#39;&#39;</span>
<span class="s1">first_two == uncons uncons pop</span>
<span class="s1">fourth == rest rest rest first</span>
<span class="s1">?fourth == [] [fourth] [] ifte</span>
<span class="s1">W.rightmost == [?fourth] [fourth] while</span>
<span class="s1">E.clear_stuff == roll&gt; popop rest</span>
<span class="s1">E.delete == cons dipdd</span>
<span class="s1">W == dup W.rightmost first_two over</span>
<span class="s1">E.0 == E.clear_stuff [W] dip E.delete swap</span>
<span class="s1">E == [[[pop third not] pop fourth] [[pop fourth not] pop third] [[E.0] cons infra]] cond</span>
<span class="s1">T&gt; == [dipd] cons infra</span>
<span class="s1">T&lt; == [dipdd] cons infra</span>
<span class="s1">R0 == over first swap dup</span>
<span class="s1">R1 == cons roll&gt; [T&gt;] [E] [T&lt;] cmp</span>
<span class="s1">BTree-Delete == [pop not] swap [R0] [R1] genrec&#39;&#39;&#39;</span><span class="p">,</span> <span class="n">D</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[23]:</div>
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;[&#39;a&#39; 23 [] [&#39;b&#39; 88 [] [&#39;c&#39; 44 [] []]]] &#39;c&#39; [&#39;Er&#39;] BTree-Delete &quot;</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="prompt"></div>
<div class="output_subarea output_stream output_stdout output_text">
<pre>[&#39;a&#39; 23 [] [&#39;b&#39; 88 [] []]]
</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[24]:</div>
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;[&#39;a&#39; 23 [] [&#39;b&#39; 88 [] [&#39;c&#39; 44 [] []]]] &#39;b&#39; [&#39;Er&#39;] BTree-Delete &quot;</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="prompt"></div>
<div class="output_subarea output_stream output_stdout output_text">
<pre>[&#39;a&#39; 23 [] [&#39;c&#39; 44 [] []]]
</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[25]:</div>
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;[&#39;a&#39; 23 [] [&#39;b&#39; 88 [] [&#39;c&#39; 44 [] []]]] &#39;a&#39; [&#39;Er&#39;] BTree-Delete &quot;</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="prompt"></div>
<div class="output_subarea output_stream output_stdout output_text">
<pre>[&#39;b&#39; 88 [] [&#39;c&#39; 44 [] []]]
</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[26]:</div>
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;[&#39;a&#39; 23 [] [&#39;b&#39; 88 [] [&#39;c&#39; 44 [] []]]] &#39;der&#39; [&#39;Er&#39;] BTree-Delete &quot;</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="prompt"></div>
<div class="output_subarea output_stream output_stdout output_text">
<pre>[&#39;a&#39; 23 [] [&#39;b&#39; 88 [] [&#39;c&#39; 44 [] &#39;Er&#39; &#39;der&#39; []]]]
</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[30]:</div>
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython2"><pre><span></span><span class="n">J</span><span class="p">(</span><span class="s2">&quot;[&#39;a&#39; 23 [] [&#39;b&#39; 88 [] [&#39;c&#39; 44 [] []]]] &#39;der&#39; [pop] BTree-Delete &quot;</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="prompt"></div>
<div class="output_subarea output_stream output_stdout output_text">
<pre>[&#39;a&#39; 23 [] [&#39;b&#39; 88 [] [&#39;c&#39; 44 [] []]]]
</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>One bug, I forgot to put <code>not</code> in the first two clauses of the <code>cond</code>.</p>
<p>The behavior of the <code>[Er]</code> function should maybe be different: either just silently fail, or maybe implement some sort of function that can grab the pending expression up to a sentinel value or something, allowing for a kind of "except"-ish control-flow?</p>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Then, once we have add, get, and delete we can see about abstracting them.</p>
</div> </div>
</div> </div>
</div> </div>

View File

@ -92,7 +92,7 @@ Ergo:
```python ```python
from notebook_preamble import J, V, define from notebook_preamble import D, J, V, define, DefinitionWrapper
``` ```
@ -590,6 +590,22 @@ from notebook_preamble import D
@FunctionWrapper @FunctionWrapper
def cmp_(stack, expression, dictionary): def cmp_(stack, expression, dictionary):
'''
cmp takes two values and three quoted programs on the stack and runs
one of the three depending on the results of comparing the two values:
a b [G] [E] [L] cmp
------------------------- a > b
G
a b [G] [E] [L] cmp
------------------------- a = b
E
a b [G] [E] [L] cmp
------------------------- a < b
L
'''
L, (E, (G, (b, (a, stack)))) = stack L, (E, (G, (b, (a, stack)))) = stack
expression = pushback(G if a > b else L if a < b else E, expression) expression = pushback(G if a > b else L if a < b else E, expression)
return stack, expression, dictionary return stack, expression, dictionary
@ -599,6 +615,51 @@ D['cmp'] = cmp_
``` ```
```python
from joy.library import FunctionWrapper, S_ifte
@FunctionWrapper
def cond(stack, expression, dictionary):
'''
like a case statement; works by rewriting into a chain of ifte.
[..[[Bi] Ti]..[D]] -> ...
[[[B0] T0] [[B1] T1] [D]] cond
-----------------------------------------
[B0] [T0] [[B1] [T1] [D] ifte] ifte
'''
conditions, stack = stack
if conditions:
expression = _cond(conditions, expression)
try:
# Attempt to preload the args to first ifte.
(P, (T, (E, expression))) = expression
except ValueError:
# If, for any reason, the argument to cond should happen to contain
# only the default clause then this optimization will fail.
pass
else:
stack = (E, (T, (P, stack)))
return stack, expression, dictionary
def _cond(conditions, expression):
(clause, rest) = conditions
if not rest: # clause is [D]
return clause
P, T = clause
return (P, (T, (_cond(rest, ()), (S_ifte, expression))))
D['cond'] = cond
```
```python ```python
J("1 0 ['G'] ['E'] ['L'] cmp") J("1 0 ['G'] ['E'] ['L'] cmp")
``` ```
@ -913,40 +974,311 @@ J('''
2 2
# TODO: BTree-delete # BTree-delete
Then, once we have add, get, and delete we can see about abstracting them. Now let's write a function that can return a tree datastructure with a key, value pair deleted:
tree key [E] BTree-delete tree key BTree-delete
---------------------------- key in tree ---------------------------
tree tree
tree key [E] BTree-delete
---------------------------- key not in tree If the key is not in tree it just returns the tree unchanged.
tree key E
So: So:
BTree-delete == [pop not] [] [R0] [R1] genrec BTree-Delete == [pop not] swap [R0] [R1] genrec
And:
[n_key n_value left right] key R0 [BTree-get] R1 [Er] BTree-delete
[n_key n_value left right] key [dup first] dip [BTree-get] R1 -------------------------------------
[n_key n_value left right] n_key key [BTree-get] R1 [pop not] [Er] [R0] [R1] genrec
[n_key n_value left right] n_key key [BTree-get] roll> [T>] [E] [T<] cmp
[n_key n_value left right] [BTree-get] n_key key [T>] [E] [T<] cmp
BTree-delete == [pop not] swap [[dup first] dip] [roll> [T>] [E] [T<] cmp] genrec
[n_key n_value left right] [BTree-get] T>
[n_key n_value left right] [BTree-get] E
[n_key n_value left right] [BTree-get] T<
[n_key n_value left right] [BTree-get] [n_key n_value left right] [BTree-get]
[n_key n_value left right] [BTree-get] E [n_key n_value left right] [BTree-get] E
[n_key n_value left right] [BTree-get] T< [n_key n_value left right] [BTree-get] T<
Now we get to figure out the recursive case:
w/ D == [pop not] [Er] [R0] [R1] genrec
[node_key node_value left right] key R0 [D] R1
[node_key node_value left right] key over first swap dup [D] R1
[node_key node_value left right] node_key key key [D] R1
And then:
[node_key node_value left right] node_key key key [D] R1
[node_key node_value left right] node_key key key [D] cons roll> [T>] [E] [T<] cmp
[node_key node_value left right] node_key key [key D] roll> [T>] [E] [T<] cmp
[node_key node_value left right] [key D] node_key key [T>] [E] [T<] cmp
Now this:;
[node_key node_value left right] [key D] node_key key [T>] [E] [T<] cmp
Becomes one of these three:;
[node_key node_value left right] [key D] T>
[node_key node_value left right] [key D] E
[node_key node_value left right] [key D] T<
### Greater than case and less than case
[node_key node_value left right] [key D] T>
-------------------------------------------------
[node_key node_value left key D right]
First:
right left node_value node_key [key D] dipd
right left key D node_value node_key
right left' node_value node_key
Ergo:
[node_key node_value left right] [key D] [dipd] cons infra
So:
T> == [dipd] cons infra
T< == [dipdd] cons infra
### The else case
[node_key node_value left right] [key D] E
We have to handle three cases, so let's use `cond`.
The first two cases are symmetrical, if we only have one non-empty child node return it.
E == [
[[pop third not] pop fourth]
[[pop fourth not] pop third]
[default]
] cond
(If both child nodes are empty return an empty node.)
The initial structure of the default function:
default == [E'] cons infra
[node_key node_value left right] [key D] default
[node_key node_value left right] [key D] [E'] cons infra
[node_key node_value left right] [[key D] E'] infra
right left node_value node_key [key D] E'
If both child nodes are non-empty, we find the highest node in our lower sub-tree, take its key and value to replace (delete) our own, then get rid of it by recursively calling delete() on our lower sub-node with our new key.
(We could also find the lowest node in our higher sub-tree and take its key and value and delete it. I only implemented one of these two symmetrical options. Over a lot of deletions this might make the tree more unbalanced. Oh well.)
First things first, we no longer need this node's key and value:
right left node_value node_key [key D] roll> popop E''
right left [key D] node_value node_key popop E''
right left [key D] E''
Then we have to we find the highest (right-most) node in our lower (left) sub-tree:
right left [key D] E''
Ditch the key:
right left [key D] rest E'''
right left [D] E'''
Find the right-most node:
right left [D] [dup W] dip E''''
right left dup W [D] E''''
right left left W [D] E''''
Consider:
left W
We know left is not empty:
[L_key L_value L_left L_right] W
We want to keep extracting the right node as long as it is not empty:
left [P] [B] while W'
The predicate:
[L_key L_value L_left L_right] P
[L_key L_value L_left L_right] fourth
L_right
(This has a bug, can run on `[]` so must be guarded:
if_not_empty == [] swap [] ifte
?fourth == [fourth] if_not_empty
W.rightmost == [?fourth] [fourth] while
The body is also `fourth`:
left [fourth] [fourth] while W'
rightest W'
We know rightest is not empty:
[R_key R_value R_left R_right] W'
[R_key R_value R_left R_right] uncons uncons pop
R_key [R_value R_left R_right] uncons pop
R_key R_value [R_left R_right] pop
R_key R_value
So:
W == [fourth] [fourth] while uncons uncons pop
And:
right left left W [D] E''''
right left R_key R_value [D] E''''
Final stretch. We want to end up with something like:
right left [R_key D] i R_value R_key
right left R_key D R_value R_key
right left' R_value R_key
If we adjust our definition of `W` to include `over` at the end:
W == [fourth] [fourth] while uncons uncons pop over
That will give us:
right left R_key R_value R_key [D] E''''
right left R_key R_value R_key [D] cons dipdd E'''''
right left R_key R_value [R_key D] dipdd E'''''
right left R_key D R_key R_value E'''''
right left' R_key R_value E'''''
right left' R_key R_value swap
right left' R_value R_key
So:
E' == roll> popop E''
E'' == rest E'''
E''' == [dup W] dip E''''
E'''' == cons dipdd swap
Substituting:
W == [fourth] [fourth] while uncons uncons pop over
E' == roll> popop rest [dup W] dip cons dipdd swap
E == [
[[pop third not] pop fourth]
[[pop fourth not] pop third]
[[E'] cons infra]
] cond
Minor rearrangement:
W == dup [fourth] [fourth] while uncons uncons pop over
E' == roll> popop rest [W] dip cons dipdd swap
E == [
[[pop third not] pop fourth]
[[pop fourth not] pop third]
[[E'] cons infra]
] cond
### Refactoring
W.rightmost == [fourth] [fourth] while
W.unpack == uncons uncons pop
E.clear_stuff == roll> popop rest
E.delete == cons dipdd
W == dup W.rightmost W.unpack over
E.0 == E.clear_stuff [W] dip E.delete swap
E == [
[[pop third not] pop fourth]
[[pop fourth not] pop third]
[[E.0] cons infra]
] cond
T> == [dipd] cons infra
T< == [dipdd] cons infra
R0 == over first swap dup
R1 == cons roll> [T>] [E] [T<] cmp
BTree-Delete == [pop not] swap [R0] [R1] genrec
By the standards of the code I've written so far, this is a *huge* Joy program.
```python
DefinitionWrapper.add_definitions('''
first_two == uncons uncons pop
fourth == rest rest rest first
?fourth == [] [fourth] [] ifte
W.rightmost == [?fourth] [fourth] while
E.clear_stuff == roll> popop rest
E.delete == cons dipdd
W == dup W.rightmost first_two over
E.0 == E.clear_stuff [W] dip E.delete swap
E == [[[pop third not] pop fourth] [[pop fourth not] pop third] [[E.0] cons infra]] cond
T> == [dipd] cons infra
T< == [dipdd] cons infra
R0 == over first swap dup
R1 == cons roll> [T>] [E] [T<] cmp
BTree-Delete == [pop not] swap [R0] [R1] genrec''', D)
```
```python
J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'c' ['Er'] BTree-Delete ")
```
['a' 23 [] ['b' 88 [] []]]
```python
J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'b' ['Er'] BTree-Delete ")
```
['a' 23 [] ['c' 44 [] []]]
```python
J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'a' ['Er'] BTree-Delete ")
```
['b' 88 [] ['c' 44 [] []]]
```python
J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'der' ['Er'] BTree-Delete ")
```
['a' 23 [] ['b' 88 [] ['c' 44 [] 'Er' 'der' []]]]
```python
J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'der' [pop] BTree-Delete ")
```
['a' 23 [] ['b' 88 [] ['c' 44 [] []]]]
One bug, I forgot to put `not` in the first two clauses of the `cond`.
The behavior of the `[Er]` function should maybe be different: either just silently fail, or maybe implement some sort of function that can grab the pending expression up to a sentinel value or something, allowing for a kind of "except"-ish control-flow?
Then, once we have add, get, and delete we can see about abstracting them.
# Tree with node and list of trees. # Tree with node and list of trees.
Let's consider a tree structure, similar to one described ["Why functional programming matters" by John Hughes](https://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf), that consists of a node value and a sequence of zero or more child trees. (The asterisk is meant to indicate the [Kleene star](https://en.wikipedia.org/wiki/Kleene_star).) Let's consider a tree structure, similar to one described ["Why functional programming matters" by John Hughes](https://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf), that consists of a node value and a sequence of zero or more child trees. (The asterisk is meant to indicate the [Kleene star](https://en.wikipedia.org/wiki/Kleene_star).)

View File

@ -149,7 +149,7 @@ Ergo:
.. code:: ipython2 .. code:: ipython2
from notebook_preamble import J, V, define from notebook_preamble import D, J, V, define, DefinitionWrapper
.. code:: ipython2 .. code:: ipython2
@ -774,6 +774,22 @@ to understand:
@FunctionWrapper @FunctionWrapper
def cmp_(stack, expression, dictionary): def cmp_(stack, expression, dictionary):
'''
cmp takes two values and three quoted programs on the stack and runs
one of the three depending on the results of comparing the two values:
a b [G] [E] [L] cmp
------------------------- a > b
G
a b [G] [E] [L] cmp
------------------------- a = b
E
a b [G] [E] [L] cmp
------------------------- a < b
L
'''
L, (E, (G, (b, (a, stack)))) = stack L, (E, (G, (b, (a, stack)))) = stack
expression = pushback(G if a > b else L if a < b else E, expression) expression = pushback(G if a > b else L if a < b else E, expression)
return stack, expression, dictionary return stack, expression, dictionary
@ -781,6 +797,50 @@ to understand:
D['cmp'] = cmp_ D['cmp'] = cmp_
.. code:: ipython2
from joy.library import FunctionWrapper, S_ifte
@FunctionWrapper
def cond(stack, expression, dictionary):
'''
like a case statement; works by rewriting into a chain of ifte.
[..[[Bi] Ti]..[D]] -> ...
[[[B0] T0] [[B1] T1] [D]] cond
-----------------------------------------
[B0] [T0] [[B1] [T1] [D] ifte] ifte
'''
conditions, stack = stack
if conditions:
expression = _cond(conditions, expression)
try:
# Attempt to preload the args to first ifte.
(P, (T, (E, expression))) = expression
except ValueError:
# If, for any reason, the argument to cond should happen to contain
# only the default clause then this optimization will fail.
pass
else:
stack = (E, (T, (P, stack)))
return stack, expression, dictionary
def _cond(conditions, expression):
(clause, rest) = conditions
if not rest: # clause is [D]
return clause
P, T = clause
return (P, (T, (_cond(rest, ()), (S_ifte, expression))))
D['cond'] = cond
.. code:: ipython2 .. code:: ipython2
J("1 0 ['G'] ['E'] ['L'] cmp") J("1 0 ['G'] ['E'] ['L'] cmp")
@ -1207,45 +1267,31 @@ So:
2 2
TODO: BTree-delete BTree-delete
================== ============
Then, once we have add, get, and delete we can see about abstracting Now let's write a function that can return a tree datastructure with a
them. key, value pair deleted:
:: ::
tree key [E] BTree-delete tree key BTree-delete
---------------------------- key in tree ---------------------------
tree tree
tree key [E] BTree-delete If the key is not in tree it just returns the tree unchanged.
---------------------------- key not in tree
tree key E
So: So:
:: ::
BTree-delete == [pop not] [] [R0] [R1] genrec BTree-Delete == [pop not] swap [R0] [R1] genrec
And:
:: ::
[n_key n_value left right] key R0 [BTree-get] R1 [Er] BTree-delete
[n_key n_value left right] key [dup first] dip [BTree-get] R1 -------------------------------------
[n_key n_value left right] n_key key [BTree-get] R1 [pop not] [Er] [R0] [R1] genrec
[n_key n_value left right] n_key key [BTree-get] roll> [T>] [E] [T<] cmp
[n_key n_value left right] [BTree-get] n_key key [T>] [E] [T<] cmp
BTree-delete == [pop not] swap [[dup first] dip] [roll> [T>] [E] [T<] cmp] genrec
::
[n_key n_value left right] [BTree-get] T>
[n_key n_value left right] [BTree-get] E
[n_key n_value left right] [BTree-get] T<
:: ::
@ -1253,6 +1299,375 @@ And:
[n_key n_value left right] [BTree-get] E [n_key n_value left right] [BTree-get] E
[n_key n_value left right] [BTree-get] T< [n_key n_value left right] [BTree-get] T<
Now we get to figure out the recursive case:
::
w/ D == [pop not] [Er] [R0] [R1] genrec
[node_key node_value left right] key R0 [D] R1
[node_key node_value left right] key over first swap dup [D] R1
[node_key node_value left right] node_key key key [D] R1
And then:
::
[node_key node_value left right] node_key key key [D] R1
[node_key node_value left right] node_key key key [D] cons roll> [T>] [E] [T<] cmp
[node_key node_value left right] node_key key [key D] roll> [T>] [E] [T<] cmp
[node_key node_value left right] [key D] node_key key [T>] [E] [T<] cmp
Now this:;
::
[node_key node_value left right] [key D] node_key key [T>] [E] [T<] cmp
Becomes one of these three:;
::
[node_key node_value left right] [key D] T>
[node_key node_value left right] [key D] E
[node_key node_value left right] [key D] T<
Greater than case and less than case
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
[node_key node_value left right] [key D] T>
-------------------------------------------------
[node_key node_value left key D right]
First:
::
right left node_value node_key [key D] dipd
right left key D node_value node_key
right left' node_value node_key
Ergo:
::
[node_key node_value left right] [key D] [dipd] cons infra
So:
::
T> == [dipd] cons infra
T< == [dipdd] cons infra
The else case
~~~~~~~~~~~~~
::
[node_key node_value left right] [key D] E
We have to handle three cases, so let's use ``cond``.
The first two cases are symmetrical, if we only have one non-empty child
node return it.
::
E == [
[[pop third not] pop fourth]
[[pop fourth not] pop third]
[default]
] cond
(If both child nodes are empty return an empty node.)
The initial structure of the default function:
::
default == [E'] cons infra
[node_key node_value left right] [key D] default
[node_key node_value left right] [key D] [E'] cons infra
[node_key node_value left right] [[key D] E'] infra
right left node_value node_key [key D] E'
If both child nodes are non-empty, we find the highest node in our lower
sub-tree, take its key and value to replace (delete) our own, then get
rid of it by recursively calling delete() on our lower sub-node with our
new key.
(We could also find the lowest node in our higher sub-tree and take its
key and value and delete it. I only implemented one of these two
symmetrical options. Over a lot of deletions this might make the tree
more unbalanced. Oh well.)
First things first, we no longer need this node's key and value:
::
right left node_value node_key [key D] roll> popop E''
right left [key D] node_value node_key popop E''
right left [key D] E''
Then we have to we find the highest (right-most) node in our lower
(left) sub-tree:
::
right left [key D] E''
Ditch the key:
::
right left [key D] rest E'''
right left [D] E'''
Find the right-most node:
::
right left [D] [dup W] dip E''''
right left dup W [D] E''''
right left left W [D] E''''
Consider:
::
left W
We know left is not empty:
::
[L_key L_value L_left L_right] W
We want to keep extracting the right node as long as it is not empty:
::
left [P] [B] while W'
The predicate:
::
[L_key L_value L_left L_right] P
[L_key L_value L_left L_right] fourth
L_right
(This has a bug, can run on ``[]`` so must be guarded:
::
if_not_empty == [] swap [] ifte
?fourth == [fourth] if_not_empty
W.rightmost == [?fourth] [fourth] while
The body is also ``fourth``:
::
left [fourth] [fourth] while W'
rightest W'
We know rightest is not empty:
::
[R_key R_value R_left R_right] W'
[R_key R_value R_left R_right] uncons uncons pop
R_key [R_value R_left R_right] uncons pop
R_key R_value [R_left R_right] pop
R_key R_value
So:
::
W == [fourth] [fourth] while uncons uncons pop
And:
::
right left left W [D] E''''
right left R_key R_value [D] E''''
Final stretch. We want to end up with something like:
::
right left [R_key D] i R_value R_key
right left R_key D R_value R_key
right left' R_value R_key
If we adjust our definition of ``W`` to include ``over`` at the end:
::
W == [fourth] [fourth] while uncons uncons pop over
That will give us:
::
right left R_key R_value R_key [D] E''''
right left R_key R_value R_key [D] cons dipdd E'''''
right left R_key R_value [R_key D] dipdd E'''''
right left R_key D R_key R_value E'''''
right left' R_key R_value E'''''
right left' R_key R_value swap
right left' R_value R_key
So:
::
E' == roll> popop E''
E'' == rest E'''
E''' == [dup W] dip E''''
E'''' == cons dipdd swap
Substituting:
::
W == [fourth] [fourth] while uncons uncons pop over
E' == roll> popop rest [dup W] dip cons dipdd swap
E == [
[[pop third not] pop fourth]
[[pop fourth not] pop third]
[[E'] cons infra]
] cond
Minor rearrangement:
::
W == dup [fourth] [fourth] while uncons uncons pop over
E' == roll> popop rest [W] dip cons dipdd swap
E == [
[[pop third not] pop fourth]
[[pop fourth not] pop third]
[[E'] cons infra]
] cond
Refactoring
~~~~~~~~~~~
::
W.rightmost == [fourth] [fourth] while
W.unpack == uncons uncons pop
E.clear_stuff == roll> popop rest
E.delete == cons dipdd
W == dup W.rightmost W.unpack over
E.0 == E.clear_stuff [W] dip E.delete swap
E == [
[[pop third not] pop fourth]
[[pop fourth not] pop third]
[[E.0] cons infra]
] cond
T> == [dipd] cons infra
T< == [dipdd] cons infra
R0 == over first swap dup
R1 == cons roll> [T>] [E] [T<] cmp
BTree-Delete == [pop not] swap [R0] [R1] genrec
By the standards of the code I've written so far, this is a *huge* Joy
program.
.. code:: ipython2
DefinitionWrapper.add_definitions('''
first_two == uncons uncons pop
fourth == rest rest rest first
?fourth == [] [fourth] [] ifte
W.rightmost == [?fourth] [fourth] while
E.clear_stuff == roll> popop rest
E.delete == cons dipdd
W == dup W.rightmost first_two over
E.0 == E.clear_stuff [W] dip E.delete swap
E == [[[pop third not] pop fourth] [[pop fourth not] pop third] [[E.0] cons infra]] cond
T> == [dipd] cons infra
T< == [dipdd] cons infra
R0 == over first swap dup
R1 == cons roll> [T>] [E] [T<] cmp
BTree-Delete == [pop not] swap [R0] [R1] genrec''', D)
.. code:: ipython2
J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'c' ['Er'] BTree-Delete ")
.. parsed-literal::
['a' 23 [] ['b' 88 [] []]]
.. code:: ipython2
J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'b' ['Er'] BTree-Delete ")
.. parsed-literal::
['a' 23 [] ['c' 44 [] []]]
.. code:: ipython2
J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'a' ['Er'] BTree-Delete ")
.. parsed-literal::
['b' 88 [] ['c' 44 [] []]]
.. code:: ipython2
J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'der' ['Er'] BTree-Delete ")
.. parsed-literal::
['a' 23 [] ['b' 88 [] ['c' 44 [] 'Er' 'der' []]]]
.. code:: ipython2
J("['a' 23 [] ['b' 88 [] ['c' 44 [] []]]] 'der' [pop] BTree-Delete ")
.. parsed-literal::
['a' 23 [] ['b' 88 [] ['c' 44 [] []]]]
One bug, I forgot to put ``not`` in the first two clauses of the
``cond``.
The behavior of the ``[Er]`` function should maybe be different: either
just silently fail, or maybe implement some sort of function that can
grab the pending expression up to a sentinel value or something,
allowing for a kind of "except"-ish control-flow?
Then, once we have add, get, and delete we can see about abstracting
them.
Tree with node and list of trees. Tree with node and list of trees.
================================= =================================

13048
docs/Treestep.html Normal file

File diff suppressed because it is too large Load Diff

499
docs/Treestep.md Normal file
View File

@ -0,0 +1,499 @@
# Treating Trees II
Let's consider a tree structure, similar to one described ["Why functional programming matters" by John Hughes](https://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf), that consists of a node value followed by a sequence of zero or more child trees. (The asterisk is meant to indicate the [Kleene star](https://en.wikipedia.org/wiki/Kleene_star).)
tree = [] | [node tree*]
## `treestep`
In the spirit of `step` we are going to define a combinator `treestep` which expects a tree and three additional items: a base-case function `[B]`, and two quoted programs `[N]` and `[C]`.
tree [B] [N] [C] treestep
If the current tree node is empty then just execute `B`:
[] [B] [N] [C] treestep
---------------------------
[] B
Otherwise, evaluate `N` on the node value, `map` the whole function (abbreviated here as `K`) over the child trees recursively, and then combine the result with `C`.
[node tree*] [B] [N] [C] treestep
--------------------------------------- w/ K == [B] [N] [C] treestep
node N [tree*] [K] map C
(Later on we'll experiment with making `map` part of `C` so you can use other combinators.)
## Derive the recursive function.
We can begin to derive it by finding the `ifte` stage that `genrec` will produce.
K == [not] [B] [R0] [R1] genrec
== [not] [B] [R0 [K] R1] ifte
So we just have to derive `J`:
J == R0 [K] R1
The behavior of `J` is to accept a (non-empty) tree node and arrive at the desired outcome.
[node tree*] J
------------------------------
node N [tree*] [K] map C
So `J` will have some form like:
J == ... [N] ... [K] ... [C] ...
Let's dive in. First, unquote the node and `dip` `N`.
[node tree*] uncons [N] dip
node [tree*] [N] dip
node N [tree*]
Next, `map` `K` over the child trees and combine with `C`.
node N [tree*] [K] map C
node N [tree*] [K] map C
node N [K.tree*] C
So:
J == uncons [N] dip [K] map C
Plug it in and convert to `genrec`:
K == [not] [B] [J ] ifte
== [not] [B] [uncons [N] dip [K] map C] ifte
== [not] [B] [uncons [N] dip] [map C] genrec
## Extract the givens to parameterize the program.
Working backwards:
[not] [B] [uncons [N] dip] [map C] genrec
[B] [not] swap [uncons [N] dip] [map C] genrec
[B] [uncons [N] dip] [[not] swap] dip [map C] genrec
^^^^^^^^^^^^^^^^
[B] [[N] dip] [uncons] swoncat [[not] swap] dip [map C] genrec
[B] [N] [dip] cons [uncons] swoncat [[not] swap] dip [map C] genrec
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Extract a couple of auxiliary definitions:
TS.0 == [[not] swap] dip
TS.1 == [dip] cons [uncons] swoncat
[B] [N] TS.1 TS.0 [map C] genrec
[B] [N] [map C] [TS.1 TS.0] dip genrec
[B] [N] [C] [map] swoncat [TS.1 TS.0] dip genrec
The givens are all to the left so we have our definition.
### (alternate) Extract the givens to parameterize the program.
Working backwards:
[not] [B] [uncons [N] dip] [map C] genrec
[not] [B] [N] [dip] cons [uncons] swoncat [map C] genrec
[B] [N] [not] roll> [dip] cons [uncons] swoncat [map C] genrec
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
## Define `treestep`
```python
from notebook_preamble import D, J, V, define, DefinitionWrapper
```
```python
DefinitionWrapper.add_definitions('''
_treestep_0 == [[not] swap] dip
_treestep_1 == [dip] cons [uncons] swoncat
treegrind == [_treestep_1 _treestep_0] dip genrec
treestep == [map] swoncat treegrind
''', D)
```
## Examples
Consider trees, the nodes of which are integers. We can find the sum of all nodes in a tree with this function:
sumtree == [pop 0] [] [sum +] treestep
```python
define('sumtree == [pop 0] [] [sum +] treestep')
```
Running this function on an empty tree value gives zero:
[] [pop 0] [] [sum +] treestep
------------------------------------
0
```python
J('[] sumtree') # Empty tree.
```
0
Running it on a non-empty node:
[n tree*] [pop 0] [] [sum +] treestep
n [tree*] [[pop 0] [] [sum +] treestep] map sum +
n [ ... ] sum +
n m +
n+m
```python
J('[23] sumtree') # No child trees.
```
23
```python
J('[23 []] sumtree') # Child tree, empty.
```
23
```python
J('[23 [2 [4]] [3]] sumtree') # Non-empty child trees.
```
32
```python
J('[23 [2 [8] [9]] [3] [4 []]] sumtree') # Etc...
```
49
```python
J('[23 [2 [8] [9]] [3] [4 []]] [pop 0] [] [cons sum] treestep') # Alternate "spelling".
```
49
```python
J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 23] [cons] treestep') # Replace each node.
```
[23 [23 [23] [23]] [23] [23 []]]
```python
J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 1] [cons] treestep')
```
[1 [1 [1] [1]] [1] [1 []]]
```python
J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 1] [cons] treestep sumtree')
```
6
```python
J('[23 [2 [8] [9]] [3] [4 []]] [pop 0] [pop 1] [sum +] treestep') # Combine replace and sum into one function.
```
6
```python
J('[4 [3 [] [7]]] [pop 0] [pop 1] [sum +] treestep') # Combine replace and sum into one function.
```
3
## Redefining the Ordered Binary Tree in terms of `treestep`.
Tree = [] | [[key value] left right]
What kind of functions can we write for this with our `treestep`?
The pattern for processing a non-empty node is:
node N [tree*] [K] map C
Plugging in our BTree structure:
[key value] N [left right] [K] map C
### Traversal
[key value] first [left right] [K] map i
key [value] [left right] [K] map i
key [left right] [K] map i
key [lkey rkey ] i
key lkey rkey
This doesn't quite work:
```python
J('[[3 0] [[2 0] [][]] [[9 0] [[5 0] [[4 0] [][]] [[8 0] [[6 0] [] [[7 0] [][]]][]]][]]] ["B"] [first] [i] treestep')
```
3 'B' 'B'
Doesn't work because `map` extracts the `first` item of whatever its mapped function produces. We have to return a list, rather than depositing our results directly on the stack.
[key value] N [left right] [K] map C
[key value] first [left right] [K] map flatten cons
key [left right] [K] map flatten cons
key [[lk] [rk] ] flatten cons
key [ lk rk ] cons
[key lk rk ]
So:
[] [first] [flatten cons] treestep
```python
J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [] [first] [flatten cons] treestep')
```
[3 2 9 5 4 8 6 7]
There we go.
### In-order traversal
From here:
key [[lk] [rk]] C
key [[lk] [rk]] i
key [lk] [rk] roll<
[lk] [rk] key swons concat
[lk] [key rk] concat
[lk key rk]
So:
[] [i roll< swons concat] [first] treestep
```python
J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [] [uncons pop] [i roll< swons concat] treestep')
```
[2 3 4 5 6 7 8 9]
## With `treegrind`?
The `treegrind` function doesn't include the `map` combinator, so the `[C]` function must arrange to use some combinator on the quoted recursive copy `[K]`. With this function, the pattern for processing a non-empty node is:
node N [tree*] [K] C
Plugging in our BTree structure:
[key value] N [left right] [K] C
```python
J('[["key" "value"] ["left"] ["right"] ] ["B"] ["N"] ["C"] treegrind')
```
['key' 'value'] 'N' [['left'] ['right']] [[not] ['B'] [uncons ['N'] dip] ['C'] genrec] 'C'
## `treegrind` with `step`
Iteration through the nodes
```python
J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [pop] ["N"] [step] treegrind')
```
[3 0] 'N' [2 0] 'N' [9 0] 'N' [5 0] 'N' [4 0] 'N' [8 0] 'N' [6 0] 'N' [7 0] 'N'
Sum the nodes' keys.
```python
J('0 [[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [pop] [first +] [step] treegrind')
```
44
Rebuild the tree using `map` (imitating `treestep`.)
```python
J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [] [[100 +] infra] [map cons] treegrind')
```
[[103 0] [[102 0] [] []] [[109 0] [[105 0] [[104 0] [] []] [[108 0] [[106 0] [] [[107 0] [] []]] []]] []]]
## Do we have the flexibility to reimplement `Tree-get`?
I think we do:
[B] [N] [C] treegrind
We'll start by saying that the base-case (the key is not in the tree) is user defined, and the per-node function is just the query key literal:
[B] [query_key] [C] treegrind
This means we just have to define `C` from:
[key value] query_key [left right] [K] C
Let's try `cmp`:
C == P [T>] [E] [T<] cmp
[key value] query_key [left right] [K] P [T>] [E] [T<] cmp
### The predicate `P`
Seems pretty easy (we must preserve the value in case the keys are equal):
[key value] query_key [left right] [K] P
[key value] query_key [left right] [K] roll<
[key value] [left right] [K] query_key [roll< uncons swap] dip
[key value] [left right] [K] roll< uncons swap query_key
[left right] [K] [key value] uncons swap query_key
[left right] [K] key [value] swap query_key
[left right] [K] [value] key query_key
P == roll< [roll< uncons swap] dip
(Possibly with a swap at the end? Or just swap `T<` and `T>`.)
So now:
[left right] [K] [value] key query_key [T>] [E] [T<] cmp
Becomes one of these three:
[left right] [K] [value] T>
[left right] [K] [value] E
[left right] [K] [value] T<
### `E`
Easy.
E == roll> popop first
### `T<` and `T>`
T< == pop [first] dip i
T> == pop [second] dip i
## Putting it together
T> == pop [first] dip i
T< == pop [second] dip i
E == roll> popop first
P == roll< [roll< uncons swap] dip
Tree-get == [P [T>] [E] [T<] cmp] treegrind
To me, that seems simpler than the `genrec` version.
```python
DefinitionWrapper.add_definitions('''
T> == pop [first] dip i
T< == pop [second] dip i
E == roll> popop first
P == roll< [roll< uncons swap] dip
Tree-get == [P [T>] [E] [T<] cmp] treegrind
''', D)
```
```python
from joy.library import FunctionWrapper
from joy.utils.stack import pushback
@FunctionWrapper
def cmp_(stack, expression, dictionary):
'''
cmp takes two values and three quoted programs on the stack and runs
one of the three depending on the results of comparing the two values:
a b [G] [E] [L] cmp
------------------------- a > b
G
a b [G] [E] [L] cmp
------------------------- a = b
E
a b [G] [E] [L] cmp
------------------------- a < b
L
'''
L, (E, (G, (b, (a, stack)))) = stack
expression = pushback(G if a > b else L if a < b else E, expression)
return stack, expression, dictionary
D['cmp'] = cmp_
```
```python
J('''\
[[3 13] [[2 12] [] []] [[9 19] [[5 15] [[4 14] [] []] [[8 18] [[6 16] [] [[7 17] [] []]] []]] []]]
[] [5] Tree-get
''')
```
15
```python
J('''\
[[3 13] [[2 12] [] []] [[9 19] [[5 15] [[4 14] [] []] [[8 18] [[6 16] [] [[7 17] [] []]] []]] []]]
[pop "nope"] [25] Tree-get
''')
```
'nope'

655
docs/Treestep.rst Normal file
View File

@ -0,0 +1,655 @@
Treating Trees II
=================
Let's consider a tree structure, similar to one described `"Why
functional programming matters" by John
Hughes <https://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf>`__,
that consists of a node value followed by a sequence of zero or more
child trees. (The asterisk is meant to indicate the `Kleene
star <https://en.wikipedia.org/wiki/Kleene_star>`__.)
::
tree = [] | [node tree*]
``treestep``
------------
In the spirit of ``step`` we are going to define a combinator
``treestep`` which expects a tree and three additional items: a
base-case function ``[B]``, and two quoted programs ``[N]`` and ``[C]``.
::
tree [B] [N] [C] treestep
If the current tree node is empty then just execute ``B``:
::
[] [B] [N] [C] treestep
---------------------------
[] B
Otherwise, evaluate ``N`` on the node value, ``map`` the whole function
(abbreviated here as ``K``) over the child trees recursively, and then
combine the result with ``C``.
::
[node tree*] [B] [N] [C] treestep
--------------------------------------- w/ K == [B] [N] [C] treestep
node N [tree*] [K] map C
(Later on we'll experiment with making ``map`` part of ``C`` so you can
use other combinators.)
Derive the recursive function.
------------------------------
We can begin to derive it by finding the ``ifte`` stage that ``genrec``
will produce.
::
K == [not] [B] [R0] [R1] genrec
== [not] [B] [R0 [K] R1] ifte
So we just have to derive ``J``:
::
J == R0 [K] R1
The behavior of ``J`` is to accept a (non-empty) tree node and arrive at
the desired outcome.
::
[node tree*] J
------------------------------
node N [tree*] [K] map C
So ``J`` will have some form like:
::
J == ... [N] ... [K] ... [C] ...
Let's dive in. First, unquote the node and ``dip`` ``N``.
::
[node tree*] uncons [N] dip
node [tree*] [N] dip
node N [tree*]
Next, ``map`` ``K`` over the child trees and combine with ``C``.
::
node N [tree*] [K] map C
node N [tree*] [K] map C
node N [K.tree*] C
So:
::
J == uncons [N] dip [K] map C
Plug it in and convert to ``genrec``:
::
K == [not] [B] [J ] ifte
== [not] [B] [uncons [N] dip [K] map C] ifte
== [not] [B] [uncons [N] dip] [map C] genrec
Extract the givens to parameterize the program.
-----------------------------------------------
Working backwards:
::
[not] [B] [uncons [N] dip] [map C] genrec
[B] [not] swap [uncons [N] dip] [map C] genrec
[B] [uncons [N] dip] [[not] swap] dip [map C] genrec
^^^^^^^^^^^^^^^^
[B] [[N] dip] [uncons] swoncat [[not] swap] dip [map C] genrec
[B] [N] [dip] cons [uncons] swoncat [[not] swap] dip [map C] genrec
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Extract a couple of auxiliary definitions:
::
TS.0 == [[not] swap] dip
TS.1 == [dip] cons [uncons] swoncat
::
[B] [N] TS.1 TS.0 [map C] genrec
[B] [N] [map C] [TS.1 TS.0] dip genrec
[B] [N] [C] [map] swoncat [TS.1 TS.0] dip genrec
The givens are all to the left so we have our definition.
(alternate) Extract the givens to parameterize the program.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Working backwards:
::
[not] [B] [uncons [N] dip] [map C] genrec
[not] [B] [N] [dip] cons [uncons] swoncat [map C] genrec
[B] [N] [not] roll> [dip] cons [uncons] swoncat [map C] genrec
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Define ``treestep``
-------------------
.. code:: ipython2
from notebook_preamble import D, J, V, define, DefinitionWrapper
.. code:: ipython2
DefinitionWrapper.add_definitions('''
_treestep_0 == [[not] swap] dip
_treestep_1 == [dip] cons [uncons] swoncat
treegrind == [_treestep_1 _treestep_0] dip genrec
treestep == [map] swoncat treegrind
''', D)
Examples
--------
Consider trees, the nodes of which are integers. We can find the sum of
all nodes in a tree with this function:
::
sumtree == [pop 0] [] [sum +] treestep
.. code:: ipython2
define('sumtree == [pop 0] [] [sum +] treestep')
Running this function on an empty tree value gives zero:
::
[] [pop 0] [] [sum +] treestep
------------------------------------
0
.. code:: ipython2
J('[] sumtree') # Empty tree.
.. parsed-literal::
0
Running it on a non-empty node:
::
[n tree*] [pop 0] [] [sum +] treestep
n [tree*] [[pop 0] [] [sum +] treestep] map sum +
n [ ... ] sum +
n m +
n+m
.. code:: ipython2
J('[23] sumtree') # No child trees.
.. parsed-literal::
23
.. code:: ipython2
J('[23 []] sumtree') # Child tree, empty.
.. parsed-literal::
23
.. code:: ipython2
J('[23 [2 [4]] [3]] sumtree') # Non-empty child trees.
.. parsed-literal::
32
.. code:: ipython2
J('[23 [2 [8] [9]] [3] [4 []]] sumtree') # Etc...
.. parsed-literal::
49
.. code:: ipython2
J('[23 [2 [8] [9]] [3] [4 []]] [pop 0] [] [cons sum] treestep') # Alternate "spelling".
.. parsed-literal::
49
.. code:: ipython2
J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 23] [cons] treestep') # Replace each node.
.. parsed-literal::
[23 [23 [23] [23]] [23] [23 []]]
.. code:: ipython2
J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 1] [cons] treestep')
.. parsed-literal::
[1 [1 [1] [1]] [1] [1 []]]
.. code:: ipython2
J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 1] [cons] treestep sumtree')
.. parsed-literal::
6
.. code:: ipython2
J('[23 [2 [8] [9]] [3] [4 []]] [pop 0] [pop 1] [sum +] treestep') # Combine replace and sum into one function.
.. parsed-literal::
6
.. code:: ipython2
J('[4 [3 [] [7]]] [pop 0] [pop 1] [sum +] treestep') # Combine replace and sum into one function.
.. parsed-literal::
3
Redefining the Ordered Binary Tree in terms of ``treestep``.
------------------------------------------------------------
::
Tree = [] | [[key value] left right]
What kind of functions can we write for this with our ``treestep``?
The pattern for processing a non-empty node is:
::
node N [tree*] [K] map C
Plugging in our BTree structure:
::
[key value] N [left right] [K] map C
Traversal
~~~~~~~~~
::
[key value] first [left right] [K] map i
key [value] [left right] [K] map i
key [left right] [K] map i
key [lkey rkey ] i
key lkey rkey
This doesn't quite work:
.. code:: ipython2
J('[[3 0] [[2 0] [][]] [[9 0] [[5 0] [[4 0] [][]] [[8 0] [[6 0] [] [[7 0] [][]]][]]][]]] ["B"] [first] [i] treestep')
.. parsed-literal::
3 'B' 'B'
Doesn't work because ``map`` extracts the ``first`` item of whatever its
mapped function produces. We have to return a list, rather than
depositing our results directly on the stack.
::
[key value] N [left right] [K] map C
[key value] first [left right] [K] map flatten cons
key [left right] [K] map flatten cons
key [[lk] [rk] ] flatten cons
key [ lk rk ] cons
[key lk rk ]
So:
::
[] [first] [flatten cons] treestep
.. code:: ipython2
J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [] [first] [flatten cons] treestep')
.. parsed-literal::
[3 2 9 5 4 8 6 7]
There we go.
In-order traversal
~~~~~~~~~~~~~~~~~~
From here:
::
key [[lk] [rk]] C
key [[lk] [rk]] i
key [lk] [rk] roll<
[lk] [rk] key swons concat
[lk] [key rk] concat
[lk key rk]
So:
::
[] [i roll< swons concat] [first] treestep
.. code:: ipython2
J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [] [uncons pop] [i roll< swons concat] treestep')
.. parsed-literal::
[2 3 4 5 6 7 8 9]
With ``treegrind``?
-------------------
The ``treegrind`` function doesn't include the ``map`` combinator, so
the ``[C]`` function must arrange to use some combinator on the quoted
recursive copy ``[K]``. With this function, the pattern for processing a
non-empty node is:
::
node N [tree*] [K] C
Plugging in our BTree structure:
::
[key value] N [left right] [K] C
.. code:: ipython2
J('[["key" "value"] ["left"] ["right"] ] ["B"] ["N"] ["C"] treegrind')
.. parsed-literal::
['key' 'value'] 'N' [['left'] ['right']] [[not] ['B'] [uncons ['N'] dip] ['C'] genrec] 'C'
``treegrind`` with ``step``
---------------------------
Iteration through the nodes
.. code:: ipython2
J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [pop] ["N"] [step] treegrind')
.. parsed-literal::
[3 0] 'N' [2 0] 'N' [9 0] 'N' [5 0] 'N' [4 0] 'N' [8 0] 'N' [6 0] 'N' [7 0] 'N'
Sum the nodes' keys.
.. code:: ipython2
J('0 [[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [pop] [first +] [step] treegrind')
.. parsed-literal::
44
Rebuild the tree using ``map`` (imitating ``treestep``.)
.. code:: ipython2
J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [] [[100 +] infra] [map cons] treegrind')
.. parsed-literal::
[[103 0] [[102 0] [] []] [[109 0] [[105 0] [[104 0] [] []] [[108 0] [[106 0] [] [[107 0] [] []]] []]] []]]
Do we have the flexibility to reimplement ``Tree-get``?
-------------------------------------------------------
I think we do:
::
[B] [N] [C] treegrind
We'll start by saying that the base-case (the key is not in the tree) is
user defined, and the per-node function is just the query key literal:
::
[B] [query_key] [C] treegrind
This means we just have to define ``C`` from:
::
[key value] query_key [left right] [K] C
Let's try ``cmp``:
::
C == P [T>] [E] [T<] cmp
[key value] query_key [left right] [K] P [T>] [E] [T<] cmp
The predicate ``P``
~~~~~~~~~~~~~~~~~~~
Seems pretty easy (we must preserve the value in case the keys are
equal):
::
[key value] query_key [left right] [K] P
[key value] query_key [left right] [K] roll<
[key value] [left right] [K] query_key [roll< uncons swap] dip
[key value] [left right] [K] roll< uncons swap query_key
[left right] [K] [key value] uncons swap query_key
[left right] [K] key [value] swap query_key
[left right] [K] [value] key query_key
P == roll< [roll< uncons swap] dip
(Possibly with a swap at the end? Or just swap ``T<`` and ``T>``.)
So now:
::
[left right] [K] [value] key query_key [T>] [E] [T<] cmp
Becomes one of these three:
::
[left right] [K] [value] T>
[left right] [K] [value] E
[left right] [K] [value] T<
``E``
~~~~~
Easy.
::
E == roll> popop first
``T<`` and ``T>``
~~~~~~~~~~~~~~~~~
::
T< == pop [first] dip i
T> == pop [second] dip i
Putting it together
-------------------
::
T> == pop [first] dip i
T< == pop [second] dip i
E == roll> popop first
P == roll< [roll< uncons swap] dip
Tree-get == [P [T>] [E] [T<] cmp] treegrind
To me, that seems simpler than the ``genrec`` version.
.. code:: ipython2
DefinitionWrapper.add_definitions('''
T> == pop [first] dip i
T< == pop [second] dip i
E == roll> popop first
P == roll< [roll< uncons swap] dip
Tree-get == [P [T>] [E] [T<] cmp] treegrind
''', D)
.. code:: ipython2
from joy.library import FunctionWrapper
from joy.utils.stack import pushback
@FunctionWrapper
def cmp_(stack, expression, dictionary):
'''
cmp takes two values and three quoted programs on the stack and runs
one of the three depending on the results of comparing the two values:
a b [G] [E] [L] cmp
------------------------- a > b
G
a b [G] [E] [L] cmp
------------------------- a = b
E
a b [G] [E] [L] cmp
------------------------- a < b
L
'''
L, (E, (G, (b, (a, stack)))) = stack
expression = pushback(G if a > b else L if a < b else E, expression)
return stack, expression, dictionary
D['cmp'] = cmp_
.. code:: ipython2
J('''\
[[3 13] [[2 12] [] []] [[9 19] [[5 15] [[4 14] [] []] [[8 18] [[6 16] [] [[7 17] [] []]] []]] []]]
[] [5] Tree-get
''')
.. parsed-literal::
15
.. code:: ipython2
J('''\
[[3 13] [[2 12] [] []] [[9 19] [[5 15] [[4 14] [] []] [[8 18] [[6 16] [] [[7 17] [] []]] []]] []]]
[pop "nope"] [25] Tree-get
''')
.. parsed-literal::
'nope'

BIN
docs/notebook_preamble.pyc Normal file

Binary file not shown.