Add files via upload

This commit is contained in:
Peter Norvig
2026-07-18 20:40:14 -07:00
committed by GitHub
parent f6bf8d2582
commit 414fe258a4

View File

@@ -156,7 +156,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"[11, 'out of', 11, 'tests pass']" "[12, 'out of', 12, 'tests pass']"
] ]
}, },
"execution_count": 4, "execution_count": 4,
@@ -173,11 +173,12 @@
" 6: 3, # composite\n", " 6: 3, # composite\n",
" 32: 2, # power of 2\n", " 32: 2, # power of 2\n",
" 49: 7, # square of a prime\n", " 49: 7, # square of a prime\n",
" 97: 97, # bigger prime\n",
" 99991: 99991, # even bigger prime\n",
" 97**9: 97, # even bigger power of a prime\n",
" 360: 5, # test case for equations above\n", " 360: 5, # test case for equations above\n",
" 600851475143: 6857 # Project Euler #3\n", " 997: 997, # bigger prime\n",
" 997**9: 997, # bigger power of a prime\n",
" 99991: 99991, # even bigger prime\n",
" 600851475143: 6857, # Project Euler #3\n",
" 99999989: 99999989 # An 8-digit prime number\n",
" }\n", " }\n",
" correct = sum(largest_prime_factor(n) == cases[n] for n in cases)\n", " correct = sum(largest_prime_factor(n) == cases[n] for n in cases)\n",
" return [correct, 'out of', len(cases), 'tests pass']\n", " return [correct, 'out of', len(cases), 'tests pass']\n",
@@ -192,7 +193,7 @@
"source": [ "source": [
"## Efficiency\n", "## Efficiency\n",
"\n", "\n",
"How long does it take to get our answer? We can use `%time` to see it is just a few hundred microseconds (μs):" "How long does it take to run all the test cases?"
] ]
}, },
{ {
@@ -205,14 +206,14 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"CPU times: user 181 μs, sys: 0 ns, total: 181 μs\n", "CPU times: user 2.01 s, sys: 15 ms, total: 2.02 s\n",
"Wall time: 183 μs\n" "Wall time: 2.03 s\n"
] ]
}, },
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"6857" "[12, 'out of', 12, 'tests pass']"
] ]
}, },
"execution_count": 5, "execution_count": 5,
@@ -221,45 +222,7 @@
} }
], ],
"source": [ "source": [
"%time largest_prime_factor(600851475143)" "%time tests()"
]
},
{
"cell_type": "markdown",
"id": "c8ead8e9-199f-47c6-ad76-360b1ebdaa02",
"metadata": {},
"source": [
"The algorithm is slowest when *n* is prime, because the `for` loop has to go all the way up to *n*. How long would it take for the largest 8-digit prime, 99,999,989?"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "7323d528-96d7-4c05-a05d-125e99605443",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 1.9 s, sys: 18.4 ms, total: 1.92 s\n",
"Wall time: 1.92 s\n"
]
},
{
"data": {
"text/plain": [
"99999989"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"n8 = 99999989 # An 8-digit number that happens to be prime \n",
"%time largest_prime_factor(n8)"
] ]
}, },
{ {
@@ -269,14 +232,14 @@
"source": [ "source": [
"About 2 seconds. Maybe that's good enough. But could we speed things up?\n", "About 2 seconds. Maybe that's good enough. But could we speed things up?\n",
"\n", "\n",
"In trying to find a *p* that evenly divides *n*, the algorithm tests all the integers from 2 to *n*. But do we really have to test all those potential factors? No! Either *n* is prime, or it has two factors *p* and *q* such that *p* × *q* = *n*. Of those two factors, one must be less than or equal to the square root of *n*. So to determine if *n* has a prime factor other than itself, we only have to check integers up to √*n*, not all the way up to *n*. That's a big difference! for an 8-digit prime it is the difference between roughly 100 million steps versus a mere 10 thousand steps.\n", "In trying to find a *p* that evenly divides *n*, the algorithm tests all the integers from 2 to *n*. But do we really have to test all those potential factors? No! Either *n* is prime, or it has two factors *p* and *q* such that *p* × *q* = *n*. Of those two factors, one must be less than or equal to the square root of *n*. So to determine if *n* has a prime factor other than itself, we only have to check integers up to √*n*, not all the way up to *n*. That's a big difference! For an 8-digit prime it is the difference between roughly 100 million steps versus a mere 10 thousand steps.\n",
"\n", "\n",
"Let's change the definition of `largest_prime_factor` to incorporate this new trick. (We will `import` the square root function, `sqrt`, from the `math` module.)" "Let's change the definition of `largest_prime_factor` to incorporate this new trick. (We will `import` the square root function, `sqrt`, from the `math` module.)"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 7, "execution_count": 6,
"id": "b90b5407-4666-4925-99d2-6a3a6b192fac", "id": "b90b5407-4666-4925-99d2-6a3a6b192fac",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
@@ -294,46 +257,17 @@
" return n # n is prime or 1" " return n # n is prime or 1"
] ]
}, },
{
"cell_type": "markdown",
"id": "c39b08b9-06ed-49c0-a277-db248de909fd",
"metadata": {},
"source": [
"Any time you change a function, you should re-run the tests to give you some confidence that you didn't introduce a bug:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "4026dc87-a0aa-4c75-b92a-96ec24cda1b7",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[11, 'out of', 11, 'tests pass']"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tests()"
]
},
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "6cddf393-a0fd-4cc2-9eef-3341339106bd", "id": "6cddf393-a0fd-4cc2-9eef-3341339106bd",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Now we can see how fast the new function is on the 8-digit prime:" "Now we can see how fast the new function is, and verify that it still passes all the tests:"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 9, "execution_count": 7,
"id": "d3d0c13e-5c01-4112-b372-60f7eb302d25", "id": "d3d0c13e-5c01-4112-b372-60f7eb302d25",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
@@ -341,23 +275,23 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"CPU times: user 196 μs, sys: 0 ns, total: 196 μs\n", "CPU times: user 523 μs, sys: 5 μs, total: 528 μs\n",
"Wall time: 196 μs\n" "Wall time: 548 μs\n"
] ]
}, },
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"99999989" "[12, 'out of', 12, 'tests pass']"
] ]
}, },
"execution_count": 9, "execution_count": 7,
"metadata": {}, "metadata": {},
"output_type": "execute_result" "output_type": "execute_result"
} }
], ],
"source": [ "source": [
"%time largest_prime_factor(n8)" "%time tests()"
] ]
}, },
{ {
@@ -365,14 +299,14 @@
"id": "82b008ea-f6b5-4bcd-8768-09c8dab089cb", "id": "82b008ea-f6b5-4bcd-8768-09c8dab089cb",
"metadata": {}, "metadata": {},
"source": [ "source": [
"As predicted, this is about 10,000 times faster.\n", "This is thousands of times faster.\n",
"\n", "\n",
"We should be able to handle a 16-digit prime in about 2 seconds:" "We should be able to handle a 16-digit prime in about 2 seconds:"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 10, "execution_count": 8,
"id": "9b6030ef-626a-4195-aedb-ef2edac65da4", "id": "9b6030ef-626a-4195-aedb-ef2edac65da4",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
@@ -380,8 +314,8 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"CPU times: user 1.96 s, sys: 19.3 ms, total: 1.97 s\n", "CPU times: user 2.12 s, sys: 13 ms, total: 2.13 s\n",
"Wall time: 1.97 s\n" "Wall time: 2.14 s\n"
] ]
}, },
{ {
@@ -390,7 +324,7 @@
"9927935178558959" "9927935178558959"
] ]
}, },
"execution_count": 10, "execution_count": 8,
"metadata": {}, "metadata": {},
"output_type": "execute_result" "output_type": "execute_result"
} }
@@ -414,17 +348,25 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 11, "execution_count": 9,
"id": "0308612c-6860-49b0-bcd6-856fa08133b1", "id": "0308612c-6860-49b0-bcd6-856fa08133b1",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
"data": { "name": "stdout",
"text/plain": [ "output_type": "stream",
"[11, 'out of', 11, 'tests pass']" "text": [
"CPU times: user 522 μs, sys: 1 μs, total: 523 μs\n",
"Wall time: 525 μs\n"
] ]
}, },
"execution_count": 11, {
"data": {
"text/plain": [
"[12, 'out of', 12, 'tests pass']"
]
},
"execution_count": 9,
"metadata": {}, "metadata": {},
"output_type": "execute_result" "output_type": "execute_result"
} }
@@ -440,9 +382,10 @@
"\n", "\n",
"def smallest_prime_factor(n):\n", "def smallest_prime_factor(n):\n",
" \"\"\"The smallest prime that evenly divides n (or n itself if no prime divisors).\"\"\"\n", " \"\"\"The smallest prime that evenly divides n (or n itself if no prime divisors).\"\"\"\n",
" return next((p for p in range(2, int(sqrt(n) + 1)) if n % p == 0), n)\n", " divisors = (p for p in range(2, int(sqrt(n) + 1)) if n % p == 0)\n",
" return next(divisors, n)\n",
"\n", "\n",
"tests()" "%time tests()"
] ]
}, },
{ {
@@ -455,17 +398,25 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 12, "execution_count": 10,
"id": "b8907a8f-872f-4531-825c-fae9c70211c1", "id": "b8907a8f-872f-4531-825c-fae9c70211c1",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
"data": { "name": "stdout",
"text/plain": [ "output_type": "stream",
"[11, 'out of', 11, 'tests pass']" "text": [
"CPU times: user 490 μs, sys: 1 μs, total: 491 μs\n",
"Wall time: 492 μs\n"
] ]
}, },
"execution_count": 12, {
"data": {
"text/plain": [
"[12, 'out of', 12, 'tests pass']"
]
},
"execution_count": 10,
"metadata": {}, "metadata": {},
"output_type": "execute_result" "output_type": "execute_result"
} }
@@ -485,15 +436,23 @@
" p = p + 1\n", " p = p + 1\n",
" return max(n, largest)\n", " return max(n, largest)\n",
" \n", " \n",
"tests()" "%time tests()"
] ]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4f44c6ec-7126-4bc8-9ce2-3fb23154791d",
"metadata": {},
"outputs": [],
"source": []
} }
], ],
"metadata": { "metadata": {
"kernelspec": { "kernelspec": {
"display_name": "Python 3 (ipykernel)", "display_name": "Python [conda env:base] *",
"language": "python", "language": "python",
"name": "python3" "name": "conda-base-py"
}, },
"language_info": { "language_info": {
"codemirror_mode": { "codemirror_mode": {