Comments 25
Какой то уж очень не читаемый код для компании, которая учит python'у
Возможно вы кого то обделили? 3.141592653589793
# python3.6
find_nums_in_pi({15, 59, 92})
# {15: 3, 59: 4, 92: 62}
# python3.6
find_nums_in_pi([15, 59, 92])
# {15: 3, 92: 5, 59: 61}
find_nums_in_pi({15, 59, 92}, 4)
# RuntimeError: Circuit breaker!
find_nums_in_pi({159, 59})
# IndexError: string index out of range
Я вас, наверное, уже задолбал, но все еще если first_n > len(nums), то получим бесконечный цикл https://habrahabr.ru/company/otus/blog/332180/#comment_10295658
find_nums_in_pi([59, 159, 230])
# {59: 61, 159: 3, 230: 63}
И вот почему
# pi = 3.14_159_2653589793
for pos in itertools.count():
d = str(pi_gen.next())
found_num = None
for cur_num in _nums:
cur_num.move_p(d)
# whole number found
if cur_num.p == cur_num.l:
nums_pos[cur_num.n] = pos - cur_num.l + 1
# found enough numbers
if len(nums_pos) == first_n:
return nums_pos
found_num = cur_num.n
# create new search array without found number
if found_num:
_nums = [num for num in _nums if num.n != found_num]
когда мы доходим до 9 то found_num будет равно 159, т.к. он перезапишет 59 и из _nums будет удален только 159, а 59 будет найден дальше
Чтобы не подбирать числа придумаем свое пи:
def pi_digits():
fake_pi = '3143338327989793238462643383279'
for p in fake_pi:
yield p
q, r, t, k, n, l = 1, 0, 1, 1, 3, 3
while True:
if 4 * q + r - t < n * t:
yield n
q, r, t, k, n, l = (10*q, 10*(r-n*t), t, k, (10*(3*q+r))//t-10*n, l)
else:
q, r, t, k, n, l = (q*k, (2*q+r)*l, t*l, k+1, (q*(7*k+2)+r*l)//(t*l), l+2)
И снова не правильно находит
class _Num(object):
def __init__(self, n):
self.n = n
self.s = str(n)
self.p = 0 # pointer in number string representation
self.l = len(self.s)
def move_p(self, d):
if self.p < self.l and d == self.s[self.p]:
self.p += 1
else:
self.p = 0 if d != self.s[0] else 1
#################
find_nums_in_pi({338})
# {338: 24}
При чем тут абсурд, ваш код неправильно работает на корректных данных (не всегда, но при определенных обстоятельствах).
Более того — ниже я вам дал более простой и в тоже время быстрый код (в 30-50 раз). Но тем не менее вы все еще полагаете, что ваш код читаем и хорош, и признавать неправоту не желаете не взирая на то количество ошибок, которое я вам указал. Что же — это ваше право.
ваше решение ниже, конечно, быстрее, но суть была не в том, чтобы придумать самое быстрее решение. Знаете как будет еще быстрее? Сгенерить цифры заранее и искать по индексу, например. А можно еще на C переписать. Можно даже, в порядке бреда, натренировать нейронку предсказывать позицию.
Еще в моем коде были(есть и будут) ошибки. К счастью не было задачи правильно искать число в Пи, была задача случайно выбрать несколько человек каким-нибудь забавным способом.
Ваше желание доказать, что я неправ в чем-то понятно и объяснимо (=
… ваше решение ниже, конечно, быстрее, но суть была не в том, чтобы придумать самое быстрее решение ...
Да, но оно решает именно ту задачу, тем методом (поиском по числу пи), на том языке которые вы выбрали. При этом оно быстрее, понятнее, работает правильно.
Ваше желание доказать, что я неправ в чем-то понятно и объяснимо (=
Будь этот пост от студента, который учится писать на python — молодец, что то делает, пишет, учится. Пускай сейчас не особо правильно и перемудрено, но это не плохо, ведь он изучает возможности языка.
Но этот пост от компании, которая учит других людей писать на python'е.
Критикуешь — предлагай, не исключаю, что и тут найдутся ошибки:
MAX_POS = 10 ** 4
class _Num:
def __init__(self, n):
self.s = str(n)
self.p = 0 # pointer in number string representation
def move_p(self, d):
if d == self.s[self.p]:
self.p += 1
else:
self.p = 0
def is_whole_found(self):
return self.p == len(self.s)
def find_next(_nums, pos, d):
nums_pos = {}
nums = {}
for n, cur_num in _nums.items():
cur_num.move_p(d)
if cur_num.is_whole_found():
nums_pos[n] = pos - len(cur_num.s) + 1
else:
nums[n] = cur_num
return nums, nums_pos
def find_nums_in_pi(nums: set, first_n: int = None):
pi_gen = pi_digits()
max_count = min(first_n or len(nums), len(nums))
_nums = {n: _Num(n) for n in nums}
nums_pos = {}
for pos, d in enumerate(pi_gen):
_nums, next_pos = find_next(_nums, pos, str(d))
nums_pos.update(next_pos)
if len(nums_pos) >= max_count:
return nums_pos
if pos % 1000 == 0:
print("Current Pi position: %s. Nums found: %s" % (pos, len(nums_pos)))
if pos == MAX_POS:
raise RuntimeError("Circuit breaker!")
Если исходить из того что все числа одной длины, то вот суперкиллер:
def ff(nums: set, first_n: int = None):
pi_gen = pi_digits()
max_count = min(first_n or len(nums), len(nums))
_nums = nums
nums_pos = {}
start = ''
for p in range(6):
start += str(next(pi_gen))
for pos, d in enumerate(pi_gen):
if int(start) in _nums:
nums_pos[int(start)] = pos
_nums = _nums - {int(start)}
if len(nums_pos) >= max_count:
return nums_pos
start = start[1:] + str(d)
if pos % 10000 == 0:
print("Current Pi position: %s. Nums found: %s" % (pos, len(nums_pos)))
if pos == MAX_POS:
raise RuntimeError("Circuit breaker!")
r = set(range(10**5, 10**6))
c = ff(r, 666)
print("res: ", c)
a = find_nums_in_pi(r, 66)
print("res: ", a)
b = _find_nums_in_pi(r, 66)
print("res: ", b)
print(a == b, a == c)
Current Pi position: 0. Nums found: 1
ff: 16.3442
res: {314159: 0, 141592: 1, 415926: 2, 159265: 3, 592653: 4, 926535: 5, 265358: 6, 653589: 7, 535897: 8, 358979: 9, 589793: 10, 897932: 11, 979323: 12, 793238: 13, 932384: 14, 323846: 15, 238462: 16, 384626: 17, 846264: 18, 462643: 19, 626433: 20, 264338: 21, 643383: 22, 433832: 23, 338327: 24, 383279: 25, 832795: 26, 327950: 27, 279502: 28, 795028: 29, 950288: 30, 502884: 31, 288419: 33, 884197: 34, 841971: 35, 419716: 36, 197169: 37, 971693: 38, 716939: 39, 169399: 40, 693993: 41, 939937: 42, 399375: 43, 993751: 44, 937510: 45, 375105: 46, 751058: 47, 510582: 48, 105820: 49, 582097: 51, 820974: 52, 209749: 53, 974944: 55, 749445: 56, 494459: 57, 944592: 58, 445923: 59, 459230: 60, 592307: 61, 923078: 62, 230781: 63, 307816: 64, 781640: 66, 816406: 67, 164062: 68, 640628: 69, 406286: 70, 628620: 72, 286208: 73, 862089: 74, 620899: 75, 208998: 76, 899862: 78, 998628: 79, 986280: 80, 862803: 81, 628034: 82, 280348: 83, 803482: 84, 348253: 86, 482534: 87, 825342: 88, 253421: 89, 534211: 90, 342117: 91, 421170: 92, 211706: 93, 117067: 94, 170679: 95, 706798: 96, 679821: 98, 798214: 99, 982148: 100, 821480: 101, 214808: 102, 148086: 103, 480865: 104, 808651: 105, 865132: 107, 651328: 108, 513282: 109, 132823: 110, 328230: 111, 282306: 112, 823066: 113, 230664: 114, 306647: 115, 664709: 117, 647093: 118, 470938: 119, 709384: 120, 938446: 122, 384460: 123, 844609: 124, 446095: 125, 460955: 126, 609550: 127, 955058: 129, 550582: 130, 505822: 131, 582231: 133, 822317: 134, 223172: 135, 231725: 136, 317253: 137, 172535: 138, 725359: 139, 253594: 140, 535940: 141, 359408: 142, 594081: 143, 940812: 144, 408128: 145, 812848: 147, 128481: 148, 284811: 149, 848111: 150, 481117: 151, 811174: 152, 111745: 153, 117450: 154, 174502: 155, 745028: 156, 450284: 157, 502841: 158, 284102: 160, 841027: 161, 410270: 162, 102701: 163, 270193: 165, 701938: 166, 193852: 168, 938521: 169, 385211: 170, 852110: 171, 521105: 172, 211055: 173, 110555: 174, 105559: 175, 555964: 177, 559644: 178, 596446: 179, 964462: 180, 644622: 181, 446229: 182, 462294: 183, 622948: 184, 229489: 185, 294895: 186, 948954: 187, 489549: 188, 895493: 189, 954930: 190, 549303: 191, 493038: 192, 930381: 193, 303819: 194, 381964: 196, 819644: 197, 196442: 198, 964428: 199, 644288: 200, 442881: 201, 428810: 202, 288109: 203, 881097: 204, 810975: 205, 109756: 206, 975665: 208, 756659: 209, 566593: 210, 665933: 211, 659334: 212, 593344: 213, 933446: 214, 334461: 215, 344612: 216, 446128: 217, 461284: 218, 612847: 219, 128475: 220, 284756: 221, 847564: 222, 475648: 223, 756482: 224, 564823: 225, 648233: 226, 482337: 227, 823378: 228, 233786: 229, 337867: 230, 378678: 231, 786783: 232, 867831: 233, 678316: 234, 783165: 235, 831652: 236, 316527: 237, 165271: 238, 652712: 239, 527120: 240, 271201: 241, 712019: 242, 120190: 243, 201909: 244, 190914: 246, 909145: 247, 914564: 249, 145648: 250, 456485: 251, 564856: 252, 648566: 253, 485669: 254, 856692: 255, 566923: 256, 669234: 257, 692346: 258, 923460: 259, 234603: 260, 346034: 261, 460348: 262, 603486: 263, 348610: 265, 486104: 266, 861045: 267, 610454: 268, 104543: 269, 454326: 271, 543266: 272, 432664: 273, 326648: 274, 266482: 275, 664821: 276, 648213: 277, 482133: 278, 821339: 279, 213393: 280, 133936: 281, 339360: 282, 393607: 283, 936072: 284, 360726: 285, 607260: 286, 726024: 288, 260249: 289, 602491: 290, 249141: 292, 491412: 293, 914127: 294, 141273: 295, 412737: 296, 127372: 297, 273724: 298, 737245: 299, 372458: 300, 724587: 301, 245870: 302, 458700: 303, 587006: 304, 870066: 305, 700660: 306, 660631: 309, 606315: 310, 631558: 312, 315588: 313, 155881: 314, 558817: 315, 588174: 316, 881748: 317, 817488: 318, 174881: 319, 748815: 320, 488152: 321, 881520: 322, 815209: 323, 152092: 324, 520920: 325, 209209: 326, 920962: 328, 209628: 329, 962829: 331, 628292: 332, 282925: 333, 829254: 334, 292540: 335, 925409: 336, 254091: 337, 540917: 338, 409171: 339, 917153: 341, 171536: 342, 715364: 343, 153643: 344, 536436: 345, 364367: 346, 643678: 347, 436789: 348, 367892: 349, 678925: 350, 789259: 351, 892590: 352, 925903: 353, 259036: 354, 590360: 355, 903600: 356, 360011: 358, 600113: 359, 113305: 362, 133053: 363, 330530: 364, 305305: 365, 530548: 367, 305488: 368, 548820: 370, 488204: 371, 882046: 372, 820466: 373, 204665: 374, 466521: 376, 665213: 377, 652138: 378, 521384: 379, 213841: 380, 138414: 381, 384146: 382, 841469: 383, 414695: 384, 146951: 385, 469519: 386, 695194: 387, 951941: 388, 519415: 389, 194151: 390, 941511: 391, 415116: 392, 151160: 393, 511609: 394, 116094: 395, 160943: 396, 609433: 397, 943305: 399, 433057: 400, 330572: 401, 305727: 402, 572703: 404, 727036: 405, 270365: 406, 703657: 407, 365759: 409, 657595: 410, 575959: 411, 759591: 412, 595919: 413, 959195: 414, 591953: 415, 919530: 416, 195309: 417, 953092: 418, 530921: 419, 309218: 420, 921861: 422, 218611: 423, 186117: 424, 861173: 425, 611738: 426, 117381: 427, 173819: 428, 738193: 429, 381932: 430, 819326: 431, 193261: 432, 932611: 433, 326117: 434, 261179: 435, 611793: 436, 117931: 437, 179310: 438, 793105: 439, 931051: 440, 310511: 441, 105118: 442, 511854: 444, 118548: 445, 185480: 446, 854807: 447, 548074: 448, 480744: 449, 807446: 450, 744623: 452, 446237: 453, 462379: 454, 623799: 455, 237996: 456, 379962: 457, 799627: 458, 996274: 459, 962749: 460, 627495: 461, 274956: 462, 749567: 463, 495673: 464, 956735: 465, 567351: 466, 673518: 467, 735188: 468, 351885: 469, 518857: 470, 188575: 471, 885752: 472, 857527: 473, 575272: 474, 752724: 475, 527248: 476, 272489: 477, 724891: 478, 248912: 479, 489122: 480, 891227: 481, 912279: 482, 122793: 483, 227938: 484, 279381: 485, 793818: 486, 938183: 487, 381830: 488, 818301: 489, 183011: 490, 830119: 491, 301194: 492, 119491: 494, 194912: 495, 949129: 496, 491298: 497, 912983: 498, 129833: 499, 298336: 500, 983367: 501, 833673: 502, 336733: 503, 367336: 504, 673362: 505, 733624: 506, 336244: 507, 362440: 508, 624406: 509, 244065: 510, 440656: 511, 406566: 512, 656643: 514, 566430: 515, 664308: 516, 643086: 517, 430860: 518, 308602: 519, 860213: 521, 602139: 522, 213949: 524, 139494: 525, 394946: 526, 949463: 527, 494639: 528, 946395: 529, 463952: 530, 639522: 531, 395224: 532, 952247: 533, 522473: 534, 224737: 535, 247371: 536, 473719: 537, 737190: 538, 371907: 539, 719070: 540, 190702: 541, 907021: 542, 702179: 544, 217986: 546, 179860: 547, 798609: 548, 986094: 549, 860943: 550, 609437: 551, 943702: 553, 437027: 554, 370277: 555, 702770: 556, 277053: 558, 770539: 559, 705392: 560, 539217: 562, 392171: 563, 921717: 564, 217176: 565, 171762: 566, 717629: 567, 176293: 568, 762931: 569, 629317: 570, 293176: 571, 931767: 572, 317675: 573, 176752: 574, 767523: 575, 675238: 576, 752384: 577, 523846: 578, 238467: 579, 384674: 580, 846748: 581, 467481: 582, 674818: 583, 748184: 584, 481846: 585, 818467: 586, 184676: 587, 846766: 588, 467669: 589, 676694: 590, 766940: 591, 669405: 592, 694051: 593, 940513: 594, 405132: 595, 513200: 597, 132000: 598, 320005: 599, 200056: 600, 568127: 604, 681271: 605, 812714: 606, 127145: 607, 271452: 608, 714526: 609, 145263: 610, 452635: 611, 526356: 612, 263560: 613, 635608: 614, 356082: 615, 560827: 616, 608277: 617, 827785: 619, 277857: 620, 778577: 621, 785771: 622, 857713: 623, 577134: 624, 771342: 625, 713427: 626, 134275: 627, 342757: 628, 427577: 629, 275778: 630, 757789: 631, 577896: 632, 778960: 633, 789609: 634, 896091: 635, 960917: 636, 609173: 637, 917363: 639, 173637: 640, 736371: 641, 363717: 642, 637178: 643, 371787: 644, 717872: 645, 178721: 646, 787214: 647, 872146: 648, 721468: 649, 214684: 650, 146844: 651, 468440: 652, 684409: 653, 844090: 654, 440901: 655, 409012: 656, 901224: 658, 122495: 660, 224953: 661, 249534: 662, 495343: 663, 953430: 664, 534301: 665, 343014: 666, 430146: 667, 301465: 668, 146549: 670, 465495: 671, 654958: 672, 549585: 673, 495853: 674, 958537: 675, 585371: 676, 853710: 677, 537105: 678, 371050: 679, 710507: 680, 105079: 681, 507922: 683, 792279: 685, 922796: 686, 227968: 687, 279689: 688, 796892: 689, 968925: 690, 689258: 691, 892589: 692, 925892: 693, 258923: 694, 589235: 695, 892354: 696, 923542: 697, 235420: 698, 354201: 699, 542019: 700, 420199: 701, 201995: 702, 199561: 704, 995611: 705, 956112: 706, 561121: 707, 611212: 708, 112129: 709, 121290: 710, 212902: 711, 129021: 712, 290219: 713, 902196: 714, 219608: 716, 196086: 717, 960864: 718, 608640: 719, 864034: 721, 640344: 722, 403441: 723, 344181: 725, 441815: 726, 418159: 727, 181598: 728, 815981: 729, 159813: 730, 598136: 731, 981362: 732, 813629: 733}
Current Pi position: 0. Nums found: 0
find_nums_in_pi: 62.4308
res: {314159: 0, 141592: 1, 415926: 2, 159265: 3, 592653: 4, 926535: 5, 265358: 6, 653589: 7, 535897: 8, 358979: 9, 589793: 10, 897932: 11, 979323: 12, 793238: 13, 932384: 14, 323846: 15, 238462: 16, 384626: 17, 846264: 18, 462643: 19, 626433: 20, 264338: 21, 643383: 22, 433832: 23, 338327: 24, 832795: 26, 327950: 27, 279502: 28, 795028: 29, 950288: 30, 502884: 31, 288419: 33, 884197: 34, 419716: 36, 197169: 37, 971693: 38, 716939: 39, 169399: 40, 693993: 41, 939937: 42, 399375: 43, 993751: 44, 937510: 45, 375105: 46, 751058: 47, 510582: 48, 105820: 49, 582097: 51, 820974: 52, 209749: 53, 974944: 55, 749445: 56, 494459: 57, 944592: 58, 445923: 59, 592307: 61, 923078: 62, 230781: 63, 307816: 64, 781640: 66, 816406: 67, 164062: 68, 640628: 69, 406286: 70, 628620: 72, 286208: 73}
Current Pi position: 0. Nums found: 0
_find_nums_in_pi: 46.1488
res: {314159: 0, 141592: 1, 415926: 2, 159265: 3, 592653: 4, 926535: 5, 265358: 6, 653589: 7, 535897: 8, 358979: 9, 589793: 10, 897932: 11, 979323: 12, 793238: 13, 932384: 14, 323846: 15, 238462: 16, 384626: 17, 846264: 18, 462643: 19, 626433: 20, 264338: 21, 643383: 22, 433832: 23, 338327: 24, 832795: 26, 327950: 27, 279502: 28, 795028: 29, 950288: 30, 502884: 31, 288419: 33, 884197: 34, 419716: 36, 197169: 37, 971693: 38, 716939: 39, 169399: 40, 693993: 41, 939937: 42, 399375: 43, 993751: 44, 937510: 45, 375105: 46, 751058: 47, 510582: 48, 105820: 49, 582097: 51, 820974: 52, 209749: 53, 974944: 55, 749445: 56, 494459: 57, 944592: 58, 445923: 59, 592307: 61, 923078: 62, 230781: 63, 307816: 64, 781640: 66, 816406: 67, 164062: 68, 640628: 69, 406286: 70, 628620: 72, 286208: 73}
True False
Возле каждой из функций в выводе указано время выполнения.
Также прошу обратить внимание что ваша функция (как и моя https://habrahabr.ru/company/otus/blog/332180/#comment_10295706) не нашли 25 елемент (383279)
PS в коде захардкорджено маленько и названия переменных/функций — не ахти, уж простите.
А из колмогоровской теория сложности следует то архиватор не влетит.
Как искать людей в числе Пи и при чем тут Python