Занимательная математика, очаровательный python. Эпизод 2: Праймориалы и факторионы

Safoyeth 8 Дек 2013

В предыдущей статье мы познакомились с целым семейством факториалов и обратных факториалов и написали целый ряд функций. Тема этой статьи намного меньше - праймориалы и факторионы. Познакомившись с новичками, мы закончим написание нашего модуля factorials. 

Праймориал

Люди любят придумывать много всего такого, что не имеет ни физического смысла, ни прикладного значения, только эзотерическое, мистическое. Может быть это как-то связано с чувством красоты, которое постоянно требует чего-то необычного, изящного и гармоничного? Но в сторону лирику, сначала как обычно теория.

Праймориалом (примориалом) числа n (обозначается n#) называется произведение всех простых чисел от 1 до n.

Теперь нужно понять (если кто не в курсе), что такое простые числа. Я думаю, что многие из вас хорошо с ними знакомы, остальных же я быстро введу в курс дела.

Простым числом называется число, которое имеет два и только два натуральных делителя - единицу и само себя.

Соответственно, простыми числами будут 2, 3, 5, 7, 11, 13 etc. Исходя из этих данных, для своих целей я решил разделить функцию праймориала на две. Первая, назовем её isPrime, будет определять, является ли число простым, вторая же, собственно primorial, будет считать праймориалы. Начинаем с функции isPrime:

Смысл функции не очень сложен. Во первых, как обычно мы ожидаем данные типа int и больше нуля. Во вторых, примем за умолчание, что 0 и 1 - не простые числа, соответственно вернем False. А дальше наша задача просто непоследовательно разделить данное число на значения, начинающиеся с двух и заканчивающиеся собственно самим значением. Соответственно как только мы получаем остаток от деления по модулю, равный нулю, мы сразу проверяем, не равен ли делитель нашему числу, если это не так, то выходим из цикла и возвращаем False, в противном случае возвращаем True - это простое число. Можно потестировать функцию в интерактивном интерпретаторе.

Теперь собственно сам праймориал. Удивительно, но в этот раз мы обойдемся даже без lambda-функции!

Все опять же не сложно. Мы проверяем валидность данных, затем в последовательности значений от 2 до данного числа проверяем каждое из них на предмет простоты нашей функцией isPrime. Если число простое, то мы просто умножаем его на предыдущее и так далее. Если же значение, передаваемое в функцию равно 0 или 1, то праймориал вернёт 1. Это получается из-за того, что мы объявили переменную primes равную 1.

Обратный праймориал

Механизм нахождения обратного праймориала  в общем-то ничем не отличается от того, что мы делали в предыдущей статье, кроме одной маленькой хитрости. Давайте импортируем наш модуль factorials и выполним функцию primorial, передав ей значения 11, 12, 13.

Удивлены? 11# = 12#! В общем-то, никакого противоречия здесь нет, просто как легко догадаться в последовательностях и от 1 до 11 и от 1 до 12 одинаковое количество простых чисел, вот и значения получаются одинаковые. Для нас это создает некоторые трудности, которые, впрочем, легко решаются. Для того, чтобы понять, что делать, давайте возьмем число 2310, которое является праймориалом и 11 и 12 и начнем его последовательно делить на простые числа. Сначала на 2, потом на 3, на 5, на 7 и на 11, своего рода поработаем функцией обратного факториала. Как не сложно догадаться, мы получим 11 в качестве значения! Ещё немного логики и решение находится просто само, мы должны найти все непростые числа до следующего простого и вернуть их вместе с нашим найденным. В коде это выглядит так.

Вся хитрость заключена именно в том, что мы сначала инструкцией values = [each] передаем найденное значение в новый список, а затем просто с помощью нашей функции isPrime мы проверяем сумму нашего значения с последовательностью до тех пор, пока не найдем следующее простое число. Тогда мы выходим из цикла, возвращая все значения. И не забываем про декоратор, который мы написали в конце предыдущей статьи! 🙂

Факторион

С факториалами тесно связано семейство цифр, которое называется факторионами. В общем и целом, они не несут никакого математического смысла, но людям, на мой взгляд, всегда нравились такие ”магические” вещи. Собственно, знакомьтесь!

Факторионом называется число, равное сумме факториалов своих цифр.

И как несложно догадаться первыми факторионами будут цифры 1 и 2.  Функция для проверки, является ли число факторионом проста и не лишена некоторого изящества.

Самое сложное здесь - разложить число на цифры. Я использовал конструкцию tuple(str(x)), но это естественно не единственный путь.

Поскольку мы просто учимся, то вот вам задание - напишите сами функции для нахождения супер-, гипер- двойных факторионов и праймориона, я же перейду к последнему семейству ”магических” цифр на сегодня - к k-факторионам.

k-факторион

Чего только люди не придумают! Вообще, можно и самостоятельно поиграть с цифрами и тоже изобрети что-нибудь красивое. Возможно, как-нибудь я даже этим и займусь, но пока давайте разбираться с тем, что придумали до нас 😛

k-факторион - число, равное сумме своих факториалов, умноженной на k.

Из этого следует, что вышеописанные факторионы -  1-факторионы. Я снова ничего не расскажу про k-супер-, k-гипер- и остальные страшные семейства, ибо в них можно просто закопаться. Если хотите, можете сами написать функции к ним, я же буду делать это в следующей статье, когда мы научимся делать наш код не просто работающим, но и красивым, и, что самое главное, коротким! Функция же для k-факторионов выглядит так:

Все тоже самое, что и с обычным факторионом... Это скучно.

Последовательности

В заключение небольшой бонус. На небезызвестном ресурсе www.oeis.org существуют последовательности факториалов, праймориалов etc. Было бы очень неплохо и нам заиметь функции, которые бы строили последовательности. Если вы в шоке от того, что мы еще будем сейчас писать для каждой функции свою функцию для создания последовательности, то расслабьтесь! Могущество питона заключается в том, что мы напишем 1 (одну!) маленькую функцию, которая будет делать всё!

Для начала давайте определимся с тем, что мы хотим. Нам нужна функция, которая будет строить последовательность, начинающуюся с любой цифры, заданной длины и будет использовать для этого уже написанные нами ранее функции. Что ж, вот и она!

Просто, не правда ли? Подробностей будет не очень много. Конечно, пока эта функция сыровата, так как всю работу берёт на себя генератор списков и никаких помощников у него нет, но это мы в будущем поправим! Первым аргументом мы передаем функцию, второе и третье значение опциональны. Мы можем вызвать нашу функцию с одним аргументом -  function и тогда получим минимальную последовательность в 2 значения, можем вызвать с двумя - function и valueTo для получения последовательности от 0 до заданной цифры, и, наконец,  можем вызвать её со всеми тремя аргументами, тогда мы сможем получить часть последовательности от valueFrom до valueTo.

И ещё одна фишка...

Догадались? Если нет, пишите в комментарии)) На этом пока всё. Поиграйтесь с sequence  самостоятельно. Я же закругляюсь на сегодня, завтра тяжёлый рабочий понедельник... А вот в следующей статье мы превратим наш пока ещё кривоватый модуль в нечто более полнофункциональное и приближенное к дзен-питону.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.




Комментарии (2) на Занимательная математика, очаровательный python. Эпизод 2: Праймориалы и факторионы

  1. Влад:

    Было бы интересно поглядеть на субфакториалы (хотя для них рекуррентная формула есть). Довольно интересно, только слишком много этих факториалов, было бы здорово посмотреть на что-то еще

    Пара замечаний:
    1) поиск простых чисел не имеет смысла вычислять до самого числа! Всего лишь до корня из числа.
    2) если что, последовательность пишется sequence

    • Тысячу лет назад баловался... Спасибо за замечания, с sequence, конечно, косяк, поправил)) О субфакториалах думал ещё тогда, но как-то руки не дошли... Я не математик, поэтому прошу меня простить за то, что возможно я изобретаю велосипед...

Добавить комментарий

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: