{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Advent of Code 2017\n",
    "\n",
    "## December 1st\n",
    "\n",
    "\\[Given\\] a sequence of digits (your puzzle input) and find the sum of all digits that match the next digit in the list. The list is circular, so the digit after the last digit is the first digit in the list.\n",
    "\n",
    "For example:\n",
    "\n",
    "* 1122 produces a sum of 3 (1 + 2) because the first digit (1) matches the second digit and the third digit (2) matches the fourth digit.\n",
    "* 1111 produces 4 because each digit (all 1) matches the next.\n",
    "* 1234 produces 0 because no digit matches the next.\n",
    "* 91212129 produces 9 because the only digit that matches the next one is the last digit, 9."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from notebook_preamble import J, V, define"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "I'll assume the input is a Joy sequence of integers (as opposed to a string or something else.)\n",
    "\n",
    "We might proceed by creating a word that makes a copy of the sequence with the first item moved to the last, and zips it with the original to make a list of pairs, and a another word that adds (one of) each pair to a total if the pair matches.\n",
    "\n",
    "    AoC2017.1 == pair_up total_matches\n",
    "\n",
    "Let's derive `pair_up`:\n",
    "\n",
    "         [a b c] pair_up\n",
    "    -------------------------\n",
    "       [[a b] [b c] [c a]]\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Straightforward (although the order of each pair is reversed, due to the way `zip` works, but it doesn't matter for this program):\n",
    "\n",
    "    [a b c] dup\n",
    "    [a b c] [a b c] uncons swap\n",
    "    [a b c] [b c] a unit concat\n",
    "    [a b c] [b c a] zip\n",
    "    [[b a] [c b] [a c]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "define('pair_up == dup uncons swap unit concat zip')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[2 1] [3 2] [1 3]]\n"
     ]
    }
   ],
   "source": [
    "J('[1 2 3] pair_up')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[2 1] [2 2] [3 2] [1 3]]\n"
     ]
    }
   ],
   "source": [
    "J('[1 2 2 3] pair_up')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we need to derive `total_matches`.  It will be a `step` function:\n",
    "\n",
    "    total_matches == 0 swap [F] step\n",
    "\n",
    "Where `F` will have the pair to work with, and it will basically be a `branch` or `ifte`.\n",
    "\n",
    "    total [n m] F\n",
    "\n",
    "It will probably be easier to write if we dequote the pair:\n",
    "\n",
    "       total [n m] i F′\n",
    "    ----------------------\n",
    "         total n m F′\n",
    "\n",
    "Now `F′` becomes just:\n",
    "\n",
    "    total n m [=] [pop +] [popop] ifte\n",
    "\n",
    "So:\n",
    "\n",
    "    F == i [=] [pop +] [popop] ifte\n",
    "\n",
    "And thus:\n",
    "\n",
    "    total_matches == 0 swap [i [=] [pop +] [popop] ifte] step"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "define('total_matches == 0 swap [i [=] [pop +] [popop] ifte] step')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n"
     ]
    }
   ],
   "source": [
    "J('[1 2 3] pair_up total_matches')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n"
     ]
    }
   ],
   "source": [
    "J('[1 2 2 3] pair_up total_matches')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we can define our main program and evaluate it on the examples."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "define('AoC2017.1 == pair_up total_matches')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n"
     ]
    }
   ],
   "source": [
    "J('[1 1 2 2] AoC2017.1')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4\n"
     ]
    }
   ],
   "source": [
    "J('[1 1 1 1] AoC2017.1')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n"
     ]
    }
   ],
   "source": [
    "J('[1 2 3 4] AoC2017.1')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "9\n"
     ]
    }
   ],
   "source": [
    "J('[9 1 2 1 2 1 2 9] AoC2017.1')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "9\n"
     ]
    }
   ],
   "source": [
    "J('[9 1 2 1 2 1 2 9] AoC2017.1')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "          pair_up == dup uncons swap unit concat zip\n",
    "    total_matches == 0 swap [i [=] [pop +] [popop] ifte] step\n",
    "\n",
    "        AoC2017.1 == pair_up total_matches"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now the paired digit is \"halfway\" round.\n",
    "\n",
    "    [a b c d] dup size 2 / [drop] [take reverse] cleave concat zip"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[3 1] [4 2] [1 3] [2 4]]\n"
     ]
    }
   ],
   "source": [
    "J('[1 2 3 4] dup size 2 / [drop] [take reverse] cleave concat zip')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "I realized that each pair is repeated..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 2 3 4] [[1 3] [2 4]]\n"
     ]
    }
   ],
   "source": [
    "J('[1 2 3 4] dup size 2 / [drop] [take reverse] cleave  zip')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "define('AoC2017.1.extra == dup size 2 / [drop] [take reverse] cleave  zip swap pop total_matches 2 *')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6\n"
     ]
    }
   ],
   "source": [
    "J('[1 2 1 2] AoC2017.1.extra')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n"
     ]
    }
   ],
   "source": [
    "J('[1 2 2 1] AoC2017.1.extra')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4\n"
     ]
    }
   ],
   "source": [
    "J('[1 2 3 4 2 5] AoC2017.1.extra')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Refactor FTW\n",
    "\n",
    "With Joy a great deal of the heuristics from Forth programming carry over nicely.  For example, refactoring into small, well-scoped commands with mnemonic names...\n",
    "\n",
    "             rotate_seq == uncons swap unit concat\n",
    "                pair_up == dup rotate_seq zip\n",
    "           add_if_match == [=] [pop +] [popop] ifte\n",
    "          total_matches == [i add_if_match] step_zero\n",
    "\n",
    "              AoC2017.1 == pair_up total_matches\n",
    "\n",
    "           half_of_size == dup size 2 /\n",
    "               split_at == [drop] [take reverse] cleave\n",
    "          pair_up.extra == half_of_size split_at zip swap pop\n",
    "\n",
    "        AoC2017.1.extra == pair_up.extra total_matches 2 *\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
