{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Euler Problem 26\n",
    "\n",
    "A unit fraction contains 1 in the numerator. The decimal representation of the unit fractions with denominators 2 to 10 are given:\n",
    "\n",
    "~~~\n",
    "1/2\t = \t0.5\n",
    "1/3\t = \t0.(3)\n",
    "1/4\t = \t0.25\n",
    "1/5\t = \t0.2\n",
    "1/6\t = \t0.1(6)\n",
    "1/7\t = \t0.(142857)\n",
    "1/8\t = \t0.125\n",
    "1/9\t = \t0.(1)\n",
    "1/10    = \t0.1\n",
    "~~~\n",
    "\n",
    "Where 0.1(6) means 0.166666..., and has a 1-digit recurring cycle. It can be seen that 1/7 has a 6-digit recurring cycle.\n",
    "\n",
    "Find the value of d < 1000 for which 1/d contains the longest recurring cycle in its decimal fraction part."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The trick here is to identify a cycle. The easiest way I see to do this is to memorize the remainders. If we have a remainder that we occurred previously there is a cycle.\n",
    "\n",
    "Let's consider 1/3. The initial remainder is 10. For ten divided by three the new remainder is again ten (or one times ten). So we have a one-cycle of 3."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "def get_cycle_count(nominator, denominator):\n",
    "    from itertools import count\n",
    "    assert(nominator == 1)\n",
    "    remainders = {}\n",
    "    remainder = nominator\n",
    "    results = []\n",
    "    for i in count():\n",
    "        result = remainder // denominator\n",
    "        remainder = remainder % denominator\n",
    "        results.append(result)\n",
    "        if remainder in remainders:\n",
    "            return i - remainders[remainder]\n",
    "        else:\n",
    "            remainders[remainder] = i\n",
    "        if remainder == 0:\n",
    "            return 0\n",
    "        remainder *= 10\n",
    "\n",
    "assert(get_cycle_count(1, 7) == 6)\n",
    "assert(get_cycle_count(1, 10) == 0)\n",
    "assert(get_cycle_count(1, 6) == 1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This is a simple divison algorithm. The only special thing is the remainder and that we remember when it occurs the first time. If a remainder occurrs for the second time we substract the position and thus have the lenght of the cycle. With this solution we should be efficient enough to brute force."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "983\n"
     ]
    }
   ],
   "source": [
    "s = max([(get_cycle_count(1, i), i)for i in range(1, 1000)])\n",
    "s = s[1]\n",
    "assert(s == 983)\n",
    "print(s)"
   ]
  }
 ],
 "metadata": {
  "completion_date": "Mon, 9 Nov 2015, 22:11",
  "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": [
   "reciprocal",
   "division",
   "nominator",
   "denominator"
  ]
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
