euler/ipython/EulerProblem031.ipynb

261 lines
6.3 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 31\n",
"\n",
"In England the currency is made up of pound, £, and pence, p, and there are eight coins in general circulation:\n",
"\n",
"1p, 2p, 5p, 10p, 20p, 50p, £1 (100p) and £2 (200p).\n",
"\n",
"It is possible to make £2 in the following way:\n",
"\n",
"1×£1 + 1×50p + 2×20p + 1×5p + 1×2p + 3×1p\n",
"\n",
"How many different ways can £2 be made using any number of coins?"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"Let's do it non-recursive. Tricky part is to use ceil, otherwise we get wrong ranges for example for $\\frac{50}{20}$."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0, 1]\n",
"[0, 1, 2]\n"
]
}
],
"source": [
"from math import ceil\n",
"\n",
"print(list(range(50 // 20)))\n",
"print(list(range(ceil(50 / 20))))"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"from math import ceil\n",
"\n",
"def calculate():\n",
" r = 200\n",
" c = 0\n",
"\n",
" if r % 200 == 0:\n",
" c += 1\n",
" for p200 in range(ceil(r / 200)):\n",
" r200 = r - p200 * 200\n",
" if r200 % 100 == 0:\n",
" c += 1\n",
" for p100 in range(ceil(r200 / 100)):\n",
" r100 = r200 - p100 * 100\n",
" if r100 % 50 == 0:\n",
" c += 1\n",
" for p50 in range(ceil(r100 / 50)):\n",
" r50 = r100 - p50 * 50\n",
" if r50 % 20 == 0:\n",
" c += 1\n",
" for p20 in range(ceil(r50 / 20)):\n",
" r20 = r50 - p20 * 20\n",
" if r20 <= 0:\n",
" break\n",
" if r20 % 10 == 0:\n",
" c += 1\n",
" for p10 in range(ceil(r20 / 10)):\n",
" r10 = r20 - p10 * 10\n",
" if r10 % 5 == 0:\n",
" c += 1\n",
" for p5 in range(ceil(r10 / 5)):\n",
" r5 = r10 - p5 * 5\n",
" if r5 % 2 == 0:\n",
" c += 1\n",
" for p2 in range(ceil(r5 / 2)):\n",
" r2 = r5 - p2 * 2\n",
" if r2 % 1 == 0:\n",
" c += 1\n",
"\n",
" return c\n",
"\n",
"s = calculate()"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"73682\n"
]
}
],
"source": [
"print(s)\n",
"assert(s == 73682)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I came up with a more concise solution that can be implemented in Scheme. I would like to compare the performance of the solutions."
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"73682\n"
]
}
],
"source": [
"def count_change(change, coins):\n",
" if not coins:\n",
" return 0\n",
" count = 0\n",
" coin, coins = coins[0], coins[1:]\n",
" for i in range(change // coin + 1):\n",
" if change - i * coin == 0:\n",
" count += 1\n",
" continue\n",
" if change - i * coin < 0:\n",
" break\n",
" count += count_change(change - i * coin, coins)\n",
" return count\n",
"\n",
"def calculate_iterative():\n",
" return count_change(200, [200, 100, 50, 20, 10, 5, 2, 1])\n",
"\n",
"s = calculate_iterative()\n",
"print(s)"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.16300111500095227\n",
"11.429953110000497\n"
]
}
],
"source": [
"import timeit\n",
"print(timeit.timeit(calculate, number=10))\n",
"print(timeit.timeit(calculate_iterative, number=10))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Turns out I was way smarter than I thought when I have developped calculate. It checks the remainder and by doing that saves a ton of iterations."
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"73682\n",
"0.34602016500139143\n"
]
}
],
"source": [
"def count_change(change, coins):\n",
" count = 0\n",
" coin, coins = coins[0], coins[1:]\n",
"\n",
" if change % coin == 0:\n",
" count += 1\n",
" \n",
" if not coins:\n",
" return count\n",
" \n",
" for i in range(ceil(change / coin)):\n",
" count += count_change(change - i * coin, coins)\n",
" return count\n",
"\n",
"def calculate_iterative():\n",
" return count_change(200, [200, 100, 50, 20, 10, 5, 2, 1])\n",
"\n",
"s = calculate_iterative()\n",
"print(s)\n",
"print(timeit.timeit(calculate_iterative, number=10))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Fri, 25 Aug 2017, 13:02",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"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.6.5"
},
"tags": [
"recursion",
"coins"
]
},
"nbformat": 4,
"nbformat_minor": 2
}