# Advent of Code 2017

## December 6th


    [0 2 7 0] dup max



```python
from notebook_preamble import D, J, V, define
```


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

    [0 2 7 0] 7



```python
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
```


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

    2



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


```python
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
```


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

    [2 4 1 2]



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

    [3 1 2 3]



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

    [0 2 3 4]



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

    [1 3 4 1]



```python
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


```python
define('direco dip rest cons')
```


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


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


```python
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


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


```python
define('AoC2017.6 make_distributor count_states')
```


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

    5



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

    4



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

    15

