306 lines
5.2 KiB
ReStructuredText
306 lines
5.2 KiB
ReStructuredText
|
|
Advent of Code 2017
|
|
===================
|
|
|
|
December 6th
|
|
------------
|
|
|
|
::
|
|
|
|
[0 2 7 0] dup max
|
|
|
|
.. code:: ipython2
|
|
|
|
from notebook_preamble import D, J, V, define
|
|
|
|
.. code:: ipython2
|
|
|
|
J('[0 2 7 0] dup max')
|
|
|
|
|
|
.. parsed-literal::
|
|
|
|
[0 2 7 0] 7
|
|
|
|
|
|
.. code:: ipython2
|
|
|
|
from joy.library import SimpleFunctionWrapper
|
|
from joy.utils.stack import list_to_stack
|
|
|
|
|
|
@SimpleFunctionWrapper
|
|
def index_of(stack):
|
|
'''Given a sequence and a item, return the index of the item, or -1 if not found.
|
|
|
|
E.g.:
|
|
|
|
[a b c] a index_of
|
|
------------------------
|
|
0
|
|
|
|
[a b c] d index_of
|
|
------------------------
|
|
-1
|
|
|
|
'''
|
|
item, (sequence, stack) = stack
|
|
i = 0
|
|
while sequence:
|
|
term, sequence = sequence
|
|
if term == item:
|
|
break
|
|
i += 1
|
|
else:
|
|
i = -1
|
|
return i, stack
|
|
|
|
|
|
D['index_of'] = index_of
|
|
|
|
.. code:: ipython2
|
|
|
|
J('[0 2 7 0] 7 index_of')
|
|
|
|
|
|
.. parsed-literal::
|
|
|
|
2
|
|
|
|
|
|
.. code:: ipython2
|
|
|
|
J('[0 2 7 0] 23 index_of')
|
|
|
|
|
|
.. parsed-literal::
|
|
|
|
-1
|
|
|
|
|
|
Starting at ``index`` distribute ``count`` "blocks" to the "banks" in
|
|
the sequence.
|
|
|
|
::
|
|
|
|
[...] count index distribute
|
|
----------------------------
|
|
[...]
|
|
|
|
This seems like it would be a PITA to implement in Joypy...
|
|
|
|
.. code:: ipython2
|
|
|
|
from joy.utils.stack import iter_stack, list_to_stack
|
|
|
|
|
|
@SimpleFunctionWrapper
|
|
def distribute(stack):
|
|
'''Starting at index+1 distribute count "blocks" to the "banks" in the sequence.
|
|
|
|
[...] count index distribute
|
|
----------------------------
|
|
[...]
|
|
|
|
'''
|
|
index, (count, (sequence, stack)) = stack
|
|
assert count >= 0
|
|
cheat = list(iter_stack(sequence))
|
|
n = len(cheat)
|
|
assert index < n
|
|
cheat[index] = 0
|
|
while count:
|
|
index += 1
|
|
index %= n
|
|
cheat[index] += 1
|
|
count -= 1
|
|
return list_to_stack(cheat), stack
|
|
|
|
|
|
D['distribute'] = distribute
|
|
|
|
.. code:: ipython2
|
|
|
|
J('[0 2 7 0] dup max [index_of] nullary distribute')
|
|
|
|
|
|
.. parsed-literal::
|
|
|
|
[2 4 1 2]
|
|
|
|
|
|
.. code:: ipython2
|
|
|
|
J('[2 4 1 2] dup max [index_of] nullary distribute')
|
|
|
|
|
|
.. parsed-literal::
|
|
|
|
[3 1 2 3]
|
|
|
|
|
|
.. code:: ipython2
|
|
|
|
J('[3 1 2 3] dup max [index_of] nullary distribute')
|
|
|
|
|
|
.. parsed-literal::
|
|
|
|
[0 2 3 4]
|
|
|
|
|
|
.. code:: ipython2
|
|
|
|
J('[0 2 3 4] dup max [index_of] nullary distribute')
|
|
|
|
|
|
.. parsed-literal::
|
|
|
|
[1 3 4 1]
|
|
|
|
|
|
.. code:: ipython2
|
|
|
|
J('[1 3 4 1] dup max [index_of] nullary distribute')
|
|
|
|
|
|
.. parsed-literal::
|
|
|
|
[2 4 1 2]
|
|
|
|
|
|
Recalling "Generator Programs"
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
::
|
|
|
|
[a F] x
|
|
[a F] a F
|
|
|
|
[a F] a swap [C] dip rest cons
|
|
a [a F] [C] dip rest cons
|
|
a C [a F] rest cons
|
|
a C [F] cons
|
|
|
|
w/ C == dup G
|
|
|
|
a dup G [F] cons
|
|
a a G [F] cons
|
|
|
|
w/ G == dup max [index_of] nullary distribute
|
|
|
|
.. code:: ipython2
|
|
|
|
define('direco == dip rest cons')
|
|
|
|
.. code:: ipython2
|
|
|
|
define('G == [direco] cons [swap] swoncat cons')
|
|
|
|
.. code:: ipython2
|
|
|
|
define('make_distributor == [dup dup max [index_of] nullary distribute] G')
|
|
|
|
.. code:: ipython2
|
|
|
|
J('[0 2 7 0] make_distributor 6 [x] times pop')
|
|
|
|
|
|
.. parsed-literal::
|
|
|
|
[0 2 7 0] [2 4 1 2] [3 1 2 3] [0 2 3 4] [1 3 4 1] [2 4 1 2]
|
|
|
|
|
|
A function to drive a generator and count how many states before a repeat.
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
First draft:
|
|
|
|
::
|
|
|
|
[] [GEN] x [pop index_of 0 >=] [pop size --] [[swons] dip x] primrec
|
|
|
|
(?)
|
|
|
|
::
|
|
|
|
[] [GEN] x [pop index_of 0 >=] [pop size --] [[swons] dip x] primrec
|
|
[] [...] [GEN] [pop index_of 0 >=] [pop size --] [[swons] dip x] primrec
|
|
[] [...] [GEN] pop index_of 0 >=
|
|
[] [...] index_of 0 >=
|
|
-1 0 >=
|
|
False
|
|
|
|
Base case
|
|
|
|
::
|
|
|
|
[] [...] [GEN] [pop index_of 0 >=] [pop size --] [[swons] dip x] primrec
|
|
[] [...] [GEN] pop size --
|
|
[] [...] size --
|
|
[] [...] size --
|
|
|
|
A mistake, ``popop`` and no need for ``--``
|
|
|
|
::
|
|
|
|
[] [...] [GEN] popop size
|
|
[] size
|
|
n
|
|
|
|
Recursive case
|
|
|
|
::
|
|
|
|
[] [...] [GEN] [pop index_of 0 >=] [popop size] [[swons] dip x] primrec
|
|
[] [...] [GEN] [swons] dip x F
|
|
[] [...] swons [GEN] x F
|
|
[[...]] [GEN] x F
|
|
[[...]] [...] [GEN] F
|
|
|
|
[[...]] [...] [GEN] F
|
|
|
|
What have we learned?
|
|
|
|
::
|
|
|
|
F == [pop index_of 0 >=] [popop size] [[swons] dip x] primrec
|
|
|
|
.. code:: ipython2
|
|
|
|
define('count_states == [] swap x [pop index_of 0 >=] [popop size] [[swons] dip x] primrec')
|
|
|
|
.. code:: ipython2
|
|
|
|
define('AoC2017.6 == make_distributor count_states')
|
|
|
|
.. code:: ipython2
|
|
|
|
J('[0 2 7 0] AoC2017.6')
|
|
|
|
|
|
.. parsed-literal::
|
|
|
|
5
|
|
|
|
|
|
.. code:: ipython2
|
|
|
|
J('[1 1 1] AoC2017.6')
|
|
|
|
|
|
.. parsed-literal::
|
|
|
|
4
|
|
|
|
|
|
.. code:: ipython2
|
|
|
|
J('[8 0 0 0 0 0] AoC2017.6')
|
|
|
|
|
|
.. parsed-literal::
|
|
|
|
15
|
|
|