С точки зрения функционального программирования PascalABC.NET - плохой язык. Однако, некоторые идеи, тем не менее, могут быть реализованы в функциональном стиле. На них и остановимся.
В качестве объекта изложения возьмем алгоритм получения следующего числа в цепочке в задаче 74 из проекта Эйлера.
Каждый следующий член цепочки получается из предыдущего как сумма факториалов его цифр:
1!+6!+9! =363601
169 363601 1454 169
Вначале разобьём целое на массив цифр. Сделаем это с помощью метода расширения для integer. Алгоритм - безобразно неоптимальный:
type IntArray = array of integer; function integer.ToDigits(): IntArray; begin var s := Self.ToString(); SetLength(Result,s.Length); for var i := 1 to s.Length do Result[i-1] := OrdUnicode(s[i])-OrdUnicode('0'); end;
Для массива целых составим метод расширения, вычисляющий сумму элементов:
function IntArray.Sum(): integer; begin Result := 0; for var i := 0 to Self.Length-1 do Result += Self[i]; end;
Для вывода массива целых на экран расширим его тип методом Print:
procedure IntArray.Print; begin for var i := 0 to Self.Length-1 do write(Self[i],' '); end;
Наконец, напишем метод расширения для преобразования массива целых в массив целых, воздействуя на каждый элемент функцией, передаваемой в качестве параметра:
type IntFun = function (i: integer): integer; function IntArray.Map(f: IntFun): IntArray; begin SetLength(Result,Self.Length); for var i := 0 to Self.Length-1 do Result[i] := f(Self[i]); end;
Проверяем:
function fact(n: integer): integer; begin Result := 1; for var i:=1 to n do Result *= i; end; begin var i := 145; writeln(i.ToDigits().Map(fact).Sum()); end.
Выводится 145 (145=1!+4!+5!)
Выведем 4 члена цепочки, начинающейся со 169. Для этого реализуем функцию перехода к следующему элементу:
function Next(i: integer): integer; begin Result := i.ToDigits().Map(fact).Sum(); end;
Наконец, реализуем для данного целого функцию получения цепочки целых с указанной функцией перехода к следующему элементу:
function integer.Take(f: IntFun; n: integer): IntArray; begin SetLength(Result,n); Result[0] := Self; for var i:=1 to n-1 do Result[i] := f(Result[i-1]); end;
Пробуем:
begin var i := 169; i.Take(Next,4).Print(); end.
Получаем цепочку из 4 элементов:
169 363601 1454 169
К сожалению, код не столь красив ввиду отсутствия в PascalABC.NET полноценной реализации лямбда-функций.
10.07.23. Release PascalABC.NET 3.9.0. All changes are here.
09.03.22. Release PascalABC.NET 3.8.3. Main features: for loop with step, foreach loop with index. All changes are here.
07.02.22. Release PascalABC.NET 3.8.2. What's new in 3.8.2.
24.08.21. Release PascalABC.NET 3.8.1. Main features - [Cache] attribute and PlotWPF unit. What's new in version 3.8.1.
07.03.21. PascalABC.NET 3.8 release. Slices of multidimensional arrays and unpacking of lambda expressions parameters into variables. What's new in version 3.8..