В пятницу можно смешивать всё и со всем!
Мы смешаем пифагоровы тройки и библиотеку RxJS.
Пифагоровой тройкой называют три натуральных числа, из которых можно составить прямоугольный треугольник.
Такие числа известны людям с очень древних времён. Например, их использовали ещё в Египте, откуда до нас дошла самая известная пифагорова тройка — это числа 3, 4 и 5.
RxJS — это библиотека для реактивного программирования. Она поможет сделать генерацию троек красивой и простой.
Сразу замечу, что статья претендует только на развлекающую роль
Часть с математикой
Начнём с небольшой теоретической подготовки. Как ранее было замечено, пифагоровой тройкой называют три натуральных числа, которые удовлетворяют уравнению:
Назовём число a малым катетом, число b большим катетом, а число c — гипотенузой.
Все пифагоровы тройки описываются параметрическими формулами, которые называют формулами Евклида.
Чтобы оставить статью скорее развлекательной, мы дальше будем рассматривать только такие пифагоровы тройки, у которых гипотенуза c отличается от большего катета b ровно на единицу.
Вот первые три такие тройки:
Попробуем вывести формулы этого семейства троек. Подставим c = b + 1
и получим:
Видно, что квадрат числа a — это всегда нечётное число. А значит и число a тоже всегда нечётное. Теперь можно легко записать выражения для a, b и c:
Часть с программированием
Напишем несколько простых функций для преобразований, которые нам понадобятся.
Малый катет a надо уметь возводить в квадрат.
function toSquare(n: number): number {
return (n ** 2);
}
Квадрат малого катета a в нашей задаче — это всегда нечётное число, а больший катет b, как видно из формулы, — это порядковый номер этого нечётного числа.
function toNatural(n: number): number {
return ((n - 1) / 2);
}
Наконец, если у нас есть больший катет b, то гипотенузу c можно получить прибавлением единицы.
function addOne(n: number): number {
return (n + 1);
}
Теперь мы можем делать все основные преобразования; осталось получить последовательность нечётных чисел. Последовательность чисел будем представлять в виде потока.
RxJS даёт достаточно много способов создания потоков, но самый подходящий нам — это функция interval()
. Она создаёт поток, который будет испускать последовательность натуральных чисел с заданным интервалом.
function generateNaturalNumbers(): Observable <number> {
return interval(500);
}
const naturalNumbers = generateNaturalNumbers();
naturalNumbers.subscribe((value) => {
console.log(value);
});
Подпишемся на созданный поток и раз в полсекунды будем получать новое натуральное число. Легко понять, как перейти к нужной нам последовательности нечётных чисел:
Для этого напишем вспомогательную функцию, которая по порядковому номеру нечётного числа будет возвращать само число. Эта функция будет обратной к функции toNatural()
.
function toOdd(n: number): number {
return ((n * 2) + 1);
}
Теперь препятствий точно не осталось!
Создадим поток с малыми катетами a. Для этого к числу из потока натуральных чисел прибавим единицу, а затем получим соответствующее нечётное число. При испускании нового натурального числа будет испускаться и новый малый катет a.
const smallCathetuses = naturalNumbers.pipe(
map(addOne),
map(toOdd),
);
Из потока с малыми катетами a, опираясь на формулы, создим поток с большими катетами b. При испускании малого катета будет испускаться соответствующий ему большой катет.
const bigCathetuses = smallCathetuses.pipe(
map(toSquare),
map(toNatural),
);
Поток с гипотенузами получить проще всего, надо всего лишь прибавить единицу к большему катету
const hypotenuses = bigCathetuses.pipe(
map(addOne),
);
Теперь у нас есть три потока: smallCathetuses
, bigCathetuses
и hypotenuses
. Если выбирать из каждого потока по последнему значению, то будем получать искомые пифагоровы тройки.
Сделать это можно с помощью функции withLatestFrom()
. Она принимает несколько потоков и возвращает массив, первый элемент которого — это элемент обрабатываемого потока, а следующие значения — это последние значения из переданных потоков.
const pythagoreanTriples = smallCathetuses.pipe(
withLatestFrom(bigCathetuses, hypotenuses),
);
Подпишемся на поток пифагоровых троек и будем наблюдать их
pythagoreanTriples.subscribe((value) => {
console.log(value);
});
// [3, 4, 5]
// [5, 12, 13]
// [7, 24, 25]
// ...
Генерация таких пифагоровых троек (где гипотенуза отличается от большего катета на единицу) имеет и практическое применение. Например, можно построить тысячеугольник, у которого все стороны и диагонали будут целыми.
Подробный алгоритм построения от Бориса Трушина
Весь код доступен на ГитХабе
P. S. За обложку спасибо Тане Лишаевой
Format-X22
Спасибо, было интересно.