|
С точки зрения функционального программирования 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 элементов:
Полный код программы - здесь.
К сожалению, код не столь красив ввиду отсутствия в PascalABC.NET полноценной реализации лямбда-функций. |