x14 = S - x11 - x12 - x13
x24 = S - x21 - x22 - x23
x34 = S - x31 - x32 - x33
x41 = S - x11 - x21 - x31
x42 = S - x12 - x22 - x32
x43 = S - x13 - x23 - x33
x44 = S + x14 - x14 - x24 - x34
Что это дает? Очень многое. Вместо перебора 16 вариантов суммарным количеством 16!=20922789888000 мы должны перебрать лишь 9 вариантов, что дает 9!=362880 вариантов, т.е. в 57657600 раз меньше! Как нетрудно догадаться, мы фактически выразили крайние строки квадрата через соседние, т.е. уменьшили размерность поиска с 4х4 до 3х3. Это же правило будет действовать и для квадратов большей диагонали.
Обновленная программа выглядит более громоздко (в ней также добавлены проверки на ненулевые значения и проверки на уникальность элементов), зато расчет происходит в разы быстрее. Здесь также используется возможность работы со множествами в языке Python, что легко позволяет делать перебор нужных цифр в цикле:
set(range(1,16+1)) - множество чисел [1..16]
set(range(1,16+1)) - set([x11]) - множество чисел [1..16] за исключением x11.
Также добавлена простая проверка на минимальность суммы: очевидно, что сумма всех элементов не может быть меньше чем 16+1+2+3 = 22.
digits = set(range(1,16+1))
cnt = 0
for x11 in digits:
for x12 in digits - set([x11]):
for x13 in digits - set([x11, x12]):
for x14 in digits - set([x11, x12, x13]):
s = x11 + x12 + x13 + x14
if s < 22: continue
for x21 in digits - set([x11, x12, x13, x14]):
for x22 in digits - set([x11, x12, x13, x14, x21]):
for x23 in digits - set([x11, x12, x13, x14, x21, x22]):
x24 = s - x21 - x22 - x23
if x24 <= 0 or x24 in [x11, x12, x13, x14, x21, x22, x23]: continue
for x31 in digits - set([x11, x12, x13, x14, x21, x22, x23, x24]):
for x32 in digits - set([x11, x12, x13, x14, x21, x22, x23, x24, x31]):
for x33 in digits - set([x11, x12, x13, x14, x21, x22, x23, x24, x31, x32]):
x34 = s - x31 - x32 - x33
x41 = s - x11 - x21 - x31
x42 = s - x12 - x22 - x32
x43 = s - x13 - x23 - x33
x44 = s - x14 - x24 - x34
if x34 <= 0 or x41 <= 0 or x42 <= 0 or x43 <= 0 or x44 <= 0: continue
data = [x11, x12, x13, x14, x21, x22, x23, x24, x31, x32, x33, x34, x41, x42, x43, x44]
if len(data) != len(set(data)): continue
if is_magic(data, 4):
print data
cnt += 1
print cnt
В результате, программа проработала всего лишь около часа (вместо 3х лет!), всего было выведено 7040 квадратов размерностью 4х4. Разумеется, большинство из них являются поворотами или отражениями друг друга. Было доказано что уникальных квадратов всего 880.
Вспомним магический квадрат Дюрера, в его строке есть цифры 1514, соответствующие году создания гравюры. С помощью программы можно решить еще одну задачу: посмотреть сколько всего возможно квадратов с такими цифрами. Здесь число вариантов перебора меньше, т.к. еще 2 цифры фиксированы. Оказывается, помимо “авторского”, возможны всего 32 варианта, например:
1 15 14 4 2 15 14 3
5 11 8 10 5 10 7 12
12 6 9 7 11 8 9 6
16 2 3 13 16 1 4 13
Интересно, что верхний ряд помимо цифр 15 и 14 может содержать либо 1,4 либо 2,3, других вариантов нет. Разные варианты содержат лишь перестановки этих цифр.
Если же говорить о квадратах большей размерности, то число вариантов перебора для них получается слишком большим. Так для квадрата 5х5, даже если выразить крайние члены через соседние, получаем 4х4 остающихся клеток, что даст нам те же самые 16! вариантов перебора. В архиве с книгой приложен файл “07 - magic5.c” для расчета квадратов 5х5, но автору так и не хватило терпения дождаться всех результатов.
В качестве примера алгоритма построения квадратов любой нечетной размерности без полного перебора, можно назвать так называемый сиамский метод, известный уже с 17 века. Его описание можно найти в Википедии, пример программы на языке Python можно найти в приложении к книге.
Для N=9, программа сгенерировала следующий квадрат:
47 58 69 80 1 12 23 34 45
57 68 79 9 11 22 33 44 46
67 78 8 10 21 32 43 54 56
77 7 18 20 31 42 53 55 66
6 17 19 30 41 52 63 65 76
16 27 29 40 51 62 64 75 5
26 28 39 50 61 72 74 4 15
36 38 49 60 71 73 3 14 25
37 48 59 70 81 2 13 24 35
Существует множество других алгоритмов построения, например метод Франклина, Россера, Рауз-Болла, желающие могут поискать их самостоятельно.
И наконец, можно вспомнить так называемые “пандиагональные” магические квадраты. Это квадраты, в которых учитываются суммы также “косых” диагоналей, которые получаются если вырезать квадрат из бумаги и склеить его в тор. Желающие могут добавить в программу вывод таких квадратов самостоятельно.
8. Магический квадрат из простых чисел
Существует еще одна разновидность магического квадрата - составленного из простых чисел. Пример такого квадрата показан на рисунке:
29
131
107
167
89
11
71
47
149
Приведенную выше программу легко модифицировать для такого расчета: достаточно лишь заменить множество digits = set(range(1,16+1)) на другое, содержащее простые числа.
Для примера будем искать квадраты среди трехзначных простых чисел от 101 до 491.
Заменим в предыдущей версии программы строку digits = set([1,2,3,4,5,6,7,8,9]) на
primes = [ 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163,
167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251,
257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443,
449, 457, 461, 463, 467, 479, 487, 491 ]
digits = set(primes)
Таких квадратов нашлось 40, например:
233
167
389
419
263
107
137
359
293
Сумма чисел равна вполне красивому числу 789.
Т.к. число вариантов перебора больше, программа работает дольше. Время поиска составило 724с для Python-версии и 316c для программы на C++.
Если же рассматривать минимально возможный квадрат из простых чисел, то его сумма равняется тоже вполне “красивому” числу 111:
7
61
43
73
37
1
31
13
67
Примером квадрата 4х4 может быть квадрат с также “красивой” суммой 222:
97
41
73
11
17
47
83
75
59
79
13
71
49
55
53
65
9. Числа Фибоначчи
Возьмем 2 числа: 0 и 1. Следующее число рассчитаем как сумму предыдущих чисел, затем повторим процесс.
Мы получили последовательность, известную как числа Фибоначчи:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, ...
Эта последовательность была названа в честь итальянского математика 12 века Леонардо Фибоначчи. Фибоначчи рассматривал задачу роста популяции кроликов. Если предположить, что новорожденная пара кроликов 1 месяц растет, через месяц начинает спариваться, и затем через каждый месяц дает потомство, то количество пар кроликов несложно подсчитать:

Как можно видеть, число пар образует как раз те самые числа Фибоначчи. Сама последовательность Фибоначчи кажется простой. Но чем она интересна? Пример с кроликами не случаен - эти числа действительно описывают множество природных закономерностей:
- Множество растений имеют количество лепестков, равное одному из чисел Фибоначчи. Количество листьев на стебле также может описываться этим законом, например у тысячелистника.
- Другое известное изображение - спираль Фибоначчи, которая строится по похожему принципу соотношения размеров прямоугольников:
Это изображение также часто встречается в природе, от раковин моллюсков, до формы атмосферного циклона или даже спиральной галактики.
Для примера достаточно взять фотографию циклона из космоса, и наложить обе картинки вместе:
- Если взять и разделить друг на друга 2 любых соседних члена последовательности, например 233/377, получится число 0,618. Случайно это или нет, но это число - то самое “золотое сечение”, считающееся наиболее эстетичной пропорцией.
Числа Фибоначчи несложно вывести в программе на языке Python:
from decimal import *
def printNumbers(n):
i1 = Decimal(0)
i2 = Decimal(1)
for p in range(1, n+1):
print("F({}) = {}".format(p, i2))
fib = i1 + i2
i1 = i2
i2 = fib
getcontext().prec = 100
N = 100
printNumbers(N)
Интересно заметить, что растет последовательность Фибоначчи весьма быстро, уже F(300) = 222232244629420445529739893461909967206666939096499764990979600.
10. Высота звуков нот
Еще в древности человек заметил, что натянутая струна порождает колебания звука. Во времена Пифагора было замечено, что струны издают мелодичный звук, если их длина соотносится как небольшие целые числа (1:2, 2:3, 3:4 и т. д.). Звук от струны длиной 2/3 дает чистую квинту, 3/4 струны дает кварту а половина струны - октаву.
Рассмотрим струну с условной длиной = 1. Будем умножать длину струны на 3/2, если полученное число больше 2, разделим еще на 2.
1
3/2 = 1,5
1.5 * 3/2 = 2.25, 2.25/2 = 1,125 = 9/8
9/8 * 3/2 = 1,6875 = 27/16
Похожий ряд, если его упорядочить по возрастанию, называется пифагоровым строем:
“до” - 1
“ре” - 9/8
“ми” - 81/64
“фа” - 4/3
“соль” - 3/2
“ля” - 27/16
“си” - 243/128
“до” - 2
Он также называется квинтовым, т.к. ноты получались увеличением на квинту, т.е. на 3/2. Считается, что этот строй использовался еще при настройке лир в древней Греции, и сохранился вплоть до средних веков. Названия нот разумеется, были другие - современные названия придумал только через 1000 лет итальянский теоретик музыки Гвидо д’Ареццо в 1025 г..
Разумеется, в древней Греции никто не знал про частоту колебаний звука, зато древние греки были хорошими геометрами, и проблем с умножением и делением у них не было. Современная теория колебаний струны появилась гораздо позже, работы Эйлера и Д’Аламбера были написаны в 1750х годах.
Как математически определяются частоты звуков нот? Сейчас мы знаем, что октава (от “до” до “до” следующей октавы) - это умножение частоты на 2 (или укорочение струны в 2 раза). Для остальных нот с 18 века используется так называемый “хорошо темперированный строй”: октава делится на 12 равных промежутков, а последовательность частот образует геометрическую прогрессию.
Для одной октавы получаются следующие коэффициенты: 1,0594, 1,1224, 1,1892, …, 2. На клавиатуре они отображаются всем известным образом, образуя 12 полутонов:

Таким образом, если знать частоту любой ноты, все остальные легко рассчитываются по вышеприведенной формуле.
Очевидно, что “базовая” частота может быть любой. Традиционно принято например, что частота камертона ноты “Ля” 440Гц. Остальные ноты первой октавы:
ДО
261.6
ДО#
277
РЕ
293.7
РЕ#
311
МИ
329.6
ФА
349.2
ФА#
370
СОЛЬ
392
СОЛЬ#
415
ЛЯ
440
ЛЯ#
466
СИ
494
Интересно заметить, что квинта в этой системе имеет соотношение частот 27/12 = 1.49, что чуть-чуть отличается от “пифагорейского” чистого тона с соотношением 1.5. На слух “современная квинта” имеет небольшие биения 0,5Гц, соответствующие разности частот 392 - 392.4. До сих пор есть любители исполнения старинной музыки в квинто-терцевом строе, называемым “чистым”. В 18м же веке дебаты между приверженцами “старого” и “нового” строя были довольно-таки острыми. Впрочем, преимущества равномерно темперированного строя в виде четкого соотношения между частотами нот и возможности транспонирования музыки в любую другую тональность “без потери качества” оказались решающими. Сейчас “чистый строй” имеет лишь историческое значение, и используется лишь иногда для исполнения старинных произведений.
И традиционно, программа на языке Python, выводящая частоты полутонов в обе стороны от ноты “Ля”:
import math
freqLa = 440
for p in range(-32,32):
freq = freqLa*math.pow(2, p/12.0)
print p,freq
11. Вращение планет
Еще в древней Греции ученые знали, что планеты движутся по небу, но каким образом? Сотни лет господствовала геоцентрическая система мира - в центре была Земля, вокруг которой по окружностям двигались Луна, планеты (на то время их было известно 5) и Солнце:

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