Add files via upload

This commit is contained in:
Peter Norvig
2026-05-29 13:29:30 -07:00
committed by GitHub
parent 9e14d0c5ac
commit 7ac2359e88

View File

@@ -15,17 +15,17 @@
" The prime factors of 13195 are 5, 7, 13 and 29.\n",
" What is the largest prime factor of the number 600851475143?\n",
"\n",
"I'll describe here how I think about this problem. There are two things to get right: the general plan of how to attack this problem, and the details of how to say it in Python.\n",
"I'll describe here how I think about this problem, at alevel suitable for a novice programmer. There are two things to get right: the general plan of how to attack this problem, and the details of how to say it in Python.\n",
"\n",
"## The General Plan\n",
"\n",
"I would like to be able to find the largest prime factor of *any* integer, not just 600851475143; I want `largest_prime_factor(n)`. Here's how I think about it:\n",
"\n",
"- I don't know how to immediately find the largest prime factor of *n*. (How would I know which numbers are prime?)\n",
"- I don't know how to immediately find the *largest* prime factor of *n*. \n",
"- I do know how to find the *smallest* prime factor: just go through the integers from 2 to *n*, in order. The first integer that evenly divides *n* must be the smallest prime factor. It is a factor because it evenly divides, it is smallest because we didn't find a smaller one first, and it is prime because if it were a composite number (like 4 or 9), then we would have found one of its factors (like 2 or 3) first.\n",
"- Once I have the smallest prime factor ***p*** then I know: **the largest prime factor of *n* is the maximum of *p* and the largest prime factor of *n*/*p*.**\n",
"- If *n* is prime, then the largest prime factor is *n*.\n",
"- If *n* is 1, then [by convention](https://oeis.org/wiki/Greatest_prime_factor_of_n) we say the greatest prime factor is 1, even though 1 is usually not considered a prime.\n"
"- If *n* is 1, then [by convention](https://oeis.org/wiki/Greatest_prime_factor_of_n) we say the largest prime factor is 1, even though 1 is usually not considered a prime."
]
},
{
@@ -53,7 +53,7 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": 10,
"id": "249c7f13-cdf9-41a2-b0e7-8a3dec15f74b",
"metadata": {},
"outputs": [],
@@ -62,7 +62,7 @@
" \"\"\"The largest prime that evenly divides n.\n",
" Find the smallest prime p that evenly divides n, \n",
" and return the maximum of p and the largest prime factor of n/p.\n",
" For prime n and for 1, return n.\"\"\"\n",
" If n is prime or if n = 1, this will return n.\"\"\"\n",
" for p in range(2, n):\n",
" if n % p == 0: # n is composite\n",
" return max(p, largest_prime_factor(n // p))\n",
@@ -81,7 +81,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 11,
"id": "734de0e3-aafc-438a-8332-09741eef39aa",
"metadata": {},
"outputs": [
@@ -91,7 +91,7 @@
"6857"
]
},
"execution_count": 2,
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
@@ -142,7 +142,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 12,
"id": "9bedb1c9-4138-4250-90e6-77b10ba01586",
"metadata": {},
"outputs": [
@@ -152,7 +152,7 @@
"'all tests pass'"
]
},
"execution_count": 3,
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
@@ -167,6 +167,7 @@
" assert largest_prime_factor(36) == 3 # example from the diagram\n",
" assert largest_prime_factor(49) == 7 # square of a prime\n",
" assert largest_prime_factor(97) == 97 # bigger prime\n",
" assert largest_prime_factor(97 ** 9) == 97 # even bigger prime\n",
" assert largest_prime_factor(600851475143) == 6857 # really big number\n",
" return 'all tests pass'\n",
"\n",
@@ -185,7 +186,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 13,
"id": "0e4a1dc6-5969-49fd-9d65-11d9801cbea2",
"metadata": {},
"outputs": [
@@ -193,8 +194,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 249 μs, sys: 20 μs, total: 269 μs\n",
"Wall time: 296 μs\n"
"CPU times: user 633 μs, sys: 71 μs, total: 704 μs\n",
"Wall time: 706 μs\n"
]
},
{
@@ -203,7 +204,7 @@
"6857"
]
},
"execution_count": 4,
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
@@ -217,12 +218,12 @@
"id": "c8ead8e9-199f-47c6-ad76-360b1ebdaa02",
"metadata": {},
"source": [
"The algorithm should be slowest when *n* is prime, because then 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?"
"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": 5,
"execution_count": 14,
"id": "7323d528-96d7-4c05-a05d-125e99605443",
"metadata": {},
"outputs": [
@@ -230,8 +231,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 1.92 s, sys: 6.64 ms, total: 1.93 s\n",
"Wall time: 1.93 s\n"
"CPU times: user 1.77 s, sys: 21.7 ms, total: 1.79 s\n",
"Wall time: 1.79 s\n"
]
},
{
@@ -240,7 +241,7 @@
"99999989"
]
},
"execution_count": 5,
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
@@ -264,7 +265,7 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 15,
"id": "b90b5407-4666-4925-99d2-6a3a6b192fac",
"metadata": {},
"outputs": [],
@@ -275,7 +276,7 @@
" \"\"\"The largest prime that evenly divides n.\n",
" Find the smallest prime p that evenly divides n, \n",
" and return the maximum of p and the largest prime factor of n/p.\n",
" For prime n and for 1, return n.\"\"\"\n",
" If n is prime or if n = 1, this will return n.\"\"\"\n",
" for p in range(2, int(sqrt(n) + 1)): # <<<< only need to go up to √n\n",
" if n % p == 0: # n is composite\n",
" return max(p, largest_prime_factor(n // p))\n",
@@ -292,7 +293,7 @@
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": 16,
"id": "4026dc87-a0aa-4c75-b92a-96ec24cda1b7",
"metadata": {},
"outputs": [
@@ -302,7 +303,7 @@
"'all tests pass'"
]
},
"execution_count": 7,
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
@@ -321,7 +322,7 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 17,
"id": "d3d0c13e-5c01-4112-b372-60f7eb302d25",
"metadata": {},
"outputs": [
@@ -329,8 +330,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 238 μs, sys: 1 μs, total: 239 μs\n",
"Wall time: 241 μs\n"
"CPU times: user 209 μs, sys: 0 ns, total: 209 μs\n",
"Wall time: 210 μs\n"
]
},
{
@@ -339,7 +340,7 @@
"99999989"
]
},
"execution_count": 8,
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
@@ -353,14 +354,14 @@
"id": "82b008ea-f6b5-4bcd-8768-09c8dab089cb",
"metadata": {},
"source": [
"As advertised, this is about 10,000 times faster.\n",
"As predicted, this is about 10,000 times faster.\n",
"\n",
"We should be able to handle a 16-digit prime in about 2 seconds:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": 18,
"id": "9b6030ef-626a-4195-aedb-ef2edac65da4",
"metadata": {},
"outputs": [
@@ -368,8 +369,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 2.05 s, sys: 7.3 ms, total: 2.05 s\n",
"Wall time: 2.06 s\n"
"CPU times: user 2.15 s, sys: 22 ms, total: 2.17 s\n",
"Wall time: 2.17 s\n"
]
},
{
@@ -378,7 +379,7 @@
"9927935178558959"
]
},
"execution_count": 9,
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
@@ -395,14 +396,14 @@
"source": [
"## Imperative versus Declarative (or Functional) Style\n",
"\n",
"Our definition of largest_prime_factor mixed paradigms, using some imperative features (a for loop with a return in the middle) and some functional (an implementation of the equation `largest_prime_factor(n) = max(p, largest_prime_factor(n // p))`).\n",
"Our definition of largest_prime_factor mixed paradigms, using some [imperative](https://en.wikipedia.org/wiki/Imperative_programming) features (a for loop with a return in the middle) and some [functional](https://en.wikipedia.org/wiki/Functional_programming) features (an implementation of the equation `largest_prime_factor(n) = max(p, largest_prime_factor(n // p))`).\n",
"\n",
"Here's what it might look like if we leaned into the functional style more, making the equation more explicit:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": 19,
"id": "0308612c-6860-49b0-bcd6-856fa08133b1",
"metadata": {},
"outputs": [
@@ -412,7 +413,7 @@
"'all tests pass'"
]
},
"execution_count": 10,
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
@@ -422,7 +423,7 @@
" \"\"\"The largest prime that evenly divides n.\n",
" Find the smallest prime p that evenly divides n, \n",
" and return the maximum of p and the largest prime factor of n/p.\n",
" For prime n and for 1, return n.\"\"\"\n",
" If n is prime or if n = 1, this will return n.\"\"\"\n",
" p = smallest_prime_factor(n)\n",
" return 1 if n == 1 else max(p, largest_prime_factor(n // p))\n",
"\n",
@@ -443,7 +444,7 @@
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": 20,
"id": "b8907a8f-872f-4531-825c-fae9c70211c1",
"metadata": {},
"outputs": [
@@ -453,7 +454,7 @@
"'all tests pass'"
]
},
"execution_count": 13,
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
@@ -463,7 +464,7 @@
" \"\"\"The largest prime that evenly divides n.\n",
" Find the smallest prime p that evenly divides n, \n",
" and return the maximum of p and the largest prime factor of n/p.\n",
" For prime n and for 1, return n.\"\"\"\n",
" If n is prime or if n = 1, this will return n.\"\"\"\n",
" largest = 1\n",
" p = 2\n",
" while p * p <= n:\n",
@@ -487,9 +488,9 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python [conda env:base] *",
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "conda-base-py"
"name": "python3"
},
"language_info": {
"codemirror_mode": {