Rebuild docs

This commit is contained in:
Simon Forman
2020-05-17 16:40:58 -07:00
parent ef6411205d
commit 56da4690d0
84 changed files with 7456 additions and 7972 deletions
+113 -113
View File
@@ -11,35 +11,35 @@ For example, given the following spreadsheet:
::
5 1 9 5
7 5 3
2 4 6 8
5 1 9 5
7 5 3
2 4 6 8
- The first row's largest and smallest values are 9 and 1, and their
- The first rows largest and smallest values are 9 and 1, and their
difference is 8.
- The second row's largest and smallest values are 7 and 3, and their
- The second rows largest and smallest values are 7 and 3, and their
difference is 4.
- The third row's difference is 6.
- The third rows difference is 6.
In this example, the spreadsheet's checksum would be 8 + 4 + 6 = 18.
In this example, the spreadsheets checksum would be 8 + 4 + 6 = 18.
.. code:: ipython2
from notebook_preamble import J, V, define
I'll assume the input is a Joy sequence of sequences of integers.
Ill assume the input is a Joy sequence of sequences of integers.
::
[[5 1 9 5]
[7 5 3]
[2 4 6 8]]
[[5 1 9 5]
[7 5 3]
[2 4 6 8]]
So, obviously, the initial form will be a ``step`` function:
::
AoC2017.2 == 0 swap [F +] step
AoC2017.2 == 0 swap [F +] step
This function ``F`` must get the ``max`` and ``min`` of a row of numbers
and subtract. We can define a helper function ``maxmin`` which does
@@ -63,7 +63,7 @@ Then ``F`` just does that then subtracts the min from the max:
::
F == maxmin -
F == maxmin -
So:
@@ -87,18 +87,18 @@ So:
18
...find the only two numbers in each row where one evenly divides the
find the only two numbers in each row where one evenly divides the
other - that is, where the result of the division operation is a whole
number. They would like you to find those numbers on each line, divide
them, and add up each line's result.
them, and add up each lines result.
For example, given the following spreadsheet:
::
5 9 2 8
9 4 7 3
3 8 6 5
5 9 2 8
9 4 7 3
3 8 6 5
- In the first row, the only two numbers that evenly divide are 8 and
2; the result of this division is 4.
@@ -107,7 +107,7 @@ For example, given the following spreadsheet:
In this example, the sum of the results would be 4 + 3 + 2 = 9.
What is the sum of each row's result in your puzzle input?
What is the sum of each rows result in your puzzle input?
.. code:: ipython2
@@ -131,8 +131,8 @@ What is the sum of each row's result in your puzzle input?
::
[9 8 5 2] uncons [swap [divmod] cons F] dupdip G
[8 5 2] [9 divmod] F [8 5 2] G
[9 8 5 2] uncons [swap [divmod] cons F] dupdip G
[8 5 2] [9 divmod] F [8 5 2] G
.. code:: ipython2
@@ -162,7 +162,7 @@ What is the sum of each row's result in your puzzle input?
Tricky
------
Let's think.
Lets think.
Given a *sorted* sequence (from highest to lowest) we want to \* for
head, tail in sequence \* for term in tail: \* check if the head % term
@@ -173,62 +173,62 @@ So we want a ``loop`` I think
::
[a b c d] True [Q] loop
[a b c d] Q [Q] loop
[a b c d] True [Q] loop
[a b c d] Q [Q] loop
``Q`` should either leave the result and False, or the ``rest`` and
True.
::
[a b c d] Q
-----------------
result 0
[a b c d] Q
-----------------
result 0
[a b c d] Q
-----------------
[b c d] 1
[a b c d] Q
-----------------
[b c d] 1
This suggests that ``Q`` should start with:
::
[a b c d] uncons dup roll<
[b c d] [b c d] a
[a b c d] uncons dup roll<
[b c d] [b c d] a
Now we just have to ``pop`` it if we don't need it.
Now we just have to ``pop`` it if we dont need it.
::
[b c d] [b c d] a [P] [T] [cons] app2 popdd [E] primrec
[b c d] [b c d] [a P] [a T] [E] primrec
[b c d] [b c d] a [P] [T] [cons] app2 popdd [E] primrec
[b c d] [b c d] [a P] [a T] [E] primrec
--------------
::
w/ Q == [% not] [T] [F] primrec
w/ Q == [% not] [T] [F] primrec
[a b c d] uncons
a [b c d] tuck
[b c d] a [b c d] uncons
[b c d] a b [c d] roll>
[b c d] [c d] a b Q
[b c d] [c d] a b [% not] [T] [F] primrec
[a b c d] uncons
a [b c d] tuck
[b c d] a [b c d] uncons
[b c d] a b [c d] roll>
[b c d] [c d] a b Q
[b c d] [c d] a b [% not] [T] [F] primrec
[b c d] [c d] a b T
[b c d] [c d] a b / roll> popop 0
[b c d] [c d] a b T
[b c d] [c d] a b / roll> popop 0
[b c d] [c d] a b F Q
[b c d] [c d] a b pop swap uncons ... Q
[b c d] [c d] a swap uncons ... Q
[b c d] a [c d] uncons ... Q
[b c d] a c [d] roll> Q
[b c d] [d] a c Q
[b c d] [c d] a b F Q
[b c d] [c d] a b pop swap uncons ... Q
[b c d] [c d] a swap uncons ... Q
[b c d] a [c d] uncons ... Q
[b c d] a c [d] roll> Q
[b c d] [d] a c Q
Q == [% not] [/ roll> popop 0] [pop swap uncons roll>] primrec
Q == [% not] [/ roll> popop 0] [pop swap uncons roll>] primrec
uncons tuck uncons roll> Q
uncons tuck uncons roll> Q
.. code:: ipython2
@@ -244,55 +244,55 @@ Now we just have to ``pop`` it if we don't need it.
::
[a b c d] uncons
a [b c d] tuck
[b c d] a [b c d] [not] [popop 1] [Q] ifte
[a b c d] uncons
a [b c d] tuck
[b c d] a [b c d] [not] [popop 1] [Q] ifte
[b c d] a [] popop 1
[b c d] 1
[b c d] a [] popop 1
[b c d] 1
[b c d] a [b c d] Q
[b c d] a [b c d] Q
a [...] Q
---------------
result 0
a [...] Q
---------------
result 0
a [...] Q
---------------
1
a [...] Q
---------------
1
w/ Q == [first % not] [first / 0] [rest [not] [popop 1]] [ifte]
w/ Q == [first % not] [first / 0] [rest [not] [popop 1]] [ifte]
a [b c d] [first % not] [first / 0] [rest [not] [popop 1]] [ifte]
a [b c d] first % not
a b % not
a%b not
bool(a%b)
a [b c d] [first % not] [first / 0] [rest [not] [popop 1]] [ifte]
a [b c d] first % not
a b % not
a%b not
bool(a%b)
a [b c d] [first % not] [first / 0] [rest [not] [popop 1]] [ifte]
a [b c d] first / 0
a b / 0
a/b 0
a [b c d] [first % not] [first / 0] [rest [not] [popop 1]] [ifte]
a [b c d] first / 0
a b / 0
a/b 0
a [b c d] [first % not] [first / 0] [rest [not] [popop 1]] [ifte]
a [b c d] rest [not] [popop 1] [Q] ifte
a [c d] [not] [popop 1] [Q] ifte
a [c d] [not] [popop 1] [Q] ifte
a [b c d] [first % not] [first / 0] [rest [not] [popop 1]] [ifte]
a [b c d] rest [not] [popop 1] [Q] ifte
a [c d] [not] [popop 1] [Q] ifte
a [c d] [not] [popop 1] [Q] ifte
a [c d] [not] [popop 1] [Q] ifte
a [c d] not
a [c d] [not] [popop 1] [Q] ifte
a [c d] not
a [] popop 1
1
a [] popop 1
1
a [c d] Q
a [c d] Q
uncons tuck [first % not] [first / 0] [rest [not] [popop 1]] [ifte]
uncons tuck [first % not] [first / 0] [rest [not] [popop 1]] [ifte]
I finally sat down with a piece of paper and blocked it out.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -302,36 +302,36 @@ candidates and return the result or zero:
::
n [...] G
---------------
result
n [...] G
---------------
result
n [...] G
---------------
0
n [...] G
---------------
0
It's a recursive function that conditionally executes the recursive part
Its a recursive function that conditionally executes the recursive part
of its recursive branch
::
[Pg] [E] [R1 [Pi] [T]] [ifte] genrec
[Pg] [E] [R1 [Pi] [T]] [ifte] genrec
The recursive branch is the else-part of the inner ``ifte``:
::
G == [Pg] [E] [R1 [Pi] [T]] [ifte] genrec
== [Pg] [E] [R1 [Pi] [T] [G] ifte] ifte
G == [Pg] [E] [R1 [Pi] [T]] [ifte] genrec
== [Pg] [E] [R1 [Pi] [T] [G] ifte] ifte
But this is in hindsight. Going forward I derived:
::
G == [first % not]
[first /]
[rest [not] [popop 0]]
[ifte] genrec
G == [first % not]
[first /]
[rest [not] [popop 0]]
[ifte] genrec
The predicate detects if the ``n`` can be evenly divided by the
``first`` item in the list. If so, the then-part returns the result.
@@ -339,8 +339,8 @@ Otherwise, we have:
::
n [m ...] rest [not] [popop 0] [G] ifte
n [...] [not] [popop 0] [G] ifte
n [m ...] rest [not] [popop 0] [G] ifte
n [...] [not] [popop 0] [G] ifte
This ``ifte`` guards against empty sequences and returns zero in that
case, otherwise it executes ``G``.
@@ -350,16 +350,16 @@ case, otherwise it executes ``G``.
define('G == [first % not] [first /] [rest [not] [popop 0]] [ifte] genrec')
Now we need a word that uses ``G`` on each (head, tail) pair of a
sequence until it finds a (non-zero) result. It's going to be designed
sequence until it finds a (non-zero) result. Its going to be designed
to work on a stack that has some candidate ``n``, a sequence of possible
divisors, and a result that is zero to signal to continue (a non-zero
value implies that it is the discovered result):
::
n [...] p find-result
---------------------------
result
n [...] p find-result
---------------------------
result
It applies ``G`` using ``nullary`` because if it fails with one
candidate it needs the list to get the next one (the list is otherwise
@@ -367,20 +367,20 @@ consumed by ``G``.)
::
find-result == [0 >] [roll> popop] [roll< popop uncons [G] nullary] primrec
find-result == [0 >] [roll> popop] [roll< popop uncons [G] nullary] primrec
n [...] p [0 >] [roll> popop] [roll< popop uncons [G] nullary] primrec
n [...] p [0 >] [roll> popop] [roll< popop uncons [G] nullary] primrec
The base-case is trivial, return the (non-zero) result. The recursive
branch...
branch
::
n [...] p roll< popop uncons [G] nullary find-result
[...] p n popop uncons [G] nullary find-result
[...] uncons [G] nullary find-result
m [..] [G] nullary find-result
m [..] p find-result
n [...] p roll< popop uncons [G] nullary find-result
[...] p n popop uncons [G] nullary find-result
[...] uncons [G] nullary find-result
m [..] [G] nullary find-result
m [..] p find-result
The puzzle states that the input is well-formed, meaning that we can
expect a result before the row sequence empties and so do not need to
@@ -402,7 +402,7 @@ guard the ``uncons``.
In order to get the thing started, we need to ``sort`` the list in
descending order, then prime the ``find-result`` function with a dummy
candidate value and zero ("continue") flag.
candidate value and zero (continue) flag.
.. code:: ipython2