PascalABC.NET официальный канал
رفتن به کانال در Telegram
Официальный канал языка и системы программирования PascalABC.NET
نمایش بیشتر1 860
مشترکین
-424 ساعت
-97 روز
-2530 روز
آرشیو پست ها
Регулярные выражения в задачах ЕГЭ
Продолжаем публиковать задачи из доклада Ипатова Ю.А. о регулярных выражениях.
Мы немного переделали решение
##
'КОСУФ'.
.CartesianPower(5)
.Numerate
.Where(t -> t[1].IsMatch('\b[^Ф]+\b'))
.Where(t -> t[1].CountOf('У') = 2)
.Last
.Print;
Буквы слова вначале выстраиваются в алфавитном порядке, потом берется их декартова степень, нумеруется и затем к каждому слову применяется регулярное выражение \b[^Ф]+\b
\b означает, мы ищем подстроку на границе слова,
[^Ф] - означает, что это любая буква кроме Ф, [^Ф]+ - она повторяется 1 или более раз
Вывод:
(2313,УУССС)Таким образом, последнее такое слово имеет номер 2313
Регулярные выражения в действии
Начинаем публиковать интересные выдержки из докладов участников конференции.
Замечательный доклад Ипатова Ю.А. об использовании регулярных выражений в задачах ЕГЭ.
Задача - на слайде.
Решение:
##
'ОДЕКОЛОН'
.Permutations
.Where(x->not x.IsMatch('(.)\1'))
.ToSet
.Count
.Print;
Расшифровка регулярного выражения:
(.)
🔹 Круглые скобки () создают группу захвата — то есть сохраняют найденное.
🔹 Точка . означает любой один символ.
🔹 В итоге (.) — это первая группа, в которую попадает любой символ.
\1
🔹 Это ссылка на первую захваченную группу.
🔹 То есть \1 означает: тот же символ, что и в первой группе.
Вместе (.)\1 означает: любой символ, за которым сразу следует точно такой же.Операции ?. и ?? в PascalABC.NET
Операции ?. и ?? позволяют избежать исключения NullReferenceException при работе с возможными nil-значениями. Они упрощают код, убирая необходимость вручную проверять переменные перед доступом к их полям.
🔹 ?. – безопасный доступ к полю объекта. Если объект nil, выражение возвращает nil, а не вызывает ошибку.
🔹 ?? – оператор "если nil", который заменяет nil значением по умолчанию.
Пример:
type
Student = auto class
name: string;
age: integer;
end;
begin
var s: Student := nil;
var name := s?.name; // Если s = nil, то name = nil
var age := s?.age ?? -1; // Если s = nil, то age = -1
Println(name, age);
s := new Student('Иванов', 18);
name := s?.name;
age := s?.age ?? -1;
Println(name, age);
end.
Раньше приходилось писать так:
if s <> nil then name := s.name else name := nil;
if s <> nil then age := s.age else age := -1;Пятая конференция "Использование системы программирования PascalABC.NET в обучении программированию"
До начала конференции - 21 час
Программа конференции: http://pascalabc.net/downloads/PABCConf2025/ConfPABCProgram_2025.pdf
Ссылки на трансляцию:
День 1 (28.03.2025):
https://vkvideo.ru/video-199884162_456239018
https://youtube.com/live/3fWOQ92-Rrc?feature=share
День 2 (29.03.2025):
https://vkvideo.ru/video-199884162_456239019
https://youtube.com/live/ypKlIpIhR_w?feature=share
Машинное обучение на PascalABC.NET.
Часть 6. Нейронная сеть прямого распространения
Нейронная сеть прямого распространения — это один из базовых типов искусственных нейронных сетей, где информация движется только в одном направлении: от входного слоя через скрытые слои к выходному.
🔹 Как это работает?
- Входные данные подаются на входной слой.
- Данные последовательно обрабатываются нейронами скрытых слоев с использованием весов и функций активации.
- Результат выдается на выходном слое.
Настоящая программа, сгенерированная Deepseek, иллюстрирует великолепную точность на стандартном датасете breast-cancer.csv.
begin
// Загрузка данных (первый столбец - Target: 1 - заболевание, 0 - нет)
var dataset := new DataSet('Datasets/breast-cancer.csv',True,',',1);
var (trainSet, testSet) := dataset.TrainTestSplit(0.8);
var scaler := new Scaler();
trainSet.Features := scaler.FitTransform(trainSet.Features);
testSet.Features := scaler.Transform(testSet.Features);
var model := new NeuralNetwork(trainSet.Features[0].Length, 10, 0.01);
model.Fit(trainSet, epochs := 1000);
var yPred := model.Predict(testSet.Features);
var acc := model.Accuracy(testSet.Target.Select(y -> Round(y)).ToArray(), yPred);
Println($'Accuracy: {acc:0.00}');
end.Решение системы линейных уравнений с помощью Mathnet.Numerics.dll
Мощная библиотека Mathnet.Numerics.dll позволяет решать систему линейных уравнений. Типы матрицы и вектора там особые, поэтому требуется преобразование в обе стороны.
{$reference Mathnet.Numerics.dll}
uses Mathnet.Numerics.LinearAlgebra;
begin
var A := Matrix&<double>.Build.DenseOfArray(Matr(
[3.0, 2, -1],
[2.0, -2, 4],
[-1, 0.5, -1]));
var b := Vector&<double>.Build.Dense([1.0, -2, 0]);
var x := A.Solve(b);
Print(x.ToArray);
end.Успехи китайского ИИ
Первый промпт к DeepSeek:
"Напиши решето Эратосфена в PascalABC.NET, используя функциональный стиль."
Второй промпт к DeepSeek:
"А короче и без комментариев?"
Ответ (безошибочный!):
function Sieve(n: integer) :=
Range(2, n)
.Where(x -> Range(2, Trunc(Sqrt(x)))
.All(y -> x mod y <> 0))
.ToArray();
begin
Sieve(50).Println;
end.МОС Линукс и версия PascalABC.NET 3.10.3
МОС Линукс первая из российских линуксов обновила версию PascalABC.NET до 3.10.3.
https://school.mos.ru/app/#/applications/234
Машинное обучение на PascalABC.NET.
Часть 5. Метод k ближайших соседей
Метод k ближайших соседей (kNN) — это один из простейших алгоритмов машинного обучения, который используется для задач классификации и регрессии. В его основе лежит принцип, что объект относится к тому классу, которому принадлежит большинство из k ближайших к нему соседей в пространстве признаков.
В качестве примера мы использовали стандартный набор данных об ирисах Фишера, содержащий три класса (виды ирисов), сбалансированные по количеству объектов. Данные были разделены на обучающую и тестовую выборки, после чего модель kNN с параметром k = 3 была обучена и протестирована.
Здесь для данного цветка ириса надо предсказать его принадлежность к одному из трех классов.
Метод показал высокую точность на тестовых данных — порядка 96%, что подтверждает его эффективность для этой задачи. Такой алгоритм можно применять для различных задач классификации, включая распознавание изображений, анализ текстов и медицинскую диагностику.
begin
var dataset := new DataSet('Datasets\iris.csv', False, ',');
// Разделение данных на обучающую и тестовую выборки
var (trainSet, testSet) := dataset.TrainTestSplit(0.8);
// Создание и обучение модели kNN
var knn1 := new KNN(3); // k = 3
knn1.Fit(trainSet);
// Прогнозирование на тестовых данных
var predictions := knn1.Predict(testSet.Features);
// Прогнозирование для одного объекта
var newSample := [5.1, 3.5, 1.4, 0.2]; // Пример нового объекта
var prediction := knn1.PredictOne(newSample);
Println($'Prediction for new sample: {prediction}');
// Оценка точности
var accuracy := knn1.Accuracy(testSet.Target.Select(t -> Round(t)).ToArray, predictions);
Println($'Accuracy: {accuracy}');
end.
Код сгенерирован DeepSeek. Код - в комментарииМашинное обучение на PascalABC.NET.
Часть 4. Деревья решений
Дерево решений — это один из самых популярных методов машинного обучения, используемый для задач классификации и регрессии. Суть метода заключается в разделении данных на группы с помощью последовательных простых решений, представленных в виде дерева, где каждый узел — это проверка условия, а ветви — возможные исходы.
Основные этапы работы дерева решений:
Обучение модели:
Алгоритм строит дерево, выбирая на каждом шаге наилучшее разделение данных с помощью критерия, такого как энтропия или индекс Джини.
Каждое разделение стремится максимизировать различие между классами или минимизировать ошибку предсказания.
Прогнозирование:
Модель применяет полученные правила для новых данных, проходя по дереву и принимая решение на основе условий в узлах.
Для классификации — выбирается класс, который чаще всего встречается в листьях дерева, для регрессии — вычисляется среднее значение целевой переменной.
Оценка качества:
Точность модели можно оценить с помощью метрик, таких как точность, полнота, F1-score (для классификации) или среднеквадратичная ошибка (для регрессии).
Важным моментом является предотвращение переобучения, для чего можно использовать такие техники, как ограничение глубины дерева или использование метода случайных лесов.
В данном примере дерево решений применяется к хорошо известному датасету заболеваемости breast-cancer.csv
Точность, получаемая на тестовой выборке, составляет 93%.
В комментарии приводится код.
Машинное обучение на PascalABC.NET.
Часть 3. Логистическая регрессия
Логистическая регрессия — это метод машинного обучения, который используется для задач классификации. В отличие от линейной регрессии, которая предсказывает числовые значения, логистическая регрессия предсказывает вероятность принадлежности объекта к определённому классу (например, 0 или 1). Это делает её особенно полезной для задач, где нужно разделить данные на две или более категорий.
Основные этапы работы логистической регрессии:
1. Обучение модели:
- Модель находит оптимальные параметры (веса и смещение), чтобы минимизировать ошибку предсказания на обучающих данных.
- Для этого используется метод градиентного спуска, который постепенно корректирует параметры.
2. Прогнозирование:
- Модель вычисляет вероятность принадлежности объекта к классу 1.
- Если вероятность больше или равна 0.5, объект классифицируется как 1, иначе — как 0.
3. Оценка качества:
- Точность модели оценивается с помощью метрики Accuracy, которая показывает долю правильных предсказаний.
Реализация в PascalABC.NET
uses MLABC;
type
LogisticRegression = class
private
weights: array of real;
learningRate: real;
numIterations: integer;
bias: real;
function Sigmoid(z: real) := 1.0 / (1.0 + Exp(-z));
function PredictProbability(X: array of real) := Sigmoid(bias + X.Zip(weights, (x, w) -> x * w).Sum());
public
constructor(lr: real := 0.01; nIter: integer := 1000);
begin
learningRate := lr;
numIterations := nIter;
end;
procedure Fit(dataset: DataSet);
function PredictOne(X: array of real) := PredictProbability(X) >= 0.5 ? 1 : 0;
function Predict(X: array of array of real) := X.Select(x -> PredictOne(x)).ToArray();
function Accuracy(yTrue, yPred: array of integer) := yTrue.Zip(yPred, (yt, yp) -> yt = yp).Count(x -> x) / yTrue.Length;
end;
// Реализация метода Fit вне класса
procedure LogisticRegression.Fit(dataset: DataSet);
begin
var X := dataset.Features;
var y := dataset.Target.Select(x -> Round(x)).ToArray(); // Преобразуем Target в массив целых чисел
var n := X.Length;
var m := X[0].Length;
weights := new real[m];
bias := 0.0;
for var i := 1 to numIterations do
begin
var (dw, db) := (new real[m], 0.0);
for var j := 0 to n - 1 do
begin
var prediction := PredictProbability(X[j]);
var error := prediction - y[j];
dw := dw.Zip(X[j], (dwk, xjk) -> dwk + error * xjk).ToArray();
db += error;
end;
weights := weights.Zip(dw, (wk, dwk) -> wk - learningRate * dwk / n).ToArray();
bias -= learningRate * db / n;
end;
end;
begin
// Загрузка данных
var dataset := new DataSet('Datasets/diabetes.csv');
// Разделение данных на обучающую и тестовую выборки
var (trainSet, testSet) := dataset.TrainTestSplit(0.8);
// Создание объекта Scaler для нормализации данных
var scaler := new Scaler();
// Нормализация обучающей выборки
trainSet.Features := scaler.FitTransform(trainSet.Features);
// Нормализация тестовой выборки
testSet.Features := scaler.Transform(testSet.Features);
// Создание и обучение модели
var model := new LogisticRegression(0.1, 100);
model.Fit(trainSet);
// Предсказание на тестовой выборке
var yPred := model.Predict(testSet.Features);
// Вычисление точности
var acc := model.Accuracy(testSet.Target.Select(y -> Round(y)).ToArray(), yPred);
// Вывод точности
Println($'Accuracy: {acc:0.00}');
end.
#### Объяснение кода:
1. Класс LogisticRegression:
- weights и bias — параметры модели.
- Sigmoid — функция, которая преобразует линейную комбинацию признаков в вероятность.
- PredictProbability — вычисляет вероятность принадлежности к классу 1.
- PredictOne — классифицирует объект на основе порога 0.5.
- Predict — классифицирует массив объектов.
- Accuracy — вычисляет точность модели.
2. Метод Fit:
- Обучает модель на данных, используя градиентный спуск.
- Корректирует веса и смещение на каждой итерации.
Код сгенерирован DeepSeekМашинное обучение на PascalABC.NET.
Часть 2. Линейная регрессия
Линейная регрессия — это метод машинного обучения для поиска линейной зависимости между признаками (входными данными) и целевой переменной (тем, что нужно предсказать).
Для применения этого метода строится модель, которая представляет собой линейное уравнение, в котором целевая переменная выражается через сумму признаков, умноженных на коэффициенты (веса), плюс смещение. Неизвестные в этом уравнении — веса, которые метод подбирает так, чтобы предсказания модели были максимально близки к реальным данным.
В этом посте линейная регрессия применяется к датасету housing.csv, чтобы найти зависимость цены дома от его характеристик: площади, количества комнат и района.
🛠 Этапы работы кода:
1. Загрузка данных:
- Данные о домах (признаки и цены) загружаются из файла housing.csv.
2. Разделение данных:
- Данные делятся на обучающую и тестовую выборки. Обучающая используется для обучения модели, а тестовая — для проверки её точности.
3. Обучение модели (метод Fit):
- Модель находит оптимальные веса и смещение методом наименьших квадратов, чтобы минимизировать ошибку предсказания на обучающих данных.
4. Прогнозирование (метод Predict):
- Модель использует найденные веса и смещение, чтобы предсказать цены для тестовой выборки.
5. Оценка качества:
- Модель сравнивает предсказанные цены с реальными и вычисляет, насколько хорошо она справилась, с помощью коэффициента R^2.
6. Прогнозирование для одного объекта:
- Модель может предсказать цену для конкретного дома, если задать его признаки.
begin
// 1. Загрузка данных
var dataset1 := new DataSet('Datasets\housing.csv', False, ' ');
// 2. Разделение данных на обучающую и тестовую выборки
var (trainSet, testSet) := dataset1.TrainTestSplit(0.8);
// 3. Создание и обучение модели
var model := new LinearRegression;
model.Fit(trainSet);
// 4. Прогнозирование на тестовых данных
var predictions := model.Predict(testSet.Features);
// 5. Оценка качества модели
var r2Score := model.Score(testSet.Target, predictions);
writeln('R² Score: ', r2Score);
// 6. Запрос количества признаков
var numFeatures := dataset1.Features[0].Length;
writeln('Количество признаков в датасете: ', numFeatures);
// 7. Генерация признаков для одного дома
var newHouse := testSet.Features[^1];
writeln('Сгенерированные признаки:');
newHouse.Println;
// 8. Прогнозирование для одного дома
var prediction := model.PredictOne(newHouse);
writeln('Предсказанное значение: ', prediction);
end.
Код линейной регрессии полностью сгенерирован DeepSeek и приводится в комментарииМашинное обучение на PascalABC.NET.
Часть 1. Модуль MLABC.
Начинаем цикл публикаций о методах машинного обучения, реализованных на PascalABC.NET, код для которых полностью сгенерирован большими языковыми моделями.
Модуль MLABC сгенерирован DeepSeek с использованием множества корректирующих промптов.
В данном модуле представлен класс DataSet, загружающий датасеты из csv-файлов, а также разбивающий данные на тестовую и тренировочную выборки.
Все данные для простоты считаются вещественными. Строковые данные должны быть предварительно удалены из датасета, а категориальные данные заменены на целые. Вещественность данных не всегда удобна, но позволяет сделать код существенно проще и представлять таблицы как array of array of real.
Также описывается класс Scaler, который предназначен для нормирования данных - когда разные показатели имеют существенно различные диапазоны значений. Некоторые методы машинного обучения (например, логистическая регрессия) чрезвычайно чувствительны к ненормированным данным и показывают на них низкую точность.
В классе Scaler метод Fit по признакам вычисляет показатели mean и std (по каждому столбцу), после чего метод Transform нормирует данные в этих столбцах.
Приведем код конструктора DataSetа, считывающего данные из csv-фала данные. Этот код интересен тем, что полностью сгенерирован DeepSeek.
constructor DataSet.Create(filePath: string; hasHeaders: boolean; delimiter: char; targetIndex: integer);
begin
Self.HasHeaders := hasHeaders;
Self.Delimiter := delimiter;
var lines := ReadLines(filePath).ToArray;
if HasHeaders then
begin
ColumnNames := lines[0].ToWords(Delimiter)[:^1];
lines := lines[1:];
end
else ColumnNames := ArrGen(lines[0].ToWords(Delimiter).Length - 1, i -> 'Feature' + (i + 1).ToString);
var numericData := lines.ConvertAll(line -> line.ToWords(Delimiter).ConvertAll(val -> val.ToReal));
if targetIndex = -1 then
begin
Features := numericData.ConvertAll(row -> row[:^1]);
Target := numericData.ConvertAll(row -> row[^1]);
end
else
begin
Features := numericData.ConvertAll(row -> row?[:targetIndex] + row?[targetIndex+1:]);
Target := numericData.ConvertAll(row -> row[targetIndex]);
end;
end;28-29 марта 2025 г. V конференция «Использование системы программирования PascalABC.NET в обучении программированию»
Первое информационное письмо.
Регистрация - здесь.
Также приглашаем выступить с докладом по тематике конференции.
Рисуем псевдографикой
Замечательная программа неизвестного автора на Rosetta Code.
// https://rosettacode.org/wiki/One-dimensional_cellular_automata#PascalABC.NET
А мы в Rosetta Code на 65 месте с 589 решениями!
##
var gen := '_###_##_#_#_#_#__#__'.Select(ch -> (if ch = '#' then 1 else 0)).ToList;
loop 10 do
begin
gen.Select(n -> (if n = 1 then '#' else '_')).Println;
gen := (0 + gen + 0).ToList;
gen := (1..gen.Count - 2).Select(m -> (if gen[m - 1:m + 2].Sum = 2 then 1 else 0)).ToList;
end;Разбор задач олимпиады на PascalABC.NET - 2 ступень
Публикуем разбор задач олимпиады для 2 ступени (автор - Мнухин Роман Михайлович).
https://disk.yandex.ru/i/xnC63UPqDzM7Rw
Разбор задач олимпиады на PascalABC.NET - 1 ступень
16 февраля в воскресной компьютерной школе мехмата ЮФУ прошла первая онлайн олимпиада по программированию на PascalABC.NET. В ней приняло участие около 100 учащихся компьютерной школы. Для 1 и 2 ступеней обучения проходили отдельные олимпиады - каждая по 9 заданий. Время на выполнение - 2 часа.
Для регистрации участников был реализован Телеграм-бот, реализованный на PascalABC.NET (автор Пучкин М.В.).
Результаты олимпиады можно посмотреть на сайте lightpt.sfedu.ru (автор Пучкин М.В.).
В качестве технического средства проверки впервые была использована система LightPT, позволяющая проверять выполнение непосредственно в интегрированной среде PascalABC.NET при запуске программы. Основное преимущество LightPT - типизированный ввод-вывод, детальные сообщения об ошибках.
Публикуем разбор задач олимпиады для 1 ступени (автор - Мнухин Роман Михайлович).
https://disk.yandex.ru/i/EzXmnGjWcE3d7g
+1
Москва в иллюминаторе видна
Вышел замечательный документ про заключительный этап всероссийской олимпиады школьников по программированию 2025.
https://sirius10.ru/wp-content/uploads/2025/02/trebovaniya-ze-2024-25-vsosh-informatika.pdf
Обращают на себя внимание две таблицы
Здесь всё прекрасно.
Только C++ гарантирует выполнение на полный балл.
PascalABC.NET образца 2015 года и отсутствие поддержки Linux.
Программируйте на C++ и будет вам счастье!
Переводчик Emoji
Словарь для перевода в Emoji - хороший пример использования словарей
// Переводчик текстовых сообщений в эмодзи
begin
var emoji := Dict(
'улыбка' to $'😊',
'солнце' to $'☀️',
'дождь' to $'🌧',
'кот' to $'🐱',
'сердце' to $'❤️'
);
var message := 'Я и кот, солнце в душе и прекрасная улыбка в моем сердце';
Println('Перевод сообщения:');
foreach var word in message.ToWords do
if word in emoji then
Print(emoji[word])
else
Print(word);
end.Cursor AI и PascalABC.NET
В этом видео мы познакомимся с новой замечательной IDE Cursor, которая делает интеллектуальные подсказки по коду, опираясь на весь корпус программ, которые находятся в ближайших папках.
Хотя поддержка PascalABC.NET не анонсирована, Cursor быстро подхватывает тематику программы и предлагает весьма вероятные подсказки.
Вот пример первой программы, которую почти полностью написал Cursor.
begin
var f := OpenRead('Progr1.txt');
var f1 := OpenWrite('Progr2.txt');
while not f.Eof do
begin
var s := f.ReadString;
if s.Length > 5 then
f1.WriteLine(s);
end;
f.Close;
f1.Close;
end.