{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Euler Problem 9\n",
    "\n",
    "A Pythagorean triplet is a set of three natural numbers, $a < b < c$, for which,\n",
    "\n",
    "$a^2 + b^2 = c^2$\n",
    "\n",
    "For example, $3^2 + 4^2 = 9 + 16 = 25 = 5^2$.\n",
    "\n",
    "There exists exactly one Pythagorean triplet for which $a + b + c = 1000$.\n",
    "Find the product $abc$."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We start bruteforcing even though it feels like there may be a smart solution."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "66.96907186399949\n",
      "31875000\n"
     ]
    }
   ],
   "source": [
    "import timeit\n",
    "\n",
    "def brute_force():\n",
    "    for a in range(1, 251):\n",
    "        for b in range(a + 1, 501):\n",
    "            for c in range(b + 1, 1001):\n",
    "                if a + b + c == 1000 and a * a + b * b == c * c:\n",
    "                    return a * b * c\n",
    "\n",
    "print(timeit.timeit(brute_force, number=10))\n",
    "print(brute_force())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's do some optimization by cancelling the loops when we exceed the boundaries. Actually, I have also realized that choosing 251 and 501 is a little bit arbitrary. For example if a, b, c where something like $332, 333, 335$ that could be a solution and the first range was too low. Then again, we would have realized that as soon as we get back None, so it is okay."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "64.4656584559998\n",
      "31875000\n"
     ]
    }
   ],
   "source": [
    "def brute_force():\n",
    "    for a in range(1, 251):\n",
    "        for b in range(a + 1, 501):\n",
    "            if a + b > 600:\n",
    "                break\n",
    "            for c in range(b + 1, 1001):\n",
    "                if a + b + c == 1000 and a * a + b * b == c * c:\n",
    "                    return a * b * c\n",
    "                \n",
    "print(timeit.timeit(brute_force, number=10))\n",
    "print(brute_force())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Big time save. Kappa. Okay, I am stupid. If I have a and b I can calculate c and check if it is a solution."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.22822808900036762\n",
      "31875000\n"
     ]
    }
   ],
   "source": [
    "def smart_brute_force():\n",
    "    for a in range(1, 251):\n",
    "        for b in range(a + 1, 501):\n",
    "            c = 1000 - a - b\n",
    "            if a * a + b * b == c * c:\n",
    "                return a * b * c\n",
    "       \n",
    "print(timeit.timeit(smart_brute_force, number=10))\n",
    "print(smart_brute_force())  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "completion_date": "Wed, 20 Aug 2014, 17:06",
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "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.5.4"
  },
  "tags": [
   "brute force",
   "pythagorean",
   "triplet"
  ]
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
