# Advent of Code 2017¶

## December 6th¶

    [0 2 7 0] dup max

In [1]:

    from notebook_preamble import D, J, V, define

In [2]:

    J('[0 2 7 0] dup max')

    [0 2 7 0] 7

In [3]:

    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

In [4]:

    J('[0 2 7 0] 7 index_of')

    2

In [5]:

    J('[0 2 7 0] 23 index_of')

    -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...

In [6]:

    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

In [7]:

    J('[0 2 7 0] dup max [index_of] nullary distribute')

    [2 4 1 2]

In [8]:

    J('[2 4 1 2] dup max [index_of] nullary distribute')

    [3 1 2 3]

In [9]:

    J('[3 1 2 3] dup max [index_of] nullary distribute')

    [0 2 3 4]

In [10]:

    J('[0 2 3 4] dup max [index_of] nullary distribute')

    [1 3 4 1]

In [11]:

    J('[1 3 4 1] dup max [index_of] nullary distribute')

    [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

In [12]:

    define('direco dip rest cons')

In [13]:

    define('G [direco] cons [swap] swoncat cons')

In [14]:

    define('make_distributor [dup dup max [index_of] nullary distribute] G')

In [15]:

    J('[0 2 7 0] make_distributor 6 [x] times pop')

    [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] tailrec

(?)

    []       [GEN] x [pop index_of 0 >=] [pop size --] [[swons] dip x] tailrec
    [] [...] [GEN]   [pop index_of 0 >=] [pop size --] [[swons] dip x] tailrec
    [] [...] [GEN]    pop index_of 0 >=
    [] [...]              index_of 0 >=
                                -1 0 >=
                                 False

Base case

    [] [...] [GEN] [pop index_of 0 >=] [pop size --] [[swons] dip x] tailrec
    [] [...] [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] tailrec
    [] [...] [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] tailrec

In [16]:

    define('count_states [] swap x [pop index_of 0 >=] [popop size] [[swons] dip x] tailrec')

In [17]:

    define('AoC2017.6 make_distributor count_states')

In [18]:

    J('[0 2 7 0] AoC2017.6')

    5

In [19]:

    J('[1 1 1] AoC2017.6')

    4

In [20]:

    J('[8 0 0 0 0 0] AoC2017.6')

    15