Лабораторные работы. Ерофеев / Разработка ИИ. Отчет №4
.docxМинистерство цифрового развития, связи и массовых коммуникаций Российской Федерации
Федеральное государственное бюджетное образовательное учреждение Высшего образования «Санкт-Петербургский государственный университет телекоммуникаций им. Проф. М. А. Бонч-Бруевича» (СПбГУТ)
Факультет Информационных технологий и программной инженерии
Кафедра Программной инженерии
Лабораторная работа 3
По дисциплине: Разработка приложений искусственного интеллекта в киберфизических системах
Выполнил студент: Яковлев М. А. ИКПИ-32
Принял работу: Ерофеев С. А.
Дата выполнения:
«28» ноября 2025 г.
Санкт-Петербург
2025 г.
Постановка задачи
Разработать программу цифровой сортировки чисел из файла в Turbo Prolog 2.0.
Алгоритм сортировки
Цифровая сортировка — это алгоритм упорядочивания чисел, который работает, обрабатывая их поразрядно, начиная с младшего разряда и продвигаясь к старшему. В основе метода лежит разбиение чисел на группы по значению цифры на текущем разряде.
Сначала алгоритм определяет максимальное число в массиве, чтобы узнать, сколько разрядов у него всего. Затем для каждого разряда, начиная с нулевого (младший разряд), выполняются следующие шаги:
• Создаются 10 пустых корзин, по одной для каждой цифры от 0 до 9.
• Все элементы исходного массива рассматриваются, и для каждого определяется цифра на текущем разряде.
• В зависимости от этой цифры элемент помещается в соответствующую корзину.
• После распределения всех элементов по корзинам они собираются в один массив, сохраняя порядок корзин от 0 к 9.
Этот процесс повторяется для всех разрядов числа, постепенно упорядочивая список.
Если в массиве есть отрицательные числа, алгоритм сначала разделяет их на отрицательные и неотрицательные. Положительные числа сортируются напрямую, а отрицательные по модулю. После завершения сортировки список с отрицательными значениями и список с положительными объединяются.
Перечень предикатов
1. main - Запускает программу, вызывает чтение данных и выполняет сортировку
2. radix_sort_signed(List, Sorted) - Обрабатывает список с учётом знаков: разделяет на положительные и отрицательные, сортирует отдельно, затем объединяет
3. split_sign(Input, Positives, Negatives) - Разделяет входной список на два: положительные числа (включая ноль) и отрицательные числа
4. restore_sign(AbsValues, SignedValues) - Преобразует список абсолютных значений обратно в отрицательные числа
5. reverse_list(Input, Reversed) - Разворачивает порядок элементов в списке
6. radix_sort(Unsorted, Sorted) - Выполняет поразрядную сортировку для неотрицательных чисел
7. radix_pass(List, CurrentPosition, MaxPosition, Result) - Выполняет сортировку по конкретному разряду, рекурсивно обрабатывает все разряды
8. count_sort(InputList, DigitPos, SortedList) - Реализует сортировку для одного разряда с использованием корзин
9. mk_buckets(Count, Buckets) - Создает указанное количество пустых корзин
10. distribute(Numbers, DigitPos, InputBuckets, OutputBuckets) - Распределяет числа по корзинам в соответствии с цифрой текущего разряда
11. collect(Buckets, CombinedList) - Собирает числа из всех корзин в единый отсортированный список
12. add_to_bucket(Buckets, Index, Number, NewBuckets) - Добавляет число в указанную корзину по индексу цифры
13. digit_at(Number, Position, Digit) - Извлекает конкретную цифру из числа по указанной позиции (разряду)
14. int_pow10(Exponent, Result) - Вычисляет 10 в заданной степени
15. max_list(Numbers, Maximum) - Находит самое длинное число в списке для определения количества разрядов
16. max_list_h(Numbers, CurrentMax, FinalMax) - Вспомогательный предикат для поиска максимума
17. digit_width(Number, Width) - Определяет количество цифр в числе
18. digit_width_h(Number, Counter, Result) - Вспомогательный предикат для рекурсивного подсчёта разрядов
19. append(List1, List2, Result) - Объединяет два списка в один
20. rev_append(Input, Accumulator, Result) - Вспомогательный предикат для разворота списка
Схема
Рисунок 1. Общая схема работы программы
Рисунок 2. Сортировка отрицательных чисел
Программа
domains
int_list = integer*
buckets = int_list*
file = text_file
predicates
main % Главный предикат, запускающий сортировку
radix_sort_signed(int_list, int_list) % Предикат для сортировки списка целых чисел с учетом знаков
read_data(int_list) % Чтение данных из файла в список целых чисел
read_n(integer, int_list) % Чтение N целых чисел и сохранение их в список
split_sign(int_list, int_list, int_list) % Разделение списка на положительные и отрицательные числа
restore_sign(int_list, int_list) % Восстановление знаков у отрицательных чисел
reverse_list(int_list, int_list)
radix_sort(int_list, int_list) % Основной предикат для сортировки с использованием алгоритма радикс-сортировки
radix_pass(int_list, integer, integer, int_list) % Один проход сортировки по определенной цифре
count_sort(int_list, integer, int_list)
mk_buckets(integer, buckets)
distribute(int_list, integer, buckets, buckets) % Распределение чисел по ведрам на основе текущей цифры
collect(buckets, int_list) % Сбор всех чисел из корзин в один список
add_to_bucket(buckets, integer, integer, buckets) % Добавление числа в соответствующее ведро
digit_at(integer, integer, integer) % Получение цифры числа по заданной позиции
int_pow10(integer, integer) % Вычисление степени числа 10
max_list(int_list, integer) % Поиск максимального значения в списке
max_list_h(int_list, integer, integer) % Вспомогательный предикат для поиска максимума
digit_width(integer, integer) % Определение количества цифр в числе
digit_width_h(integer, integer, integer) % Вспомогательный предикат для подсчета ширины числа
append(int_list, int_list, int_list)
rev_append(int_list, int_list, int_list)
clauses
read_data(List) :-
write("Enter input-file name: "),
readln(FileName),
openread(text_file, FileName),
!,
readdevice(text_file),
readint(N),
read_n(N, List),
closefile(text_file).
read_data([]).
read_n(0, []) :- !.
read_n(N, [X|T]) :-
readint(X),
N1 = N - 1,
read_n(N1, T).
main :-
read_data(Numbers),
radix_sort_signed(Numbers, Sorted),
write("Sorted: "), write(Sorted), nl.
radix_sort_signed([], []) :- !.
radix_sort_signed(List, Final) :-
split_sign(List, Pos0, Neg0),
radix_sort(Pos0, PosSorted),
restore_sign(Neg0, NegAbs),
radix_sort(NegAbs, NegSortedAbs),
restore_sign(NegSortedAbs, NegSigned),
reverse_list(NegSigned, NegRev),
append(NegRev, PosSorted, Final).
split_sign([], [], []). % Разделяет список на положительные и отрицательные числа
split_sign([H|T], [H|Pos], Neg) :- H >= 0, !, split_sign(T, Pos, Neg).
split_sign([H|T], Pos, [H|Neg]) :- split_sign(T, Pos, Neg).
restore_sign([], []). % Восстанавливает знаки у отрицательных чисел
restore_sign([H|T], [NH|NT]) :- NH = -H, restore_sign(T, NT).
reverse_list(L, R) :- rev_append(L, [], R).
rev_append([], A, A).
rev_append([H|T], A, R) :- rev_append(T, [H|A], R).
radix_sort([], []) :- !. % Основной предикат для сортировки с использованием алгоритма радикс-сортировки
radix_sort(List, Sorted) :-
max_list(List, Max),
digit_width(Max, W),
radix_pass(List, 0, W, Sorted).
radix_pass(List, P, W, List) :- P = W, !. % Проход по цифрам завершен
radix_pass(List, P, W, Sorted) :-
count_sort(List, P, Tmp),
Тестирование
Для проверки работоспособности программы были выполнены тестовые запуски.
Первый тест:
7, 8, 0, -9
Рисунок 1. Результат теста для первого набора данных
Второй тест:
90, 9, -28, 4, 4, 5, 0, -1, -2, 45, 555
Рисунок 2. Результат теста для первого набора данных
Третий тест:
10, 100, 1000, -1, 1, 1, -1, 0
Рисунок 3. Результат теста для первого набора данных
Заключение
В результате выполнения работы была разработана программа цифровой сортировки чисел, реализованная в среде Turbo Prolog 2.0.
