{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "[Oregon Curriculum Network](http://4dsolutions.net/ocn/)\n", "\n", "# The School of Tomorrow\n", "\n", "[Home Page](School_of_Tomorrow.ipynb)\n", "\n", "\"ramanujan1\"\n", "\n", "# Lambda Calc \n", "($\\lambda$ Calc vs $\\Delta$ Calc)\n", "\n", "In one of the shoptalks or namespaces around here, we get the proposal to bifurcate the math track through high school along what used to be called college prep and vocational lines. The vocational track had fallen out of vogue and gotten defunded, because higher education had become mandatory for most white collar and many blue collar professions. \n", "\n", "Meanwhile, computer science had proved relevant to society at all levels and many high schools were pushing to develop their computer science faculty, as distinct from the mathematics faculty, mirroring many colleges.\n", "\n", "The $\\Delta$- and $\\lambda$- calc bifurcation would keep everything mathematical, as computer technology needs to permeate even everyday math by osmosis. However some of the topics abandoned in the rush to delta calc (*the* calculus), could now be covered under the rubric of this other calculus. The original $\\lambda$-calc of Alonso Church & Co. would be included under the newer expanded domain, following subsequent branding down around $\\lambda$ in the computer field. " ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/jpeg": "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\n", "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.display import YouTubeVideo\n", "YouTubeVideo(\"eTDH7m4vEiM\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Number Theory\n", "\n", "Number Theory often begins with the Fundamental Theorem of Arithmetic: all positive integers may be distilled into a unique set of prime factors. If -1 is considered a prime factor, per [J.H. Conway's suggestion](https://groups.google.com/g/geometry.research/c/7pyFhAAye1E), then all of $Z$ (except 0) may be so distilled.\n", "\n", "Determining whether a number is really prime or not, and therefore whether it has factors, is a difficult problem. The unfactorability of large composites is at the basis of the Rivest Shamir Adelson (RSA) method of public key cryptography.\n", "\n", "The School of Tomorrow introduces number theory in steps, with a goal of making RSA comprehensible. To this end, some vocabulary is needed, most specifically: prime, composite, totatives, totient, coprime (stranger) and modulo arithmetic i.e. operations relative to some modulus.\n", "\n", "Python offers the modulo operator (%) and divmod as tools for doing modulo arithmetic." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Prime Versus Composite\n", "\n", "We start by distinguishing primes from composites in the positive integers, and then look at GCD and LCM, or Greatest Common Divisor and Lowest Common Multiple.\n", "\n", "Missing from many a high school math textbook in the late 1900s was Euclid's Method, often expressed recursively in lambda calculus, but not always." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "def gcd(a, b):\n", " while b:\n", " a, b = b, a % b\n", " return a" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "gcd(55, 20)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "def lcm(a, b):\n", " return (a * b) // gcd(a, b)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "24" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from functools import reduce\n", "reduce(lcm, (12, 24, 6))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Two positive integers with no prime factors in common, or in other words a GCD of just one, are said to be coprime, relatively prime, and/or strangers." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "def coprime(a, b):\n", " return True if gcd(a,b)==1 else False" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "coprime(200, 99)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "From [Futility Closet: More Prime Images](https://www.futilitycloset.com/2020/01/12/more-prime-images/)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "prime = int(\"\"\"\\\n", "53084469288402965415857953902888840109250315594591772197851275320\n", "59910735745658243457138160802170063601085186072703319516241231606\n", "86858731799078163479147444957979157038109676507221794134810159187\n", "99946828292780972255445123198357952762990102770564813212521111380\n", "68349356142222060588948481473772481328151681322128358047354205784\n", "70540373426870045719371801557904317944239925854314103160489406736\n", "99060594293236420918525997085793619098456109204165164418661475892\n", "01109662597018777150106134376006906212249382614768188594613749419\n", "81773446881694503562852062669737115544391406458301430146238093071\n", "02894114746014041621168186006763973309046545159248106457826024237\n", "26295585692705999572335711556642484343647905815411003310539537633\n", "41950800883057333667657184487306007957156203546941504909814030908\n", "34965188540308705963440466656812927154037805823279990648845960204\n", "63331562527077555356154644447566217362506777244670808476000607805\n", "03811498534406491478259767678703610171309197408223291080531370612\n", "62650405840051780819121599354652788179742394248611555080762986718\n", "96826790066089904275315943211982421764246751417927128802586925712\n", "27099955857542532516878558368313422620050604202219808465512659996\n", "23064148740328947837353070554937134618609926277437895029980245174\n", "01474719468068984349536087237870814923058804265001775440222136692\n", "19497268319149971553957338283899722324260346170316327132892172432\n", "93414823219221781561202067498414863282586486396494894086735311984\n", "87542808513750059732993808185407922249214024344950525276107816857\n", "04707717662079906664246810240363777462148167179131661698526525933\n", "27455038156208677911356439404008565505518270407112444336214476635\n", "90179341953108431111005767617305509479336875319574363889314007557\n", "80075653313610206913250864729950372237487765836958630210102788727\n", "36316538995288936776915812144955490067485142591851239438281782980\n", "49266403870939263057525714093639423600887115586024837895236645603\n", "39309565092104096166270212323904043359754209734891624081548291170\n", "80360665817900770688282037236785560524155682291636091743772117655\n", "59023604955032646389401878907537621901104165756011023874877122701\n", "96250964612099585830958920626319449976949804992786372992220222097\n", "60635584717392117583345925369515540556572166535535975903825177497\n", "033726681165539444448225642477607711558401523711\"\"\".replace(\"\\n\",\"\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You might need to change the scale of your browser window to see this Mercator clearly. It's 150 x 50 characters and is the binary expression of the above prime." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "mercator = bin(prime)[2:]\n", "def the_map():\n", " for i in range(50):\n", " pos = i * 150\n", " print(mercator[pos:pos + 150])\n", "# the_map()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\"binary_world\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Curriculum is Shaped By Political Concerns\n", "\n", "Because older generations are concerned with how younger generations are introduced to their culture, the process of hammering out a curriculum tends to involve political considerations.\n", "\n", "For example, to what extent was Number Theory purged from some curricula owing to [anti-German sentiment](https://ohiohistorycentral.org/w/Anti-German_Sentiment) and a wish to deprecate all things German? Too much Gauss would never do, and yet he was a Principal. Solution: spend more time on Euclidean Geometry instead. But did it have to be either / or?\n", "\n", "Sometimes our Notebook will be more of a springboard, a diving board, into a deep well or chasm (sounds dramatic). You may jump into Number Theory through Cryptography as well, and may wish to study them together. Indeed, what has brought Number Theory back into vogue, if it ever went away, is the ubiquity (omnipresence) of cryptography in our daily lives today.\n", "\n", "In practice the security layer, called TLS, provided by a web browser, may use eliptic curve cryptography instead of RSA. The public key system is the used to exchange symmetric keys for a faster encrypted connection.\n", "\n", "You'll want to learn about Fermat's Little Theorem, about totatives and totients, and about Diophantine Equations. Even earlier, let's start out with Euclid's Method for the GCD (greatest common divisor), as one of the earliest numeric algorithms out there.\n", "\n", "Links:\n", "\n", "* [Interview with Milo Gardner (November 24, 2011)](https://www.eimacs.com/blog/2011/11/milo-gardner-cryptanalyst-code-breaker/)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "image/jpeg": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAUDBA0NDxAPDRANDhANDhAODxAPDw0NEBAODQ0ODQ0NEBAPDRANDQ0ODQ0NDRUNDhESExMTDQ0WGBYSGBASExIBBQUFCAcIDwkJDxcTEhUWFRUXFRUXFhgVFRgVFRIXFRcVFhUWFRUXFRUXFRUXFRUVFRUVFRUVFRUVFRUVEhUVFf/AABEIAWgB4AMBIgACEQEDEQH/xAAdAAEAAgMBAQEBAAAAAAAAAAAABgcEBQgDAgEJ/8QAXhAAAgEDAgMFBQIFDQwHBwMFAQIDAAQREiEFEzEGByJBUQgUMmFxgZEjQlKhsQkVMzQ1U2Jyc5KzwdEXGCRUdIKTstPU4fAWQ5SVtNLxJTZVg6LCw2PE5EV1hKOk/8QAGwEBAAMBAQEBAAAAAAAAAAAAAAIDBAUBBgf/xAA6EQABBAEDAgUCBQMDAwQDAAABAAIDEQQSITEFQRMiUWFxBoEUMpGhsULR8CPB4RVi8TNSosIWJIL/2gAMAwEAAhEDEQA/AOMqUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURKUpREpSlESlKURK+4YyxAUEkkAADJJOwAA3JJ2xXxV0+zD2eR3luXAJi0xxZ3wzgl2+TBdKg+jtVGRMIYy89lu6bguzchsDTV9/QDclRjhPc7xGVdRjSLPQSuFb7VXUy/RgD8q1Xazu6vrNS8sWUHWSMiRR82x4kHllwBnHrVud8vejNZTCC3WPIQPIzgtu2dKKAwAwoBJOc6hjGN5Z3Udrf1xti8iKrKxikUbo3hByASTpZWxpJO4byrmHNyWM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ZXHZb1rcumJ1Cn1ByAfIjzBrbDs1BAkcqxYkTxapGZizYIyyHwjGQwBUbhetRmyvZNalTllIKjHn5EfP51OTwC4mBZxuwzhmYDPXfG32EVNrgTsvDYVccRu8sSXGScnJ3r7S5U+dWr2f7IxR4LxxhvPCqRn1yQT9tbz9a7dFJ0ggDJOBj656Dp5mpmIHuoa1TvA7GS4cLCNZz6gAfX5Ctb29ie1ZlJEmhgraeuWUMCMjcHOPXNT/AIr2lgJ0wqEJGkugCtjOQNXXGa010gmkKyiSTnqIzp06i4AWNiTgZDYJI3GM+VVx6LXpJq1zx2j7Xu2VTK4+yofdOS2evr9vX89Wz3/d3rWMqEsHMsepmGR4s6WG5PTyP09aqJF2xv1/RXaiDdPlWVxPdQWlKVYiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJW47Mdp7mzLNbSvEXADaceIDOMggg4ya1CHHzrO/XIfvcP81v/ADVF7GvGlwsehXjmhwpwsLI7S9prm7Ia5lklK5C6jsucZ0qMKucDOAM4Gelais79cB+9xfzT/wCah4gP3uL+a3/mo1oaKaKHoEa0NFDYLBpWceID97i/mn/zV43VzqA8KLj8kEZ+uSakvVj0pX6p+3/n5URflK+2cegH3/218URKUpREpSlEUz7pu8e64TPzYDqRsCWFvglT0P5Lj8WQbqfUFlPdfdr29tOKQCW3PoHjbGuNsZKMP0MNiNxmv5w1v+wfbC54dMJ7V9DDZgd0dfNHXI1KfsI6gggGqJYQ/ccqQdS7Z71ZBHNGFzhkJI6AHURt9cD7q1K8J5yddJU68/1YrnztF7QnELnBkiswVGAVjmB/PcH81ePCe/y/i3Edo38ZJj+icVhdiSXYVjZAF1l2BtoojqZCzH1IGB6gb9fWrNt+JqcDSV+41wrae0xxFBgQWHTGTHcZ/wDFeVZcPtU8VXpFYfbHcf71U24r2hDIDyu51kQ7bZqEd6faBEieBSObJgaRg6VyN2IPhz5L1rlH++s4rviKwBIIyI7gEZ8x/hWMjrUTXvvvslilqWJySUlJznP7/wCteSY8pFABA9vddDiEIBnqfIHzrZ2ClSrE/Bgj5Ebj7c4rmle/S+znl2h890m/29ZK9/8Af/vVmfqk/wDvFUx4L23an4oXQHtA3qXkUHLIaaLIZB10OoLH7GRdjudRrnvjnC2U7rpIOSPUDzrDn76bxm1cq1B+SS/7etfxXvSuJfiitvsWXz+sxrfE2Rm1KpxBUDpSlalWlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiJSlKIlKUoiUpSiL/9k=\n", "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.display import YouTubeVideo\n", "YouTubeVideo(\"X63MWZIN3gM\") " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Euclid's Method in More Detail\n", "\n", "I had you two lengths and ask you what size length in whole number size, will divide into both with no remainder. \n", "\n", "Start with the two lengths also being whole number. Everything in this picture is an integer, a positive integer, a length. \n", "\n", "What integer length divides evenly into these two? Clearly 1 does, as 1 divides into everything. How about 2? How about 3? What's the greatest number that divides them both, without remainder?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Well, what if the smaller length already divides the larger into two. If we call them A and B and divide A into B, not knowing which is longer, then if A is longer, it won't go into B at all. If it does, does it go just once? If so, we're done, and A is the GCD. Otherwise, last possibility, there's some remainder.\n", "\n", "That remainder then, is the next shorter length of interest. If there's a GCD > 1, it will divide both of these, as if it does, it will also divide into B, which consists of N As + R for remainder. So make R the new A, and B the new longest length, what used to be A." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(4, 0)" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "N, R = divmod(12, 3) # how many times goes in N, what remainder R\n", "(N, R)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(0, 3)" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "divmod(3, 12) # 12 doesn't go into 3, 3 is left" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here's a recursive solution, based on the description above:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "def GCD(A, B):\n", " N, R = divmod(B, A) # bigger by smaller?\n", " if N == 0: # if not\n", " return GCD(B, A) # then switch\n", " elif R == 0:\n", " return A # if no remainder, we're done\n", " elif R == 1:\n", " return 1 # down to 1, nowhere to go so 1\n", " elif R > 0:\n", " return GCD(R, B) # keep drilling down" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "10" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "GCD(100, 30)" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "9" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "GCD(81, 18)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "However Guido came up with a more brilliant, non-recursive solution, that automatically switches the arguments if a > b:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "18" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "18 % 81 # 81 doesn't go into 18, 18 remains" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "9\n", "(4, 9)\n" ] } ], "source": [ "print(81 % 18) # 18 goes into 81 4 times, remainder 9\n", "print(divmod(81, 18))" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "12" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "12 % 24 # 24 doesn't go into 12, 12 is the remainder" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "def gcd(a, b):\n", " while b:\n", " b, a = a % b, b\n", " return a" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "9" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "gcd(18, 81)" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "10" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "gcd(100, 30)" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "gcd(12, 3)" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "gcd(3, 12)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, how about the Lowest Common Multiple or LCM. That turns out to be the product of A and B (all factors combined) divided by the GCD (all factors common to both)." ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "def lcm(a, b):\n", " return int((a * b)/gcd(a, b))" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "99" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "lcm(11, 9)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If two positive integers have no factors in common other than 1, they're considered \"co-prime\" to one another or, more colorfully, they're considered \"strangers\".\n", "\n", "All numbers < N that are coprime to N are called \"totatives on N\" and the number of such totivatives is considered \"the totient of N\". Lets do some Python." ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 5, 7, 11]" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def totatives(N):\n", " return [totative for totative in range(1, N) if gcd(N, totative)==1]\n", "\n", "totatives(12)" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [], "source": [ "def 𝜙(N):\n", " # the totient function was called 𝜙 or \"phi\" by Euler\n", " return len(totatives(N))" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "40" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "𝜙(100)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Euler's Totient Theorem \n", "\n", "If ${a}$ is an integer and $m$ is a positive integer relatively prime to $a$,Then ${a}^{\\phi (m)}\\equiv 1 \\pmod {m}$." ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'1, 3, 7, 9, 11, 13, 17, 19, 21, 23, 27, 29, 31, 33, 37, 39, 41, 43, 47, 49, 51, 53, 57, 59, 61, 63, 67, 69, 71, 73, 77, 79, 81, 83, 87, 89, 91, 93, 97, 99, 101, 103, 107, 109, 111, 113, 117, 119, 121, 123, 127, 129, 131, 133, 137, 139, 141, 143, 147, 149, 151, 153, 157, 159, 161, 163, 167, 169, 171, 173, 177, 179, 181, 183, 187, 189, 191, 193, 197, 199, 201, 203, 207, 209, 211, 213, 217, 219, 221, 223, 227, 229, 231, 233, 237, 239, 241, 243, 247, 249, 251, 253, 257, 259, 261, 263, 267, 269, 271, 273, 277, 279, 281, 283, 287, 289, 291, 293, 297, 299, 301, 303, 307, 309, 311, 313, 317, 319, 321, 323, 327, 329, 331, 333, 337, 339, 341, 343, 347, 349, 351, 353, 357, 359, 361, 363, 367, 369, 371, 373, 377, 379, 381, 383, 387, 389, 391, 393, 397, 399, 401, 403, 407, 409, 411, 413, 417, 419, 421, 423, 427, 429, 431, 433, 437, 439, 441, 443, 447, 449, 451, 453, 457, 459, 461, 463, 467, 469, 471, 473, 477, 479, 481, 483, 487, 489, 491, 493, 497, 499, 501, 503, 507, 509, 511, 513, 517, 519, 521, 523, 527, 529, 531, 533, 537, 539, 541, 543, 547, 549, 551, 553, 557, 559, 561, 563, 567, 569, 571, 573, 577, 579, 581, 583, 587, 589, 591, 593, 597, 599, 601, 603, 607, 609, 611, 613, 617, 619, 621, 623, 627, 629, 631, 633, 637, 639, 641, 643, 647, 649, 651, 653, 657, 659, 661, 663, 667, 669, 671, 673, 677, 679, 681, 683, 687, 689, 691, 693, 697, 699, 701, 703, 707, 709, 711, 713, 717, 719, 721, 723, 727, 729, 731, 733, 737, 739, 741, 743, 747, 749, 751, 753, 757, 759, 761, 763, 767, 769, 771, 773, 777, 779, 781, 783, 787, 789, 791, 793, 797, 799, 801, 803, 807, 809, 811, 813, 817, 819, 821, 823, 827, 829, 831, 833, 837, 839, 841, 843, 847, 849, 851, 853, 857, 859, 861, 863, 867, 869, 871, 873, 877, 879, 881, 883, 887, 889, 891, 893, 897, 899, 901, 903, 907, 909, 911, 913, 917, 919, 921, 923, 927, 929, 931, 933, 937, 939, 941, 943, 947, 949, 951, 953, 957, 959, 961, 963, 967, 969, 971, 973, 977, 979, 981, 983, 987, 989, 991, 993, 997, 999'" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "\", \".join(map(str, totatives(1000)))" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m = 1000\n", "pow(7, 𝜙(m), m) # m % 7 ** 𝜙(m)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Given public key N:\n", "\n", "$$ \\gcd(p, q) = 1 $$\n", "$$ N = pq $$\n", "\n", "and a number $e$ with inverse $d$ (secret), modulo $\\phi(N)$, such that:\n", "\n", "$$ ed \\equiv 1 \\pmod{\\phi(N)}$$\n", "\n", "--------------------\n", "Encryption:\n", "$$ c \\equiv m^e \\pmod{N}$$\n", "Decryption:\n", "$$ m^\\prime \\equiv c^d \\pmod{N} $$\n", "$$ m^\\prime \\equiv (m^e)^d \\equiv m^{ed} \\pmod{N} $$\n", "\n", "Is it true that $m^\\prime \\equiv m$?\n", "\n", "Thanks to Euler's Theorem:\n", "\n", "$$ a^{\\phi(N)} \\equiv 1 \\pmod{N}, \\text{ if } \\gcd(a,N) = 1. $$\n", "\n", "Write $ed = 1 + k~\\phi(N)$:\n", "$$ m^\\prime \\equiv m^{1+k\\phi(N)} \\pmod{N}$$\n", "$$ m^\\prime \\equiv m\\cdot m^{k\\phi(N)} \\pmod{N}$$\n", "$$ m^\\prime \\equiv m\\cdot \\underbrace{m^{k\\phi(N)}}_{1} \\pmod{N}$$\n", "\n", "So $m^\\prime \\equiv m \\pmod{N}$.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Links:\n", "\n", "* [Chapter 5: Discovering Math with Python](https://nbviewer.jupyter.org/github/4dsolutions/Python5/blob/master/Public%20Key%20Cryptography.ipynb)\n", "* [Camp Crypto](https://mybizmo.blogspot.com/2019/04/camp-crypto.html)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Defining Type Q: The Rational Number Type\n", "\n", "We can use that to define a Fraction, or rational number (Rat). Our adventures in Python's object oriented model might, in fact, begin here, even though Python's standard library already includes a Fraction class in fraction. Our tests might compare their behaviors." ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [], "source": [ "from fractions import Fraction" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the Rational Number or alternative fraction class below, we make use of the ```gcd``` and ```lcm``` functions defined above.\n", "\n", "If you haven't looked at Python a lot, you may miss some of what's going on: Python's special names define the guts of a fraction [in terms of its operations](https://docs.python.org/3/library/operator.html). \n", "\n", "When you add two fractions, what happens? A lowest common multiple makes for a denominator. Given the initialization process reduces the fraction to lowest terms, just multiplying the two denominators together would also work.\n", "\n", "Complexity arises when we let integers play with Rationals, which we should, as they're a subset of same. $N \\subset Z \\subset Q \\subset R \\subset C$ as we say." ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [], "source": [ "from __future__ import annotations\n", "from functools import total_ordering\n", "from typing import Union\n", "\n", "@total_ordering\n", "class Rat:\n", " \n", " def __init__(self, n, d=None):\n", " \n", " if type(d) is None:\n", " d = 1\n", " if d == 0:\n", " raise ZeroDivisionError\n", " \n", " _gcd = gcd(n, d)\n", " self.numer = n//_gcd\n", " self.denom = d//_gcd\n", " \n", " def _convert(self, other: int) -> Rat:\n", " if type(other) is int:\n", " return Rat(other, 1)\n", " elif type(other) is Rat:\n", " return other\n", " else:\n", " raise TypeError(\"Not int or Rat\")\n", " \n", " def __repr__(self):\n", " return \"(%s/%s)\" % (self.numer, self.denom)\n", " \n", " def __eq__(self, other: Union[int, Rat]) -> bool:\n", " other = self._convert(other)\n", " return ((self.numer == other.numer) \n", " and (self.denom == other.denom))\n", " \n", " def __gt__(self, other: Union[int, Rat]) -> bool:\n", " other = self._convert(other)\n", " _lcm = lcm(self.denom, other.denom)\n", " return ((self.numer * _lcm//self.denom) \n", " > (other.numer * _lcm//other.denom))\n", " \n", " def __add__(self, other: Union[int, Rat]) -> Rat:\n", " # get an lcm before adding\n", " other = self._convert(other)\n", " _lcm = lcm(self.denom, other.denom)\n", " return Rat(self.numer * _lcm//self.denom\n", " + other.numer * _lcm//other.denom, \n", " _lcm) # denominator\n", " \n", " def __sub__(self, other: Union[int, Rat]) -> Rat:\n", " # add the additive inverse of other\n", " other = self._convert(other)\n", " return self + (-other)\n", " \n", " def __neg__(self) -> Rat:\n", " # return the additive inverse of self\n", " return Rat(-self.numer, self.denom)\n", " \n", " def __mul__(self, other: Union[int, Rat]) -> Rat:\n", " # multiply two rationals\n", " other = self._convert(other)\n", " return Rat(self.numer * other.numer, \n", " self.denom * other.denom)\n", " \n", " def __truediv__(self, other: Union[int, Rat]) -> Rat:\n", " # multiply by the multiplicative inverse of other\n", " other = self._convert(other)\n", " return self * other**(-1)\n", " \n", " def __pow__(self, n : int) -> Rat:\n", " # raise self to the nth power\n", " if n < 0:\n", " n = abs(n)\n", " return Rat(self.denom ** n, self.numer ** n)\n", " return Rat(self.numer ** n, self.denom ** n)\n", " \n", " \n", " __rmul__ = __mul__\n", " __radd__ = __add__\n", " __rtruediv__ = __truediv__" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lets approach our development challenge by means of unittests." ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [], "source": [ "from unittest import TestCase\n", "import unittest\n", "\n", "class TestRat(TestCase):\n", " \n", " def test_1(self):\n", " p = Rat(1, 3)\n", " q = Rat(2, 3)\n", " self.assertEqual(p + q, 1)\n", " \n", " def test_2(self):\n", " fp = Fraction(16,32)\n", " fq = Fraction(18,56)\n", " p = Rat(16,32)\n", " q = Rat(18,56)\n", " fproduct = fp * fq\n", " product = p * q\n", " self.assertEqual(fproduct.numerator, product.numer)\n", " self.assertEqual(fproduct.denominator, product.denom)\n", " \n", " def test_3(self):\n", " p = Rat(16,32)\n", " q = Rat(18,56)\n", " result = p - q\n", " fp = Fraction(16,32)\n", " fq = Fraction(18,56)\n", " fresult = fp - fq\n", " self.assertEqual(fresult.numerator, result.numer)\n", " self.assertEqual(fresult.denominator, result.denom) \n", " \n", " def test_4(self):\n", " p = Rat(2,3)\n", " q = Rat(3,4)\n", " self.assertTrue(q > p)\n", " self.assertTrue(p <= q) " ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(17/12)" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p = Rat(2,3)\n", "q = Rat(3,4)\n", "p + q" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "test_1 (__main__.TestRat) ... ok\n", "test_2 (__main__.TestRat) ... ok\n", "test_3 (__main__.TestRat) ... ok\n", "test_4 (__main__.TestRat) ... ok\n", "\n", "----------------------------------------------------------------------\n", "Ran 4 tests in 0.032s\n", "\n", "OK\n" ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "unittest.main(argv=[''], verbosity=3, exit=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## RAMANUJAN\n", "\n", "\\begin{equation*}\n", "\\frac{1}{\\Bigl(\\sqrt{\\phi \\sqrt{5}}-\\phi\\Bigr) e^{\\frac25 \\pi}} =\n", "1+\\frac{e^{-2\\pi}} {1+\\frac{e^{-4\\pi}} {1+\\frac{e^{-6\\pi}}\n", "{1+\\frac{e^{-8\\pi}} {1+\\ldots} } } }\n", "\\end{equation*}" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "gmpy\n", "1.001867436219318606077227680424157087122424127427497054500130190210949798909562825712938250353099963\n", "1.001867436219318606077227680424157087122424127427497054500130190210949798909562825712938250353099963\n", "Ta daa!\n" ] } ], "source": [ "# %load genius_identity.py\n", "#!/usr/bin/env python3\n", "\"\"\"\n", "Created on Mon Jun 8 17:48:56 2020\n", "\n", "@author: Kirby Urner\n", "\n", "Verifying a Ramanujan Identity\n", "https://flic.kr/p/2j9NcAd\n", "\n", "Keywords: recursion, number theory, arbitrary precision\n", "\n", "School of Tomorrow\n", "https://medium.com/@kirbyurner/calculator-of-tomorrow-using-arbitrary-precision-8f219b0092d9\n", "https://repl.it/@kurner/RamanujanIdentity01\n", "\"\"\"\n", "\n", "import mpmath\n", "from mpmath import e, pi\n", "print(mpmath.libmp.BACKEND)\n", "mpmath.mp.dps = 100\n", "two = mpmath.mpf('2')\n", "five = mpmath.mpf('5')\n", "root5 = mpmath.mpf('5').sqrt()\n", "phi = (1 + root5)/2\n", "\n", "term = \"(1 + (e ** (-2*{} * pi))/{})\"\n", "\n", "def cont_frac(n, c=1):\n", " \"\"\"\n", " Recursively build the continued fraction, \n", " as a string, to level of depth n\n", " \"\"\"\n", " if n==0:\n", " return \"1\"\n", " else: \n", " return \"(1 + ((e ** (-2*{} * pi)/{})))\".format(c, cont_frac(n-1, c+1))\n", "\n", "print(eval(cont_frac(10))) # evaluate the continued fraction\n", "print(1/(((phi * root5).sqrt() - phi) * e ** (two/five * pi))) # left side of the equation\n", "print(\"Ta daa!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Magic Squares\n", "\n", "* [Futility Closet: Time Well Spent](https://www.futilitycloset.com/2010/08/14/time-well-spent/)\n", "* [Tue N. Vu, 27x27 Magic Square, 9/11/13, from Series Math Study Resource.](http://seriesmathstudy.com/sms/content/27x27-magic-square)" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(9,)" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import numpy as np\n", "magic_square = np.zeros((9,), dtype=np.int32)\n", "magic_square.shape" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[2, 7, 6],\n", " [9, 5, 1],\n", " [4, 3, 8]], dtype=int32)" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "magic_square[:] = 2,7,6,9,5,1,4,3,8\n", "magic_square = magic_square.reshape((3,3))\n", "magic_square" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[15, 15, 15]" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[magic_square[:,column].sum() for column in range(0,3)]" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[15, 15, 15]" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[magic_square[row,:].sum() for row in range(0,3)]" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "15" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "magic_square.diagonal().sum()" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "15" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.diag(np.fliplr(magic_square)).sum()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Magic Cubes\n", "\n", "* [Order 9](http://www.magic-squares.net/c-t-htm/c_cube-9.htm)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Sudoku\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "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.7.9" } }, "nbformat": 4, "nbformat_minor": 4 }