{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Advent of Code 2017\n",
    "\n",
    "## December 6th\n",
    "\n",
    "\n",
    "    [0 2 7 0] dup max\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from notebook_preamble import D, J, V, define"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0 2 7 0] 7\n"
     ]
    }
   ],
   "source": [
    "J('[0 2 7 0] dup max')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "from joy.library import SimpleFunctionWrapper\n",
    "from joy.utils.stack import list_to_stack\n",
    "\n",
    "\n",
    "@SimpleFunctionWrapper\n",
    "def index_of(stack):\n",
    "    '''Given a sequence and a item, return the index of the item, or -1 if not found.\n",
    "\n",
    "    E.g.:\n",
    "\n",
    "       [a b c] a index_of\n",
    "    ------------------------\n",
    "               0\n",
    "\n",
    "       [a b c] d index_of\n",
    "    ------------------------\n",
    "            -1\n",
    "\n",
    "    '''\n",
    "    item, (sequence, stack) = stack\n",
    "    i = 0\n",
    "    while sequence:\n",
    "        term, sequence = sequence\n",
    "        if term == item:\n",
    "            break\n",
    "        i += 1\n",
    "    else:\n",
    "        i = -1\n",
    "    return i, stack\n",
    "\n",
    "\n",
    "D['index_of'] = index_of"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n"
     ]
    }
   ],
   "source": [
    "J('[0 2 7 0] 7 index_of')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-1\n"
     ]
    }
   ],
   "source": [
    "J('[0 2 7 0] 23 index_of')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Starting at `index` distribute `count` \"blocks\" to the \"banks\" in the sequence.\n",
    "\n",
    "    [...] count index distribute\n",
    "    ----------------------------\n",
    "               [...]\n",
    "\n",
    "This seems like it would be a PITA to implement in Joypy..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "from joy.utils.stack import iter_stack, list_to_stack\n",
    "\n",
    "\n",
    "@SimpleFunctionWrapper\n",
    "def distribute(stack):\n",
    "    '''Starting at index+1 distribute count \"blocks\" to the \"banks\" in the sequence.\n",
    "\n",
    "    [...] count index distribute\n",
    "    ----------------------------\n",
    "               [...]\n",
    "\n",
    "    '''\n",
    "    index, (count, (sequence, stack)) = stack\n",
    "    assert count >= 0\n",
    "    cheat = list(iter_stack(sequence))\n",
    "    n = len(cheat)\n",
    "    assert index < n\n",
    "    cheat[index] = 0\n",
    "    while count:\n",
    "        index += 1\n",
    "        index %= n\n",
    "        cheat[index] += 1\n",
    "        count -= 1\n",
    "    return list_to_stack(cheat), stack\n",
    "\n",
    "\n",
    "D['distribute'] = distribute"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2 4 1 2]\n"
     ]
    }
   ],
   "source": [
    "J('[0 2 7 0] dup max [index_of] nullary distribute')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[3 1 2 3]\n"
     ]
    }
   ],
   "source": [
    "J('[2 4 1 2] dup max [index_of] nullary distribute')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0 2 3 4]\n"
     ]
    }
   ],
   "source": [
    "J('[3 1 2 3] dup max [index_of] nullary distribute')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 3 4 1]\n"
     ]
    }
   ],
   "source": [
    "J('[0 2 3 4] dup max [index_of] nullary distribute')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2 4 1 2]\n"
     ]
    }
   ],
   "source": [
    "J('[1 3 4 1] dup max [index_of] nullary distribute')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Recalling \"Generator Programs\"\n",
    "\n",
    "    [a F] x\n",
    "    [a F] a F \n",
    "    \n",
    "    [a F] a swap [C] dip rest cons\n",
    "    a   [a F]    [C] dip rest cons\n",
    "    a C [a F]            rest cons\n",
    "    a C   [F]                 cons\n",
    "\n",
    "    w/ C == dup G\n",
    "\n",
    "    a dup G [F] cons\n",
    "    a a   G [F] cons\n",
    "\n",
    "    w/ G == dup max [index_of] nullary distribute"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "define('direco dip rest cons')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "define('G [direco] cons [swap] swoncat cons')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "define('make_distributor [dup dup max [index_of] nullary distribute] G')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0 2 7 0] [2 4 1 2] [3 1 2 3] [0 2 3 4] [1 3 4 1] [2 4 1 2]\n"
     ]
    }
   ],
   "source": [
    "J('[0 2 7 0] make_distributor 6 [x] times pop')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### A function to drive a generator and count how many states before a repeat.\n",
    "First draft:\n",
    "\n",
    "    [] [GEN] x [pop index_of 0 >=] [pop size --] [[swons] dip x] tailrec\n",
    "\n",
    "(?)\n",
    "\n",
    "    []       [GEN] x [pop index_of 0 >=] [pop size --] [[swons] dip x] tailrec\n",
    "    [] [...] [GEN]   [pop index_of 0 >=] [pop size --] [[swons] dip x] tailrec\n",
    "    [] [...] [GEN]    pop index_of 0 >=\n",
    "    [] [...]              index_of 0 >=\n",
    "                                -1 0 >=\n",
    "                                 False\n",
    "\n",
    "Base case\n",
    "\n",
    "    [] [...] [GEN] [pop index_of 0 >=] [pop size --] [[swons] dip x] tailrec\n",
    "    [] [...] [GEN]                      pop size --\n",
    "    [] [...]                                size --\n",
    "    [] [...]                                size --\n",
    "\n",
    "A mistake, `popop` and no need for `--`\n",
    "\n",
    "    [] [...] [GEN] popop size\n",
    "    []                   size\n",
    "    n\n",
    "\n",
    "Recursive case\n",
    "\n",
    "    [] [...] [GEN] [pop index_of 0 >=] [popop size] [[swons] dip x] tailrec\n",
    "    [] [...] [GEN]                                   [swons] dip x  F\n",
    "    [] [...] swons [GEN]                                         x  F\n",
    "    [[...]]        [GEN]                                         x  F\n",
    "    [[...]] [...]  [GEN]                                            F\n",
    "\n",
    "    [[...]] [...] [GEN] F\n",
    "\n",
    "What have we learned?\n",
    "\n",
    "    F == [pop index_of 0 >=] [popop size] [[swons] dip x] tailrec"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "define('count_states [] swap x [pop index_of 0 >=] [popop size] [[swons] dip x] tailrec')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "define('AoC2017.6 make_distributor count_states')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n"
     ]
    }
   ],
   "source": [
    "J('[0 2 7 0] AoC2017.6')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4\n"
     ]
    }
   ],
   "source": [
    "J('[1 1 1] AoC2017.6')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "15\n"
     ]
    }
   ],
   "source": [
    "J('[8 0 0 0 0 0] AoC2017.6')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
