{ "cells": [ { "cell_type": "code", "execution_count": 3, "id": "c601dd6f", "metadata": {}, "outputs": [], "source": [ "# precondition: x is a list of natural numbers, y is a natural number.\n", "#\n", "# if any a + b = y exist such that a and b are both elements of x, where a != b,\n", "# the function returns [a, b]; if none such a and b exist, the empty set is returned.\n", "#\n", "# the content of the list object from the calling method may not be altered.\n", "#\n", "# note: this is done with a list only for demonstration purposes;\n", "# normally, among the data structures form Python, we would preferably use a set.\n", "#\n", "def natmatch_iter(x, y):\n", " for i in range(len(x)):\n", " for j in range(i+1, len(x)):\n", " if (x[i]+x[j] == y) and (x[i] != x[j]):\n", " return [x[i], x[j]]\n", " return []\n", "\n", "def natmatch_iter_debug(x, y):\n", " print(\"breakpoint S0: x = \", x, \", y = \", y, sep='')\n", " input()\n", " for i in range(len(x)):\n", " for j in range(i+1, len(x)):\n", " if (x[i]+x[j] == y) and (x[i] != x[j]):\n", " print(\"breakpoint S7: match found, returning; i = \", i, \", j = \", j, \\\n", " \", x[i] = \", x[i], \", x[j] = \", x[j], \", x[i] + x[j] = \", x[i]+x[j], sep='')\n", " input()\n", " return [x[i], x[j]]\n", " else:\n", " print(\"breakpoint S8: no match so far, including for i = \", i, \", j = \", j, \\\n", " \", x[i] = \", x[i], \", x[j] = \", x[j], \", x[i] + x[j] = \", x[i]+x[j], sep='')\n", " input()\n", " print(\"breakpoint S3: no match found; returning\")\n", " input()\n", " return [] " ] }, { "cell_type": "code", "execution_count": 4, "id": "fd523554", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "List x = [16, 13, 18, 23, 20] where y = 25\n", "breakpoint S0: x = [16, 13, 18, 23, 20], y = 25\n", "\n", "breakpoint S8: no match so far, including for i = 0, j = 1, x[i] = 16, x[j] = 13, x[i] + x[j] = 29\n", "\n", "breakpoint S8: no match so far, including for i = 0, j = 2, x[i] = 16, x[j] = 18, x[i] + x[j] = 34\n", "\n", "breakpoint S8: no match so far, including for i = 0, j = 3, x[i] = 16, x[j] = 23, x[i] + x[j] = 39\n", "\n", "breakpoint S8: no match so far, including for i = 0, j = 4, x[i] = 16, x[j] = 20, x[i] + x[j] = 36\n", "\n", "breakpoint S8: no match so far, including for i = 1, j = 2, x[i] = 13, x[j] = 18, x[i] + x[j] = 31\n", "\n", "breakpoint S8: no match so far, including for i = 1, j = 3, x[i] = 13, x[j] = 23, x[i] + x[j] = 36\n", "\n", "breakpoint S8: no match so far, including for i = 1, j = 4, x[i] = 13, x[j] = 20, x[i] + x[j] = 33\n", "\n", "breakpoint S8: no match so far, including for i = 2, j = 3, x[i] = 18, x[j] = 23, x[i] + x[j] = 41\n", "\n", "breakpoint S8: no match so far, including for i = 2, j = 4, x[i] = 18, x[j] = 20, x[i] + x[j] = 38\n", "\n", "breakpoint S8: no match so far, including for i = 3, j = 4, x[i] = 23, x[j] = 20, x[i] + x[j] = 43\n", "\n", "breakpoint S3: no match found; returning\n", "\n", "Return value obtained as []\n" ] } ], "source": [ "import random\n", "\n", "k = 5\n", "\n", "random.seed()\n", "x = [random.randrange(k*k) for j in range(k)]\n", "print(\"List x =\", x, \"where y =\", k*k)\n", "print(\"Return value obtained as\", natmatch_iter_debug(x, k*k))" ] }, { "cell_type": "code", "execution_count": 9, "id": "79e0aa5a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "50\t0.48\n", "100\t0.41\n", "150\t0.38\n", "200\t0.375\n", "250\t0.38\n", "300\t0.39\n", "350\t0.38\n", "400\t0.375\n", "450\t0.38\n", "500\t0.386\n", "550\t0.387273\n", "600\t0.391667\n", "650\t0.396923\n", "700\t0.398571\n", "750\t0.397333\n", "800\t0.405\n", "850\t0.403529\n", "900\t0.398889\n", "950\t0.401053\n", "1000\t0.403\n", "fraction of length k lists with a match adding up to k squared: 0.403\n" ] } ], "source": [ "import random\n", "\n", "k = 5000\n", "repetitions = 1000\n", "\n", "matches_iter = 0\n", "for i in range(repetitions):\n", " k_input = [random.randrange(k*k) for j in range(k)]\n", " if len(natmatch_iter(k_input, k*k)) > 1:\n", " matches_iter += 1\n", " if (i+1) % (repetitions // 20) == 0:\n", " print(i + 1, round(matches_iter / (i+1), 6), sep=\"\\t\")\n", "\n", "# challenge: find the value of this quantity for large k\n", "#\n", "print(\"fraction of length k lists with a match adding up to k squared:\", matches_iter/repetitions)" ] }, { "cell_type": "code", "execution_count": 18, "id": "1de6e016", "metadata": {}, "outputs": [], "source": [ "# precondition: x is a list of integers, y is a single-digit integer between 0 and 9\n", "# postcondition: return [q1, q2, q3] as specified in the lecture\n", "#\n", "# challenge: create a more efficient function that solves the same problem\n", "#\n", "def mod10_count_naive(x, y):\n", " q1, q2, q3 = 0, 0, 0\n", " for i in range(len(x)):\n", " if x[i] % 10 == y:\n", " q1 += 1\n", " for j in range(len(x)):\n", " if i == j:\n", " continue\n", " elif (x[i]*x[j]) % 10 == y:\n", " q2 += 1\n", " for k in range(len(x)):\n", " if i == k or j == k:\n", " continue\n", " elif (x[i]*x[j]*x[k]) % 10 == y:\n", " q3 += 1\n", " return [q1, q2, q3]" ] }, { "cell_type": "code", "execution_count": 21, "id": "100529f5", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "List x = [24, 8, 19, 8, 2] where y = 4\n", "Return value obtained as [q1, q2, q3] = [1, 2, 24]\n" ] } ], "source": [ "import random\n", "\n", "k = 5\n", "\n", "random.seed()\n", "x = [random.randrange(k*k) for j in range(k)]\n", "y = random.randrange(10)\n", "\n", "print(\"List x =\", x, \"where y =\", y)\n", "print(\"Return value obtained as [q1, q2, q3] =\", mod10_count_naive(x, y))" ] }, { "cell_type": "code", "execution_count": 12, "id": "353f2fdf", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\t9.5367431640625e-07\n", "2\t3.4928321838378907e-06\n", "4\t1.5103816986083985e-05\n", "6\t4.7647953033447264e-05\n", "8\t0.00010575056076049805\n", "10\t0.00016651153564453124\n", "12\t0.00025377273559570315\n", "14\t0.00041273832321166994\n", "16\t0.0005746960639953613\n", "18\t0.0008049845695495605\n", "20\t0.0011807322502136231\n", "22\t0.0015154004096984864\n", "24\t0.001899862289428711\n", "26\t0.0023062944412231444\n", "28\t0.002781796455383301\n", "30\t0.003397035598754883\n", "32\t0.0044381141662597655\n", "34\t0.0049473166465759276\n", "36\t0.0059199690818786625\n", "38\t0.007124781608581543\n", "40\t0.008204948902130128\n", "42\t0.009437751770019532\n", "44\t0.011912238597869874\n", "46\t0.013664722442626953\n", "48\t0.015797066688537597\n", "50\t0.017937052249908447\n", "52\t0.01964545249938965\n", "54\t0.020915377140045165\n", "56\t0.023358488082885744\n", "58\t0.02586294412612915\n", "60\t0.028313446044921874\n", "62\t0.030790185928344725\n", "64\t0.03576785326004028\n", "66\t0.03951317071914673\n", "68\t0.041276729106903075\n", "70\t0.04627230167388916\n", "72\t0.05012154579162598\n", "74\t0.054620134830474856\n", "76\t0.06190111637115479\n", "78\t0.06557252407073974\n", "80\t0.06676410436630249\n", "82\t0.07315609455108643\n", "84\t0.08296858072280884\n", "86\t0.0843926191329956\n", "88\t0.08983358144760131\n", "90\t0.09320390224456787\n", "92\t0.10385820865631104\n", "94\t0.10812110900878906\n", "96\t0.11717798709869384\n", "98\t0.12154171466827393\n", "100\t0.12585008144378662\n", "102\t0.13931398391723632\n", "104\t0.14722951650619506\n", "106\t0.15211163759231566\n", "108\t0.1631190299987793\n", "110\t0.1754698395729065\n", "112\t0.18486316204071046\n", "114\t0.20014564990997313\n", "116\t0.20863407850265503\n", "118\t0.21899917125701904\n", "120\t0.22838568687438965\n", "122\t0.2372503399848938\n", "124\t0.24869710206985474\n", "126\t0.26082031726837157\n", "128\t0.26672853231430055\n", "130\t0.29371817111968995\n", "132\t0.2973006248474121\n", "134\t0.32195124626159666\n", "136\t0.33127418756484983\n", "138\t0.35492147207260133\n", "140\t0.3841936945915222\n", "142\t0.3901970624923706\n", "144\t0.3864531874656677\n", "146\t0.39739433526992796\n", "148\t0.41666375398635863\n", "150\t0.44275245666503904\n", "152\t0.46015899181365966\n", "154\t0.47617594003677366\n", "156\t0.49427716732025145\n", "158\t0.5104174971580505\n", "160\t0.5335351467132569\n", "162\t0.5581546902656556\n", "164\t0.5841298341751099\n", "166\t0.6039108157157898\n", "168\t0.6163124799728393\n", "170\t0.6301173806190491\n", "172\t0.6461889147758484\n", "174\t0.6756220459938049\n", "176\t0.7013526201248169\n", "178\t0.7234141945838928\n", "180\t0.7442171573638916\n", "182\t0.7719490647315979\n", "184\t0.8003442287445068\n", "186\t0.826941454410553\n", "188\t0.8565832853317261\n", "190\t0.8878767490386963\n", "192\t0.9223721623420715\n", "194\t0.9497387290000916\n", "196\t0.976621150970459\n", "198\t1.0238276839256286\n", "200\t1.0545471429824829\n" ] } ], "source": [ "import time\n", "import random\n", "\n", "step = 2\n", "kmax = 200\n", "repetitions = 20\n", "\n", "perf_iter = {}\n", "random.seed()\n", "\n", "for k in range(0, kmax+1, step):\n", " time_measurement = 0\n", " for i in range(repetitions):\n", " x = [random.randrange(k*k) for j in range(k)]\n", " y = random.randrange(10)\n", " start = time.time()\n", " mod10_count_naive(x, y)\n", " end = time.time()\n", " time_measurement += end-start\n", " perf_iter[k] = time_measurement/repetitions\n", " \n", " print(k, perf_iter[k], sep='\\t')" ] }, { "cell_type": "code", "execution_count": 14, "id": "e477dc28", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "import seaborn as sbn\n", "import matplotlib.pyplot as plt\n", "\n", "keylist_iter = list(perf_iter.keys())\n", "vallist_iter = list(perf_iter.values())\n", "\n", "fig, ax = plt.subplots()\n", "fig.set_size_inches(15, 9)\n", "plt.xticks(fontsize=18, color=\"#322300\")\n", "plt.yticks(fontsize=18, color=\"#322300\")\n", "ax.set_xlabel(\"input list size\", fontsize=24, color=\"#322300\")\n", "ax.set_ylabel(\"average runtime in seconds\", fontsize=24, color=\"#322300\")\n", "\n", "# show the data as a regression plot with a cubic fit (order = 3)\n", "#\n", "sbn.regplot(x=keylist_iter, y=vallist_iter, color='#002855', order=3)" ] }, { "cell_type": "code", "execution_count": 15, "id": "c03fa90c", "metadata": {}, "outputs": [], "source": [ "# list with n = 200 elements for performance testing\n", "#\n", "x200 = [20674, 11633, 8618, 3966, 6885, 15989, 32051, 9792, 30817, 23417, 1420, 39408, 8908, 39007, 31282, 22764, 19111, 14656, 20658, 3213, 34768, 32452, 9808, 13885, 32611, 5376, 20146, 2432, 39805, 31476, 22245, 35263, 1121, 9315, 6339, 24362, 21272, 16485, 6129, 21197, 36781, 15168, 36069, 13612, 5327, 16078, 39047, 23158, 14039, 31705, 23125, 11679, 39477, 5429, 16166, 21403, 11773, 317, 10817, 17070, 15397, 17240, 16015, 37777, 25007, 29084, 19545, 5219, 9830, 763, 12718, 21327, 31619, 32982, 33681, 19686, 13799, 22386, 9049, 32294, 23339, 11682, 28712, 14777, 33012, 24047, 13255, 37662, 37118, 11836, 36578, 11884, 22617, 6784, 19248, 33797, 2844, 19525, 10358, 25964, 7133, 4701, 35483, 37107, 30512, 9479, 31821, 38829, 14446, 16455, 9181, 38693, 37374, 28439, 1886, 21768, 34728, 6066, 22346, 264, 18495, 32083, 27651, 914, 20122, 37, 10277, 27546, 1678, 35704, 12747, 92, 10035, 16245, 24834, 28993, 38, 30773, 37294, 12121, 29464, 29437, 36314, 7102, 17136, 24754, 10778, 28326, 36576, 20562, 31742, 15229, 14213, 3736, 33775, 36094, 30970, 2059, 32205, 35793, 10357, 33123, 5496, 22560, 5876, 37680, 26200, 10193, 16057, 33859, 2019, 8539, 2416, 4439, 15279, 29905, 31335, 1344, 36215, 23618, 27207, 5417, 29735, 16258, 12045, 31127, 14090, 34355, 36555, 31805, 27363, 32230, 20689, 35049, 28937, 29870, 22063, 27636, 2873, 350]\n", "\n", "# list with n = 1000 elements for performance testing\n", "#\n", "x1000 = [759099, 176511, 874067, 486800, 490790, 229090, 570416, 331257, 701444, 191680, 119764, 380964, 890150, 90470, 317716, 706443, 598320, 504176, 929737, 236176, 889040, 999867, 496044, 245955, 811768, 290297, 842831, 473391, 529440, 364150, 150346, 786022, 936686, 85956, 225036, 497692, 566283, 872184, 818759, 550966, 413003, 382362, 794689, 446478, 633368, 921631, 885103, 711119, 803204, 714347, 673581, 619801, 725482, 904452, 894959, 469185, 80225, 455345, 13718, 931809, 438982, 662770, 478419, 998034, 639388, 791859, 583323, 861558, 244054, 577355, 211591, 218649, 552854, 884265, 424349, 301941, 980615, 842425, 891345, 771404, 868792, 488988, 430810, 97922, 321840, 660009, 360610, 896948, 362319, 687654, 558715, 16304, 530727, 409156, 121934, 191371, 498379, 71028, 830212, 934206, 622838, 610736, 275275, 1871, 671872, 52303, 275955, 553532, 578100, 2818, 968830, 253758, 574496, 612976, 560563, 967641, 259768, 545596, 178670, 556426, 168498, 842436, 989120, 220198, 852554, 382081, 353389, 254514, 292814, 136001, 87682, 222951, 844958, 830154, 72844, 783419, 636148, 290558, 187632, 168559, 872390, 504847, 376992, 997954, 621205, 10817, 985640, 444056, 396000, 40441, 69814, 746935, 307509, 488654, 631092, 276594, 599897, 565826, 846047, 435967, 922650, 104363, 947298, 814558, 103425, 205872, 682663, 853982, 111231, 76009, 633745, 204089, 728524, 908650, 343304, 803121, 70611, 743173, 767787, 384393, 407468, 869230, 240575, 39137, 261583, 846827, 318814, 672609, 373456, 590178, 667032, 456403, 642961, 394678, 381537, 984069, 118630, 230806, 380466, 396880, 678223, 664987, 234591, 702672, 175088, 62202, 960929, 193088, 261832, 614494, 570144, 354305, 952236, 193536, 508172, 672419, 694551, 282607, 879348, 719629, 402784, 834430, 106205, 621520, 823857, 611024, 95101, 550271, 273161, 298493, 546506, 128860, 203164, 675411, 549768, 809270, 910851, 262130, 697081, 756648, 745736, 43535, 600087, 63979, 893888, 447262, 605306, 384093, 711257, 515357, 815134, 355344, 80146, 903859, 577909, 579012, 600633, 979217, 614228, 450852, 206144, 935175, 442220, 615608, 186591, 290065, 99431, 230095, 216445, 699614, 777932, 412126, 216529, 139979, 866260, 929838, 79458, 454532, 399462, 224694, 691781, 231709, 595974, 837595, 777697, 157141, 62806, 437022, 568172, 154078, 433667, 702151, 588069, 997599, 427947, 554039, 650003, 388182, 84871, 228772, 189137, 983525, 47771, 737424, 597345, 552426, 597134, 822356, 547223, 413741, 623328, 434399, 342550, 285059, 758789, 917646, 32244, 673447, 634752, 716229, 267264, 612989, 221683, 729129, 718098, 989923, 443507, 56899, 821179, 316735, 148720, 313688, 829608, 408613, 721487, 280808, 694541, 192774, 716972, 864473, 548778, 835479, 314128, 877210, 896329, 316522, 434457, 863520, 302811, 855764, 968508, 727447, 94936, 435499, 369354, 626743, 899770, 927037, 627951, 42823, 571781, 516003, 659966, 679961, 97140, 840204, 918295, 990028, 609716, 295569, 565580, 291275, 813792, 628098, 264109, 304238, 734361, 633898, 991534, 31063, 651691, 180972, 582103, 634993, 218079, 996535, 474079, 439419, 842426, 680657, 437320, 17932, 808550, 826145, 308259, 769410, 317087, 107175, 253447, 52629, 33247, 48037, 5185, 690650, 60156, 528860, 109676, 759769, 788781, 890473, 572819, 972913, 86113, 324565, 657662, 397037, 69552, 923247, 321156, 180625, 612294, 987109, 490956, 188793, 873104, 34832, 440259, 361574, 163314, 90547, 616227, 655353, 653350, 557012, 195506, 351331, 22962, 118970, 854950, 420532, 274304, 664365, 762960, 150246, 265220, 684471, 717729, 725489, 969122, 644360, 232242, 103144, 532958, 153175, 366685, 937552, 58334, 631948, 233769, 272351, 992372, 37000, 911988, 102735, 75227, 777012, 111823, 799444, 565255, 694030, 405036, 143253, 542278, 956757, 958676, 184326, 972559, 534675, 22176, 569937, 432168, 734581, 235631, 164613, 845103, 32269, 564530, 978742, 34413, 607402, 85996, 167385, 808261, 698551, 252858, 943480, 359010, 193227, 853281, 646645, 680639, 654081, 57003, 250399, 489586, 546493, 579313, 881860, 488629, 340808, 397107, 595685, 325684, 158523, 893879, 982462, 625765, 41171, 622934, 590937, 405121, 518235, 779658, 708529, 266111, 568341, 449562, 784757, 161350, 627273, 912996, 948061, 335335, 389786, 56764, 252339, 16951, 962137, 618134, 784076, 291721, 539184, 691900, 170391, 548299, 547281, 354653, 661381, 656086, 613391, 959599, 473034, 203891, 992265, 72610, 923731, 368983, 568322, 891286, 511070, 42116, 31793, 203285, 706711, 786320, 194493, 746250, 734019, 618665, 383681, 426724, 75054, 19282, 529820, 153489, 846268, 127087, 614641, 988480, 163617, 278431, 197481, 165322, 359216, 807932, 626321, 858998, 440380, 912663, 771974, 861724, 702132, 530792, 697065, 559573, 817813, 157350, 713583, 48517, 723372, 337604, 953113, 485499, 721602, 13422, 941197, 99070, 295354, 918892, 899210, 800763, 899204, 273516, 336520, 931609, 716873, 770451, 672, 695277, 925949, 350436, 795244, 287154, 218796, 196401, 862267, 664246, 520007, 680804, 469263, 982373, 567541, 944243, 878654, 433383, 180845, 178061, 897872, 705889, 609993, 280020, 335442, 750839, 324409, 223218, 105985, 751249, 855333, 59283, 459690, 901028, 575830, 650184, 71509, 148312, 741812, 656497, 899869, 16990, 10766, 626975, 498872, 800647, 540732, 787473, 184226, 717598, 620793, 395768, 367436, 819414, 156468, 159770, 273479, 577524, 682353, 557042, 909200, 168251, 873103, 630326, 716470, 737045, 948058, 931459, 656787, 27936, 715707, 223043, 506860, 920064, 829989, 518652, 605160, 234980, 953562, 924271, 687420, 991656, 192097, 848058, 790796, 773466, 667840, 403903, 45622, 66298, 364798, 980637, 921951, 164043, 671031, 988272, 853078, 14241, 282598, 496215, 846025, 866051, 919782, 694357, 898736, 791143, 574613, 163174, 399994, 998626, 50375, 276878, 233306, 635910, 971513, 836339, 227337, 304375, 510547, 857065, 752632, 500251, 232456, 131106, 475825, 338371, 66386, 4237, 925014, 150370, 216517, 384573, 194756, 766967, 33316, 773, 794621, 510731, 194584, 672237, 754429, 193654, 228447, 747559, 534489, 672407, 444360, 42565, 218795, 508952, 14727, 833366, 620856, 934604, 64933, 175066, 646898, 305686, 959091, 13447, 105915, 188260, 554400, 855361, 482908, 907635, 777983, 578809, 681939, 863756, 239668, 477840, 770517, 201504, 107832, 974857, 952473, 553429, 480983, 820298, 327128, 529407, 345361, 33838, 965117, 206206, 189846, 727515, 154424, 859753, 652667, 486197, 411453, 759914, 229399, 883838, 17747, 362898, 242616, 18387, 897536, 22578, 574814, 708176, 463385, 444271, 116617, 431685, 829582, 755463, 695258, 525183, 696868, 78246, 874813, 470454, 492362, 491753, 621035, 607897, 958607, 793562, 893893, 803033, 243097, 483691, 584640, 757037, 371618, 511135, 930186, 866098, 817555, 485362, 563235, 304881, 643274, 935171, 79431, 78958, 195903, 282642, 345094, 838323, 474845, 760043, 275327, 214268, 51534, 836301, 398066, 888828, 981798, 306932, 741074, 512049, 83507, 616839, 880409, 133236, 989109, 769720, 276175, 663059, 831396, 601022, 597908, 497599, 165928, 792201, 723257, 875715, 48365, 326909, 89882, 789125, 641104, 645177, 348010, 842514, 22680, 554496, 761383, 697942, 120960, 59409, 316334, 211990, 181631, 575943, 995577, 901321, 387304, 473300, 967050, 895307, 361490, 305721, 996292, 214877, 952558, 437375, 781049, 147153, 289313, 364414, 250903, 932843, 807534, 389922, 639132, 477874, 937048, 394802, 955044, 258025, 688664, 862783, 731877, 188464, 670970, 421247, 445668, 374965, 676575, 524043, 731120, 716287, 41238, 246597, 732834, 193403, 539895, 552887, 918627, 522211, 948117, 94330, 717197, 814458, 983364, 351020, 729571, 489138, 655800, 74087, 667194, 677924, 906746, 374886, 326357, 833309, 306036, 232661, 495013, 949953, 317845, 155578, 744065, 703902, 448154, 610492, 149358, 813736, 846980, 945134, 900325, 658180, 169476, 249217, 676742, 566483, 324411, 72213, 34776, 396871, 282221, 852640, 739661, 134494, 27448, 551501, 662994]\n" ] }, { "cell_type": "code", "execution_count": 23, "id": "748cb9f8", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Demo runtime for n = 200 elements: 1.639 seconds\n", "Result: [q1, q2, q3] = [28, 1528, 134610]\n", "\n", "Demo runtime for n = 1000 elements: 214.245 seconds\n", "Result: [q1, q2, q3] = [105, 42660, 17483370]\n", "\n", "==\n", "Ratio between the two runtimes: 130.69022369642522\n", "Suggested time-requirements class: O(n ** 3.028)\n" ] } ], "source": [ "# single-run mid-to-large scale performance test\n", "#\n", "# for our naive implementation, we should measure a scaling consistent with O(n**3) time requirements\n", "#\n", "# a) what runtime, and what O(...) performance class estimate, do you obtain for your improved code?\n", "# b) check whether your improved code still returns the same output:\n", "# - for x200, the return value should be [28, 1528, 134610]\n", "# - for x1000, the return value should be [105, 42660, 17483370]\n", "#\n", "import time\n", "import math\n", "\n", "y = 7\n", "\n", "start = time.time()\n", "out200 = mod10_count_naive(x200, y)\n", "end = time.time()\n", "time200 = end - start\n", "print(\"Demo runtime for n = 200 elements:\" , round(time200, 3), \"seconds\")\n", "print(\"Result: [q1, q2, q3] =\", out200)\n", "\n", "start = time.time()\n", "out1000 = mod10_count_naive(x1000, y)\n", "end = time.time()\n", "time1000 = end - start\n", "print(\"\\nDemo runtime for n = 1000 elements:\" , round(time1000, 3), \"seconds\")\n", "print(\"Result: [q1, q2, q3] =\", out1000)\n", "\n", "print(\"\\n==\\nRatio between the two runtimes:\", time1000/time200)\n", "\n", "print(\"Suggested time-requirements class: O(n ** \", \\\n", " round(math.log(time1000/time200, 1000/200), 3), \")\", sep='')" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.9.7" } }, "nbformat": 4, "nbformat_minor": 5 }