      "    * return value\n",
      "\n",
      "Complexity:\n",
      "* Time: O(1)\n",
      "* Space: O(1)\n",
      "\n",
      "\n",
      "### Absolute Index\n",
      "\n",
      "* return stack size * stack index + stack pointer\n",
      "\n",
      "Complexity:\n",
      "* Time: O(1)\n",
      "* Space: O(1)"
     ]
    },
    {
     "cell_type": "markdown",
 
</s> remove     "* Initialize array\n",
    "* Initialize stack pointers to -1\n",
 </s> add     "### Absolute Index\n",
    "\n",
    "* return stack size * stack index + stack pointer\n",
    "\n",
    "Complexity:\n",
    "* Time: O(1)\n",
    "* Space: O(1)\n", </s> remove     "## Clarifying Questions\n",
 </s> add     "## Constraints and Assumptions\n",
    "\n",
    "*Problem statements are often intentionally ambiguous.  Identifying constraints and stating assumptions can help to ensure you code the intended solution.*\n", </s> remove     "* [Code](#Code)"
 </s> add     "* [Code](#Code)\n",
    "* [Unit Test](#Unit-Test)" </s> remove     "num_stacks = 3\n",
    "stack_size = 100\n",
    "print('Pop on empty stack')\n",
    "stacks = Stacks(num_stacks, stack_size)\n",
    "try:\n",
    "    stacks.pop(0)\n",
    "except Exception as e:\n",
    "    print(e)\n",
    "print('Push to non-full stack')\n",
    "stacks.push(0, 1)\n",
    "stacks.push(0, 2)\n",
    "stacks.push(1, 3)\n",
    "stacks.push(2, 4)\n",
    "print('Pop on non-empty stack')\n",
    "print(stacks.pop(0))\n",
    "print(stacks.pop(0))\n",
    "print(stacks.pop(1))\n",
    "print(stacks.pop(2))\n",
    "print('Push to full stack')\n",
    "for i in xrange(0, stack_size):\n",
    "    stacks.push(2, i)\n",
    "try:\n",
    "    stacks.push(2, stack_size)\n",
    "except Exception as e:\n",
    "    print(e)"
 </s> add     "from nose.tools import assert_equal\n",
    "from nose.tools import raises\n",
    "\n",
    "class Test(object):\n",
    "    @raises(Exception)\n",
    "    def test_pop_on_empty(self, num_stacks, stack_size):\n",
    "        print('Test: Pop on empty stack')\n",
    "        stacks = Stacks(num_stacks, stack_size)\n",
    "        stacks.pop(0)\n",
    "\n",
    "    @raises(Exception)\n",
    "    def test_push_on_full(self, num_stacks, stack_size):\n",
    "        print('Test: Push to full stack')\n",
    "        stacks = Stacks(num_stacks, stack_size)\n",
    "        for i in xrange(0, stack_size):\n",
    "            stacks.push(2, i)\n",
    "        stacks.push(2, stack_size)\n",
    "\n",
    "    def test_stacks(self, num_stacks, stack_size):\n",
    "        print('Test: Push to non-full stack')\n",
    "        stacks = Stacks(num_stacks, stack_size)\n",
    "        stacks.push(0, 1)\n",
    "        stacks.push(0, 2)\n",
    "        stacks.push(1, 3)\n",
    "        stacks.push(2, 4)\n",
    "\n",
    "        print('Test: Pop on non-empty stack')\n",
    "        assert_equal(stacks.pop(0), 2)\n",
    "        assert_equal(stacks.pop(0), 1)\n",
    "        assert_equal(stacks.pop(1), 3)\n",
    "        assert_equal(stacks.pop(2), 4)\n",
    "\n",
    "        print('Success: test_stacks\\n')\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    num_stacks = 3\n",
    "    stack_size = 100    \n",
    "    test = Test()\n",
    "    test.test_pop_on_empty(num_stacks, stack_size)\n",
    "    test.test_push_on_full(num_stacks, stack_size)\n",
    "    test.test_stacks(num_stacks, stack_size)"
      "    * return value\n",
      "\n",
      "Complexity:\n",
      "* Time: O(1)\n",









      "* Space: O(1)"
     ]
    },
    {
     "cell_type": "markdown",
keep keep keep keep replace replace replace replace replace replace replace replace replace keep keep keep keep keep
 Reworked notebook: Added more detail to constraints and test cases.  Reworked algorithm discussion and unit test. 
stacks-queues/n-stacks.ipynb