uk
Feedback
PascalABC.NET официальный канал

PascalABC.NET официальный канал

Відкрити в Telegram

Официальный канал языка и системы программирования PascalABC.NET

Показати більше
1 864
Підписники
-624 години
-57 днів
-2330 днів
Архів дописів
Новый метод последовательностей DistinctAdjacent В стандартной библиотеке последовательностей появился новый метод: DistinctAdjacent. Он удаляет только подряд идущие одинаковые элементы, в отличие от обычного Distinct, который убирает все повторы. Пример с числами
begin
  Seq(1,1,2,2,2,3,1,1).DistinctAdjacent.Println
end.
Результат:
1 2 3 1
Пример со строкой
begin
  var s := 'aaabbbcca'.ToCharArray;
  s.DistinctAdjacent.Println
end.
Результат:
a b c a
Пример с логами
begin
  var logs := Seq('INFO','INFO','WARN','WARN','ERROR','INFO');
  logs.DistinctAdjacent.Println
end.
Результат:
INFO WARN ERROR INFO
Когда это полезно * очистка логов от повторяющихся подряд сообщений * сжатие последовательностей (run-length preprocessing) * обработка сигналов и данных с “залипанием” значений Метод работает за один проход и не требует дополнительной памяти под множество — только сравнение с предыдущим элементом. #новое

Scan в PascalABC.NET — строим путь по шагам Одна из самых недооценённых функций в работе с последовательностями — это Scan. О
Scan в PascalABC.NET — строим путь по шагам Одна из самых недооценённых функций в работе с последовательностями — это Scan. Она позволяет не просто «посчитать итог», а увидеть, как меняется состояние на каждом шаге. 📌 Пример — строим путь по последовательности шагов:
begin
  var steps := Seq((1,0),(0,1),(1,0),(0,-1),(0,-1),(-1,0),(0,1),(0,1));

  steps.Scan((p, step) -> (p[0] + step[0], p[1] + step[1])).Print
end.
📊 Что происходит: (1,0) → старт затем добавляем каждый следующий шаг получаем всю траекторию движения 👉 Результат — последовательность координат: (1,0) (1,1) (2,1) (2,0) (2,-1) (1,-1) (1,0) (1,1)

🔍 Поиск выхода из лабиринта (DFS + backtracking) Классическая задача: есть лабиринт → нужно найти путь от старта к выходу. Р
🔍 Поиск выхода из лабиринта (DFS + backtracking) Классическая задача: есть лабиринт → нужно найти путь от старта к выходу. Решение — через DFS с откатом (backtracking): * идём в глубину * помечаем посещённые вершины * если зашли в тупик — откатываемся назад
function FindPath(graph: List<List<integer>>; visited: array of boolean;
  path: List<integer>; v, finish: integer): boolean;
begin
  path.Add(v);
  visited[v] := True;
  
  if v = finish then
    exit(True);
  
  foreach var toV in graph[v] do
    if not visited[toV] then
      if FindPath(graph, visited, path, toV, finish) then
        exit(True);
  
  path.RemoveAt(path.Count - 1);
  Result := False;
end;

begin
  // 3x3 лабиринт (граф)
  var graph := Lst(
    Lst(1,3),
    Lst(0,2,4),
    Lst(1,5),
    Lst(0,4,6),
    Lst(1,3,5),
    Lst(2,4,8),
    Lst(3,7),
    Lst(6,8),
    Lst(5,7)
  );

  var n := graph.Count;
  
  var visited := n *[False];   
  var path := new List<integer>;

  if FindPath(graph, visited, path, 0, 8) then
    Println(path.JoinToString(' -> '))
  else
    Println('No path');
end.
💡 Что важно: * path.RemoveAt(...) — ключевой шаг отката * Lst(...) удобно задаёт граф декларативно 📌 Такой код — отличный мост: школьные задачи → графы → алгоритмы поиска → основы AI/ML

🌳 Рекурсия на примере идеально сбалансированного дерева type Node = auto class public Value: T; Left, Right: Node; end; func
🌳 Рекурсия на примере идеально сбалансированного дерева
type
  Node<T> = auto class
  public
    Value: T;
    Left, Right: Node<T>;
  end;

function RandomTree(n: integer): Node<integer>;
begin
  if n = 0 then
    Result := nil
  else
    Result := new Node<integer>(
      Random(100),
      RandomTree((n - 1) div 2),
      RandomTree(n - 1 - (n - 1) div 2)
    );
end;

procedure Infix<T>(r: Node<T>; act: Action<T>);
begin
  if r = nil then exit;
  Infix(r.Left, act);
  act(r.Value);
  Infix(r.Right, act);
end;

begin
  var root := RandomTree(10);
  Infix(root, x -> Print(x));
end.
💡 Что здесь происходит 1. Идеально сбалансированное дерево Функция RandomTree(n) строит дерево из n узлов так, чтобы: * левое поддерево получает (n - 1) div 2 узлов * правое — остальные Разница размеров поддеревьев не больше 1 ⇒ дерево максимально «ровное» по высоте. 2. Рекурсия * База: n = 0 → nil * Шаг: создаём узел и рекурсивно строим левое и правое поддеревья То же самое в обходе: * если узел пустой — выходим * иначе обходим левое поддерево → текущий узел → правое 3. Инфиксный обход (LNR) Порядок: 👉 Left → Node → Right Это означает: * сначала все элементы слева * затем текущий * затем справа #pascalabc #рекурсия #деревья

Гистограмма распределения цен uses MLABC, PlotML; begin var ds := Datasets.MoscowHousing; var df := ds.Data; var price := df.
Гистограмма распределения цен
uses MLABC, PlotML;

begin
  var ds := Datasets.MoscowHousing;
  var df := ds.Data;

  var price := df.ToVector(ds.Target);

  Plot.Hist(price, bins := 40);
  Plot.Title := 'Распределение цен на квартиры в Москве';
  Plot.XLabel('Цена (руб)');
  Plot.YLabel('Количество');
end.
Гистограмма показывает, как часто встречаются значения из набора данных. В данном случае: • по оси X — цена квартиры • по оси Y — количество квартир с такой ценой Каждый столбец (bin) — это интервал цен. По гистограмме можно: • понять, в каком диапазоне находится большинство значений • увидеть редкие значения (очень дешёвые или очень дорогие квартиры) • оценить форму распределения (например, симметричное или с «длинным хвостом» вправо) Это базовый инструмент анализа данных перед построением моделей.

Машинное обучение в PascalABC.NET: логистическая регрессия Продолжаем серию практических постов по ML-библиотеке в PascalABC.
Машинное обучение в PascalABC.NET: логистическая регрессия Продолжаем серию практических постов по ML-библиотеке в PascalABC.NET. В этом посте — первый полный пример: обучение и применение модели. Разберём пример на классическом датасете Iris 🌸
uses MLABC;

begin
  var ds := Datasets.Iris;
  var df := ds.Data;

  var X := df.ToMatrix(ds.Features);
  var y := df.EncodeLabels(ds.Target);

  var (Xtrain, Xtest, ytrain, ytest) :=
    Validation.TrainTestSplit(X, y, 0.2, 1);

  var model := new LogisticRegression;

  model.Fit(Xtrain, ytrain);

  var pred := model.Predict(Xtest);

  Println('Accuracy:', Metrics.Accuracy(ytest, pred):0:3);
end.
🔍 Что здесь происходит 1. Загрузка данных ▪️ Datasets.Iris — встроенный датасет ▪️ df — табличное представление (DataFrame) 2. Подготовка признаков ▪️ ToMatrix → преобразование в Matrix (числовое ядро) ▪️ EncodeLabels → кодирование классов в Vector<int> 3. Разбиение ▪️ TrainTestSplit → контроль воспроизводимости через seed 4. Модель ▪️ LogisticRegression ▫️ мультиклассовая (softmax) ▫️ работает через Matrix/Vector ▫️ типобезопасная реализация 5. Обучение и предсказание ▪️ Fit → обучение ▪️ Predict → классы 6. Метрика ▪️ Metrics.Accuracy → базовая проверка качества 💡 Важно Это не “обёртка над Python”, а нативная ML-библиотека на PascalABC.NET: ▪️ все шаги явно прописаны в коде (нет скрытых преобразований) ▪️ данные и модели имеют строгие типы (Matrix, Vector<int>) ▪️ результат полностью воспроизводим (за счёт фиксированного seed)

📊 Синтетические датасеты в PascalABC.NET: MakeBlobs Иногда для демонстрации алгоритмов или отладки ML-моделей нужны простые
📊 Синтетические датасеты в PascalABC.NET: MakeBlobs Иногда для демонстрации алгоритмов или отладки ML-моделей нужны простые и наглядные данные. Вместо поиска реальных датасетов удобно генерировать их самостоятельно. В модуле MLABC есть классический генератор — MakeBlobs. Он создаёт точки, сгруппированные в кластеры (как в задачах кластеризации и классификации). 🔹 Что делает MakeBlobs: * генерирует заданное число точек * разбивает их на кластеры * добавляет контролируемый шум * возвращает: * X — координаты точек * y — метки кластеров 🔹 Пример + визуализация через PlotML:
uses MLABC, PlotML;

begin
  var centers := 3;
  var (X,y) := Datasets.MakeBlobs(
    n := 600,
    centers := centers,
    clusterStd := 0.8,
    seed := 1
  );

  Plot.Title := 'MakeBlobs синтетический датасет';
    
  var xs := X.Col(0);
  var ys := X.Col(1);
  
  Plot.Points(xs, ys, LabelsToInts(y), size := 4);
end.
🔹 Ключевые параметры: * n — число точек * centers — число кластеров * clusterStd — разброс внутри кластера * seed — фиксирует генерацию (важно для воспроизводимости) 💡 Где это полезно: * объяснение кластеризации (k-means, DBSCAN) * тестирование моделей классификации * демонстрации на лекциях * отладка пайплайнов

📊 Синтетические датасеты в PascalABC.NET: MakeBlobs Иногда для демонстрации алгоритмов или отладки ML-моделей нужны простые
📊 Синтетические датасеты в PascalABC.NET: MakeBlobs Иногда для демонстрации алгоритмов или отладки ML-моделей нужны простые и наглядные данные. Вместо поиска реальных датасетов удобно генерировать их самостоятельно. В модуле MLABC есть классический генератор — MakeBlobs. Он создаёт точки, сгруппированные в кластеры (как в задачах кластеризации и классификации). 🔹 Что делает MakeBlobs: * генерирует заданное число точек * разбивает их на кластеры * добавляет контролируемый шум * возвращает: * X — координаты точек * y — метки кластеров 🔹 Пример + визуализация через PlotML:
uses MLABC, PlotML;

begin
  var centers := 3;
  var (X,y) := Datasets.MakeBlobs(
    n := 600,
    centers := centers,
    clusterStd := 0.8,
    seed := 1
  );

  Plot.Title := 'MakeBlobs синтетический датасет';
    
  var xs := X.Col(0);
  var ys := X.Col(1);
  
  Plot.Points(xs, ys, LabelsToInts(y), size := 4);
end.
🔹 Ключевые параметры: * n — число точек * centers — число кластеров * clusterStd — разброс внутри кластера * seed — фиксирует генерацию (важно для воспроизводимости) 💡 Где это полезно: * объяснение кластеризации (k-means, DBSCAN) * тестирование моделей классификации * демонстрации на лекциях * отладка пайплайнов

ML в PascalABC.NET — старт В PascalABC.NET появилась новая библиотека машинного обучения — ML PascalABC.NET. Она спроектирова
ML в PascalABC.NET — старт В PascalABC.NET появилась новая библиотека машинного обучения — ML PascalABC.NET. Она спроектирована как полноценный промышленный стек: с чёткой архитектурой, типобезопасностью и без внешних зависимостей. Начинаем с базовых примеров. 📊 Стандартный датасет Iris + PairPlot визуализация
uses MLABC, PlotML;

begin
  var ds := Datasets.Iris;
  var df := ds.Data;
  
  var X := df.ToMatrix(ds.Features);
  var labels := df.EncodeLabels(ds.Target);

  Plot.PairPlot(X, labels, ds.Features);

  Plot.Title := 'Iris: пары признаков';
end.
💡 Что здесь важно: — Загрузка готового датасета (Datasets.Iris) — Работа через DataFrame (ds.Data) — Выделение матрицы признаков (ToMatrix) — Кодирование целевой переменной (EncodeLabels) — Визуализация через PairPlot 📌 PairPlot — базовый инструмент разведочного анализа данных (EDA): он показывает распределения признаков и их попарные зависимости, что позволяет быстро увидеть структуру данных и разделимость классов. Дальше будут: — обучение моделей — метрики — пайплайны — практические кейсы Начинаем двигаться к полноценному ML прямо в PascalABC.NET.

PrintPreview для DataFrame Обратите внимание, как выводит данные PrintPreview: выводится 3 строки - примерно половина из нача
PrintPreview для DataFrame Обратите внимание, как выводит данные PrintPreview: выводится 3 строки - примерно половина из начала датасета и оставшаяся часть - из конца.
uses DataFrameABC;

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

Left Join в DataFrameABC Ранее мы показывали Inner Join — он оставляет только те строки, для которых ключи есть в обеих табли
Left Join в DataFrameABC Ранее мы показывали Inner Join — он оставляет только те строки, для которых ключи есть в обеих таблицах. Теперь посмотрим на Left Join, который ведёт себя иначе. Left Join сохраняет все строки из левой таблицы, даже если для них нет совпадения в правой.
// Left Join
uses DataFrameABC;

begin
  var students := DataFrame.FromCsvText('''
  id,name
  1,Alice
  2,Bob
  3,Charlie
  ''');
  
  var scores := DataFrame.FromCsvText('''
  id,score
  1,85
  2,90
  4,70
  ''');
  
  students.Join(scores, 'id', jkLeft).Print;
end.
Результат:
id     name  score
 1    Alice     85
 2      Bob     90
 3  Charlie     NA
Здесь: * Alice и Bob получили свои score * Charlie сохранился, но значение scoreNA * строка id = 4 из таблицы scores не попала в результат Это главное отличие от Inner Join, где строка Charlie исчезла бы из результата.

Inner Join в DataFrameABC Иногда данные находятся в разных таблицах, и их нужно объединить по общему ключу. Для этого использ
Inner Join в DataFrameABC Иногда данные находятся в разных таблицах, и их нужно объединить по общему ключу. Для этого используется Inner Join — соединение, которое оставляет только те строки, где ключ присутствует в обеих таблицах.
// Inner Join
uses DataFrameABC;

begin
  var students := DataFrame.FromCsvText('''
  id,name
  1,Alice
  2,Bob
  3,Charlie
  ''');
  
  var scores := DataFrame.FromCsvText('''
  id,score
  1,85
  2,90
  4,70
  ''');
  
  students.Join(scores, 'id').Print;
end.
Результат:
id  name   score
1   Alice  85
2   Bob    90
Что произошло: * соединение выполняется по столбцу id * строка id = 3 отсутствует в таблице scores, поэтому она исключается * строка id = 4 отсутствует в таблице students, поэтому она тоже исключается Таким образом, Inner Join оставляет только пересечение ключей. Такой тип соединения — один из самых используемых в анализе данных: объединение пользователей и заказов, студентов и оценок, товаров и продаж и т.д. #MachineLearning

DataFrameABC - группировка с последующим вычислением групповой операции В DataFrame можно сгруппировать данные по какому то с
DataFrameABC - группировка с последующим вычислением групповой операции В DataFrame можно сгруппировать данные по какому то столбцу, после чего вычислить какую-нибудь групповую характеристику для элементов группы. На скрине - вычисление среднего score в каждой группе людей с одним возрастом.

DataFrameABC - Describe по столбцу В DataFrame все числовые статистики по столбцу можно вычислить с помощью метода Describe.
DataFrameABC - Describe по столбцу В DataFrame все числовые статистики по столбцу можно вычислить с помощью метода Describe. Возвращается запись, содержащая поля Count, Min, Max, Mean, Std

DataFrameABC - простые статистики по столбцу В DataFrame можно просто вычислить простейшие статистики по числовым столбцам -
DataFrameABC - простые статистики по столбцу В DataFrame можно просто вычислить простейшие статистики по числовым столбцам - в стиле pandas

Фрактальная L-кривая Sierpinski Arrowhead Отвлечемся от ML - и посмотрим на красоту фрактальных кривых. Перед нами - Sierpins
Фрактальная L-кривая Sierpinski Arrowhead Отвлечемся от ML - и посмотрим на красоту фрактальных кривых. Перед нами - Sierpinski Arrowhead Модуль Turtle позволяет масштабировать мышью изображение.
uses Turtle,GraphWPF;

var 
  Atom,FStr,XStr,YStr: string;
  angle,len,x0,y0: real;
  n: integer;

procedure Init5; // Sierpinski Arrowhead
begin
  (Atom,FStr,XStr,YStr) := ('X', 'F', 'YF+XF+Y', 'XF-YF-X');
  (angle,len,n,x0,y0) := (60,0.1,9,1,1);
end;

procedure RunStr(s: string; n: integer);
begin
  foreach var c in s do
    case c of
      '+': Turn(angle);
      '-': Turn(-angle);
      'f','F': if n>0 then RunStr(FStr,n-1) else Forw(len);
      'x','X': if n>0 then RunStr(XStr,n-1);
      'y','Y': if n>0 then RunStr(YStr,n-1);
      else Print('error')
    end;
end;

begin
  Init5;
  x0 := -10;
  y0 := -10;
  ToPoint(x0,y0);
  SetWidth(0.5);
  Down;
  RunStr(Atom,n);
  Up;
end.

Модуль DataFrameABC - добавление нового вычисляемого столбца Можно добавлять новые вычисляемые столбцы с помощью WithColumn..
Модуль DataFrameABC - добавление нового вычисляемого столбца Можно добавлять новые вычисляемые столбцы с помощью WithColumn... В примере показано, как добавить вычисляемый столбец passed, который принимает значение True для тех, у кого score >= 80. Создается новый датафрейм, но данные создаются только для нового столбца. #DataFrameABC

Модуль DataFrameABC - фильтрация с пропущенными данными Пропущенные данные в SCV-файле обозначаются как NA либо просто пустым
Модуль DataFrameABC - фильтрация с пропущенными данными Пропущенные данные в SCV-файле обозначаются как NA либо просто пустым элементом. У курсора row есть метод, позволяющий проверять, пропущены ли данные в этом столбце. В примере - фильтрация по строкам, в которых не пропущены данные в столбце score #DataFrameABC

Модуль DataFrameABC - фильтрация Для фильтрации строк используется метод Filter. Возвращается новый датафрейм. Вызов - в стил
Модуль DataFrameABC - фильтрация Для фильтрации строк используется метод Filter. Возвращается новый датафрейм. Вызов - в стиле LINQ, однако row здесь имеет тип DataFrameCursor - курсор, перемещающийся по данным. #DataFrameABC

Модуль DataFrame - скорость считывания данных из CSV Считывание данных из CSV оптимизировано. В примере - файл с 1 миллионом
Модуль DataFrame - скорость считывания данных из CSV Считывание данных из CSV оптимизировано. В примере - файл с 1 миллионом строк и 20 столбцами разных типов считывается за 1.2 секунды. Этот же файл в pandas считывается за 0.65 сек - здесь код написан на C++, поэтому быстрее, но не намного. В примере вы также видите другие параметры Load - разделители между данными, режим наличия заголовка и режим строгой проверки на ошибки #DataFrameABC