Короткий пост, просто хотел поделиться одним изящным открытием, которое я сделал сегодня ранее. Для тех из вас, у кого большой опыт работы с Wolfram Mathematica, это может быть старая шляпа.

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

В Wolfram Mathematica есть понятие чистые функции. С некоторыми оговорками вы можете использовать чистые функции в Wolfram Alpha. Фактически, перейдите прямо сейчас на Wolfram Alpha и введите это:

Select[Prime[Range[100]], PrimeQ[3# + 4] &]

Вероятно, это то, что вы бы набрали, если вам интересно, какие простые числа p также дают простые числа для 3 p + 4. Например, 5 является таким простым числом, так как 3 × 5 + 4 = 19. Напротив, мы видим, что 7 не такое простое число, поскольку 3 × 7 + 4 = 25 = 5².

Wolfram Alpha дает правильный ответ на приведенное выше утверждение Wolfram Mathematica: 3, 5, 11, 13, 19 и т. Д. И т. Д. На 541, которое оказывается сотым простым числом.

Итак, Range[100] просто дает нам целые числа от 1 до 100, а Prime[Range[100]] дает нам простые числа, проиндексированные целыми числами от 1 до 100, то есть 2, 3, 5, 7, 11, 13, 17, 19 и так далее до 541.

Затем Select сообщает Mathematica, что мы хотим, чтобы она выбрала из этого списка элементы, которые возвращают True для заданного логического значения, в данном случае PrimeQ[3# + 4] &.

# «вытягивает» число из списка, умножает его на 3 и добавляет 4 (вы можете написать 3 * # + 4, если хотите). Чтобы система Mathematica знала, что мы вызываем чистую функцию, нам нужно поставить & перед закрывающей фигурной скобкой Select.

Что, если вы хотите повторить 3 x + 4 несколько раз, начиная с x = 3 и передав результат в следующий x? В Mathematica вы можете использовать NestList. Это также будет работать в Wolfram Alpha:

NestList[3# + 4 &, 3, 20]

# здесь сначала обозначает начальный x, а затем предыдущие 3 x + 4, которые становятся новым x. И снова нам нужно &, чтобы система Mathematica знала, что мы вызываем чистую функцию. Затем запятая и наш начальный аргумент, в данном случае 3. И после этого 20 означает, что мы хотим повторить это двадцать раз.

Результат: 3, 13, 43, 133, 403, 1213, 3643 и т. Д. Эти числа быстро становятся большими, хотя нам не нужно беспокоиться о переполнении 32- или 64-битного целочисленного примитива.

Как видите, некоторые из этих чисел, например 13 и 43, простые, другие - составные, например 133 = 7 × 19.

Это может заставить нас задуматься: существуют ли простые числа p такие, что мы можем повторить 3 x + 4 четыре раза и получить только простые числа?

Мы могли создать логическую функцию и использовать ее в Select, что-то вроде

specNumberQ[n_] := (Union[PrimeQ[NestList[3# + 4 &, n, 4]]] == {True});

Это кажется неэлегантным. Даже если мы не сохраним блокнот Mathematica, будет напрасно называть эту функцию, которую мы, возможно, никогда больше не будем использовать.

Должен быть способ использовать две чистые функции в одной строке (это нормально, если строка переносится по длине), одну для NestList, другую для Select.

Я не буду утомлять вас списком всех неправильных вещей, которые я пробовал. Я хочу убедиться, что вы понимаете, что это решение, такое простое и элегантное, было не первым, что я пробовал, и даже не вторым или третьим:

Select[Prime[Range[1000]], Union[PrimeQ[NestList[(3# + 4 &), #, 4]]] == {True} &]

Обратите внимание, что 3# + 4 & заключен в круглые скобки. Таким образом, я сообщаю Mathematica, что объем итерации чистой функции ограничен первым аргументом NestList, что позволяет Mathematica понять, что следующий # означает число из Prime[Range[1000]].

Однако это не будет работать в Wolfram Alpha. «Wolfram | Alpha не понимает ваш запрос». Ну что ж.

В любом случае, в системе Mathematica этот запрос дает только один результат: 3203. Мы проверяем, что 9613, 28843, 86533 и 259603 - все простые числа, но 778813 = 7 × 31 × 37 × 97. Если мы увеличим 1000 в Range, скажем, 10000, мы могли бы получить больше цифр.

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

На самом деле, как оказалось, по крайней мере, для этого конкретного примера скобки не нужны. Только что я подтвердил, что

Select[Prime[Range[1000]], Union[PrimeQ[NestList[3# + 4 &, #, 4]]] == {True} &]

дает правильный результат. При правильном размещении амперсандов Mathematica правильно поймет, откуда берется аргумент для каждой чистой функции.

Я надеюсь, что вы получите от этого какую-то пользу или, по крайней мере, думаете, что это может быть вам полезно в будущем.