PascalABC.NET официальный канал
1.91K subscribers
599 photos
1 video
9 files
404 links
Официальный канал языка и системы программирования PascalABC.NET
Download Telegram
🧠 ML: нормализация признаков в PascalABC.NET

При подготовке данных для моделей машинного обучения часто требуется нормализовать каждый признак (столбец матрицы): вычесть среднее и поделить на стандартное отклонение. В PascalABC.NET это можно сделать компактно и полностью функционально.

function Normalize(a: array of real): array of real;
begin
var mean := a.Average;
var std := Sqrt(a.ConvertAll(x -> (x-mean)**2).Average);
Result := a.ConvertAll(x -> (x-mean)/std);
end;

function NormalizeCols(a: array[,] of real): array[,] of real
:= MatrByCol(a.Cols.ConvertAll(col -> Normalize(col)));

begin
var a := Matr([1.1,2,3],[4.3,5,6],[7.0,8,9],[5.7,2,8]);
NormalizeCols(a).Print(7,1)
end.


Нормализация столбцов — стандартный шаг при работе с датасетами: она улучшает сходимость моделей, делает признаки сопоставимыми и устраняет влияние масштаба. Благодаря функциональному стилю PascalABC.NET такие операции можно выразить очень компактно.
👍71
Copy для массивов и матриц как метод расширения

Для создания копии массивов и матриц пользуемся методом расширения Copy
4👍3
Массивы и списки - это последовательности

В PascalABC.NET есть специальный тип-последовательность - набор элементов, которые можно перебрать один за другим циклом foreach.

Если нужно написать некоторый алгоритм и перебрать элементы, то лучше использовать не конкретный тип - массив или список, а последовательность:

function SumSquares(s: sequence of integer): integer;
begin
Result := 0;
foreach var x in s do
Result += x*x;
end;

begin
SumSquares(Arr(1,2,3)).Print;
SumSquares(Lst(2,3,4)).Print;
end.
6👍1
Количество простых чисел

Как вычислить количество простых чисел, меньших заданного n?

Используем LINQ и функциональное программирование.

Два способа: обычный и с распараллеливанием.

##
function IsPrime(x: integer) := (2..x.Sqrt.Round).All(i -> x.NotDivs(i));

var n := 4000000;
(2..n).Where(IsPrime).Count.Println;
MillisecondsDelta.Println;

(2..n).AsParallel.Where(IsPrime).Count.Println;
MillisecondsDelta.Println;


Linq автоматически распараллеливает проверки для разных чисел на простоту по различным потокам.

Скорость распараллеленной версии - примерно в 6 раз меньше - значит, процессор шестиядерный.
👍9❤‍🔥1
Умножение матриц в стиле LINQ

Для умножения матриц используем метод Zip и срезы матрицы по строке и столбцу

function Dot(a1, a2: array of real): real := a1.Zip(a2,(x,y) -> x*y).Sum;

function Mult(a, b: array[,] of real): array[,] of real :=
MatrGen(a.RowCount, b.ColCount, (i,j) -> Dot(a[i,:],b[:,j]));

begin
var a := Matr([1.1,2,3],[4.3,5,6],[7.0,8,9],[5.7,2,8]);
var b := Matr([4.0,5],[8.2,4],[3.0,9]);
a.Print(7,1); Println;
b.Print(7,1); Println;
Mult(a,b).Print(7,1);
end.

Результат:

    1.1    2.0    3.0
4.3 5.0 6.0
7.0 8.0 9.0
5.7 2.0 8.0

4.0 5.0
8.2 4.0
3.0 9.0

29.8 40.5
76.2 95.5
120.6 148.0
63.2 108.5
👍5🤩2
🔧 Замена текста внутри квадратных скобок

Если требуется заменить текст внутри [...], можно воспользоваться методами строк IndexOf, Remove и Insert.

Первую открывающую скобку ищем до цикла, а в самом цикле переходим к следующей уже со строки позиции конечной скобки.
begin
var s := 'Клад зарыт на [юго-западе] под [пальмой]';
var replaceStr := 'скрыто';

var startPos := s.IndexOf('[');
while startPos <> -1 do
begin
var endPos := s.IndexOf(']', startPos + 1);
if endPos = -1 then break;

s := s.Remove(startPos + 1, endPos - startPos - 1);
s := s.Insert(startPos + 1, replaceStr);

startPos := s.IndexOf('[', endPos); // безопасно в PascalABC.NET
end;

Println(s);
end.

Приём подходит для любой задачи, где нужно обработать фрагменты между парными символами.
👍9
Находим элементы, встречающиеся в последовательности ровно один раз

Используем два множества: одно для потенциально уникальных значений, второе — для повторяющихся.

begin
var data := [1, 2, 3, 2, 4, 5, 3, 6, 7, 1, 8, 9, 4, 10];
data.Println;

var unique, multi: set of integer;

foreach var num in data do
begin
if num in multi then
continue;
if num in unique then
begin
unique -= num;
multi += num;
end
else unique += num;
end;

unique.Order.Println;
end.


Ровно один раз встретившиеся элементы выводятся в отсортированном виде.
👍9
Решето Эратосфена - максимально компактно и понятно

Решето Эратосфена — это один из наиболее эффективных алгоритмов для нахождения всех простых чисел до заданного предела n. Он отличается высокой производительностью и простотой реализации.

Алгоритм обладает асимптотической сложностью O(n * log ⁡log ⁡n), что делает его значительно быстрее простейших методов определения простоты через деление.

##
function SieveOfEratosthenes(n: integer): array of integer;
begin
var isPrime := [False] * 2 + [True] * (n - 1);

for var i := 2 to ISqrt(n) do
if isPrime[i] then
for var j := i * i to n step i do
isPrime[j] := False;

Result := (2..n).Where(i -> isPrime[i]).ToArray;
end;

SieveOfEratosthenes(1000).Println;


А что такое ISqrt(n) - читайте в справке!
4👍2🔥1
Фабрика предикатов

Напишем функцию, которая возвращает лямбду-предикат с параметром. Функция принимает параметр, лямбда его захватывает.

В результате вместо лямбды можно писать вызов функции с параметром

function less(a: integer): integer -> boolean
:= x -> x < a;

begin
Arr(1..9).Where(less(5)).Print
end.
🔥6👍3
2000 подписчиков в нашем телеграм-канале!

Прямо сейчас: нас - 2000!
👉 https://tgstat.ru/channel/@pascalabc_official/stat

И это особенно приятно, потому что канал растёт естественно:
🔹без накруток
🔹без покупной рекламы
🔹без «случайных» подписчиков

Здесь собираются те, кому действительно интересен современный PascalABC.NET:
🔹живые примеры кода
🔹новые возможности языка
🔹приёмы, о которых не пишут в учебниках
🔹актуальные подходы и современные парадигмы программирования

Спасибо каждому, кто читает, думает, пробует и пишет код на PascalABC.NET вместе с нами 🚀
🎉23👍97🔥1👏1🤗1
Без слов :)
🤓15😁2👍1😐1
match — это case по типам

В современном PascalABC.NET можно элегантно обрабатывать значение в зависимости от его типа, а не только от значения.

begin
var obj: object := 'Hello PascalABC.NET!';

match obj with
integer(i): Println(i * i);
string(s): Println(s.Length);
else Println(TypeName(obj));
end;
end.

Что важно:
🔹выбор ветки происходит по типу объекта
🔹при совпадении тип сразу доступен в переменной (i, s)
🔹код получается короче и понятнее, чем цепочки if obj is ...

По сути, это case, который работает с типами.
👍11🔥1
Сколько слов в строке каждой длины

Если строка состоит из слов, легко посчитать, сколько слов каждой длины, используя комбинацию методов GropupBy и Each. Метод Each возвращает словарь, который можно отсортировать по ключу и вывести

begin  
var s := 'как однажды жак звонарь головой сломал фонарь';
s.ToWords
.GroupBy(word -> word.Length)
.Each(word -> word.Count)
.OrderBy(kv -> kv.Key)
.PrintLines(kv -> $'{kv.Key}-буквенных - {kv.Value} шт')
end.
🥰5👍21
🎄 С Новым 2026 годом!

Друзья, с наступающим Новым годом!

Спасибо, что этот год вы провели вместе с PascalABC.NET — в обсуждении задач, примеров, поиске красивых решений.

Пусть в 2026 году:

🔷 код будет читаемым и лаконичным,
🔶 типы станут надёжной путеводной звездой,
🔷 алгоритмы — интересными и быстрыми,
🔶 а изучение программирования будет приносить удовольствие и уверенность в результате.

В новом году мы планируем важный шаг — перевод PascalABC.NET на .NET 9.0 и дальнейшее развитие инструментов для обучения современному программированию.

Спасибо, что остаетесь с нами, делитесь идеями и проблемами, задаёте вопросы и используете PascalABC.NET в обучении и работе.

До встречи в 2026 году — он уже почти скомпилировался :)
🎄259🔥4
Метод последовательности FirstOrDefault

Метод последовательности FirstOrDefault позволяет заменять цикл с break. Он работает лениво и выходит из вычислений в тот момент как найден элемент, удовлетворяющий условию - всё как в цикле break.

Единственный недостаток - в случае неудачи возвращает значение по умолчанию - данном случае 0.

begin
var a := ArrRandomInteger(20,1,20);
a.Println;
var res := a.FirstOrDefault(x -> x > 17);
Print(res);

res := 0;
foreach var x in a do
if x > 17 then
begin
res := x;
break;
end;
Print(res);
end.
👍84
Во всех ли строках матрицы есть четные элементы?

Решение с помощью комбинации методов All и Any

begin
var a := MatrRandom(5,3);
a.Println;
a.Rows.All(row -> row.Any(x -> x.IsEven)).Print;
end.
9👍1
Прямо сейчас студенты 1 курса ФИИТ сдают экзамен по Основам программирования.

И подошли к делу очень творчески :)

Оценка - отлично!
👍319😁9❤‍🔥3🥰1
Лаконичные вычисления для матриц

Насколько выразительной и компактной может быть запись алгоритмов, в которых сначала вычисляется некоторая характеристика строк или столбцов матрицы, а затем — агрегированная характеристика по всем полученным значениям!

Например, одной строкой можно найти максимум сумм строк матрицы.

Точно так же просто вычисляется среднее значение минимумов её столбцов.

begin
var a := MatrRandom;
a.Println;
// Максимум сумм строк
a.Rows.Max(row -> row.Sum).Println;
// Среднее минимумов столбцов
a.Cols.Average(col -> col.Min).Println;
end.
👍6
Связка методов GroupBy и Each - словарь характеристик групп

Открываем красоту LINQ в сочетании с элегантностью PascalABC.NET. Смотрите, как легко делать аналитику данных:

type 
Product = auto class
Category: string;
Model: string;
Price: real;
Rating: real;
end;

begin
var products :=
[
new Product('Phones', 'iPhone 13', 499.99, 4.5),
new Product('Phones', 'Galaxy S21', 699.99, 4.7),
new Product('Phones', 'iPhone 13', 299.99, 4.2),
new Product('Laptops', 'MacBook', 999.99, 4.8),
new Product('Laptops', 'MacBook', 1299.99, 4.9),
new Product('Tablets', 'iPad Air', 399.99, 4.3),
new Product('Tablets', 'iPad Air', 399.99, 4.3)
];

// 1. Количество уникальных моделей по категориям
var uniqueModels := products
.GroupBy(p -> p.Category)
.Each(g -> g.DistinctBy(p -> p.Model).Count);

// 2. Средняя цена по категориям
var avgPrices := products
.GroupBy(p -> p.Category)
.Each(g -> g.Average(p -> p.Price));

// 3. Количество товаров по категориям
var totalCounts := products
.GroupBy(p -> p.Category)
.Each(g -> g.Count);

Println('Уникальные модели по категориям:');
uniqueModels.PrintLines(kv -> $' {kv.Key}: {kv.Value}');

Println('Средняя цена по категориям:');
avgPrices.PrintLines(kv -> $' {kv.Key}: ${kv.Value:F2}');

Println('Всего товаров по категориям:');
totalCounts.PrintLines(kv -> $' {kv.Key}: {kv.Value}');
end.


Почему этот подход — находка:

🎯 .GroupBy() + .Each() — идеальная пара для групповых операций
🎯 Автоматический словарь — .Each() сам возвращает Dictionary<K,V>
🎯 Читаемость — код говорит сам за себя: "сгруппируй и для каждой группы посчитай"
🎯 Расширяемость — подходит для любых агрегаций: Average, Sum, Min, Max, DistinctBy

Современный PascalABC.NET - для реальной аналитики данных!
12👍3
Новый стандартный модуль DataFrameABC

В PascalABC.NET 3.11.1 beta появился модуль DataFrameABC для работы с датафреймами.

Он совмещает идеи pandas и преимущества компилируемых языков.

Возможности:
4 типа столбцов: Int, Str, Bool, Float
Считывание из CSV и текстовой строки
И многое другое...

Пример 1. Загрузка и просмотр данных

uses DataFrameABC;

begin
var df := DataFrame.FromCsvText('''
name,age,score
Alice,20,85
Bob,22,90
Charlie,21,78
''');

df.Print;
end.


#DataFrameABC
🔥138
Модуль DataFrameABC - выбор столбцов

Выбор столбцов в новом эффективном модуле DataFrameABC делается с помощью метода Select с указанием массива выбираемых столбцов.

Возвращается View в виде нового датафрейма

uses DataFrameABC;

begin
var df := DataFrame.FromCsvText('''
name,age,score
Alice,20,85
Bob,22,90
Charlie,21,78
''');

df.Select(['name', 'score']).Print;
end.


#DataFrameABC
👍9