|
|
% ===============================================
|
|
|
% LAB9 TASK3 - МОДУЛЬНЫЕ РЕШЕНИЯ ЗАДАЧ С МАССИВАМИ
|
|
|
% Вариант 4: Задачи 4, 16, 28
|
|
|
% ===============================================
|
|
|
|
|
|
% ===============================================
|
|
|
% ЗАДАЧА 4: Индексы элементов в убывающем порядке
|
|
|
% ===============================================
|
|
|
|
|
|
/**
|
|
|
* task4_main(-Result)
|
|
|
* Главный предикат задачи 4: находит индексы массива в порядке убывания элементов
|
|
|
*
|
|
|
* @param Result - список индексов в порядке убывания элементов (неунифицированная)
|
|
|
*
|
|
|
* Назначение: Объединяет чтение, логику и вывод для задачи 4
|
|
|
* При вызове: Result неунифицированная
|
|
|
* По завершении: Result содержит отсортированные по убыванию элементов индексы
|
|
|
*/
|
|
|
task4_main(Result) :-
|
|
|
task4_read(List),
|
|
|
task4_logic(List, Result),
|
|
|
task4_output(Result).
|
|
|
|
|
|
/**
|
|
|
* task4_read(-List)
|
|
|
* Предикат чтения для задачи 4
|
|
|
*
|
|
|
* @param List - считанный список (неунифицированная переменная)
|
|
|
*
|
|
|
* Назначение: Читает массив с клавиатуры
|
|
|
* При вызове: List неунифицированная
|
|
|
* По завершении: List содержит введенные пользователем элементы
|
|
|
*/
|
|
|
task4_read(List) :-
|
|
|
write('Введите элементы массива (завершите ввод точкой): '), nl,
|
|
|
read_list(List).
|
|
|
|
|
|
/**
|
|
|
* task4_logic(+List, -SortedIndices)
|
|
|
* Предикат логики работы для задачи 4
|
|
|
*
|
|
|
* @param List - исходный список (унифицированная переменная)
|
|
|
* @param SortedIndices - индексы в порядке убывания элементов (неунифицированная)
|
|
|
*
|
|
|
* Назначение: Создает пары (индекс, элемент), сортирует по убыванию элементов, извлекает индексы
|
|
|
* При вызове: List унифицированная с исходным массивом, SortedIndices неунифицированная
|
|
|
* По завершении: SortedIndices содержит индексы (начиная с 1) в порядке убывания соответствующих элементов
|
|
|
*/
|
|
|
task4_logic(List, SortedIndices) :-
|
|
|
create_index_value_pairs(List, 1, Pairs),
|
|
|
sort_pairs_by_value_desc(Pairs, SortedPairs),
|
|
|
extract_indices(SortedPairs, SortedIndices).
|
|
|
|
|
|
/**
|
|
|
* task4_output(+Result)
|
|
|
* Предикат вывода для задачи 4
|
|
|
*
|
|
|
* @param Result - результирующий список индексов (унифицированная переменная)
|
|
|
*
|
|
|
* Назначение: Выводит результат на экран
|
|
|
* При вызове: Result унифицированная со списком индексов
|
|
|
* По завершении: результат выведен, переменные остаются без изменений
|
|
|
*/
|
|
|
task4_output(Result) :-
|
|
|
write('Индексы в порядке убывания элементов: '), write(Result), nl.
|
|
|
|
|
|
% ===============================================
|
|
|
% ЗАДАЧА 16: Элементы между первым и вторым максимальным
|
|
|
% ===============================================
|
|
|
|
|
|
/**
|
|
|
* task16_main(-Result)
|
|
|
* Главный предикат задачи 16: находит элементы между первым и вторым максимальным
|
|
|
*
|
|
|
* @param Result - элементы между первым и вторым максимумом (неунифицированная)
|
|
|
*
|
|
|
* Назначение: Объединяет чтение, логику и вывод для задачи 16
|
|
|
* При вызове: Result неунифицированная
|
|
|
* По завершении: Result содержит элементы между первым и вторым максимумом
|
|
|
*/
|
|
|
task16_main(Result) :-
|
|
|
task16_read(List),
|
|
|
task16_logic(List, Result),
|
|
|
task16_output(Result).
|
|
|
|
|
|
/**
|
|
|
* task16_read(-List)
|
|
|
* Предикат чтения для задачи 16
|
|
|
*
|
|
|
* @param List - считанный список (неунифицированная переменная)
|
|
|
*
|
|
|
* Назначение: Читает массив с клавиатуры
|
|
|
* При вызове: List неунифицированная
|
|
|
* По завершении: List содержит введенные пользователем элементы
|
|
|
*/
|
|
|
task16_read(List) :-
|
|
|
write('Введите элементы массива (завершите ввод точкой): '), nl,
|
|
|
read_list(List).
|
|
|
|
|
|
/**
|
|
|
* task16_logic(+List, -ElementsBetween)
|
|
|
* Предикат логики работы для задачи 16
|
|
|
*
|
|
|
* @param List - исходный список (унифицированная переменная)
|
|
|
* @param ElementsBetween - элементы между первым и вторым максимумом (неунифицированная)
|
|
|
*
|
|
|
* Назначение: Находит максимальный элемент, первую и вторую его позицию, извлекает элементы между ними
|
|
|
* При вызове: List унифицированная с исходным массивом, ElementsBetween неунифицированная
|
|
|
* По завершении: ElementsBetween содержит элементы между первым и вторым вхождением максимума
|
|
|
*/
|
|
|
task16_logic(List, ElementsBetween) :-
|
|
|
find_max_element(List, MaxElement),
|
|
|
find_first_occurrence(List, MaxElement, 1, FirstPos),
|
|
|
( find_second_occurrence(List, MaxElement, 1, FirstPos, SecondPos) ->
|
|
|
extract_elements_between_positions(List, FirstPos, SecondPos, ElementsBetween)
|
|
|
; ElementsBetween = []
|
|
|
).
|
|
|
|
|
|
/**
|
|
|
* task16_output(+Result)
|
|
|
* Предикат вывода для задачи 16
|
|
|
*
|
|
|
* @param Result - результирующий список элементов (унифицированная переменная)
|
|
|
*
|
|
|
* Назначение: Выводит результат на экран
|
|
|
* При вызове: Result унифицированная со списком элементов
|
|
|
* По завершении: результат выведен, переменные остаются без изменений
|
|
|
*/
|
|
|
task16_output(Result) :-
|
|
|
write('Элементы между первым и вторым максимальным: '), write(Result), nl.
|
|
|
|
|
|
% ===============================================
|
|
|
% ЗАДАЧА 28: Элементы между первым и последним максимальным
|
|
|
% ===============================================
|
|
|
|
|
|
/**
|
|
|
* task28_main(-Result)
|
|
|
* Главный предикат задачи 28: находит элементы между первым и последним максимальным
|
|
|
*
|
|
|
* @param Result - элементы между первым и последним максимумом (неунифицированная)
|
|
|
*
|
|
|
* Назначение: Объединяет чтение, логику и вывод для задачи 28
|
|
|
* При вызове: Result неунифицированная
|
|
|
* По завершении: Result содержит элементы между первым и последним максимумом
|
|
|
*/
|
|
|
task28_main(Result) :-
|
|
|
task28_read(List),
|
|
|
task28_logic(List, Result),
|
|
|
task28_output(Result).
|
|
|
|
|
|
/**
|
|
|
* task28_read(-List)
|
|
|
* Предикат чтения для задачи 28
|
|
|
*
|
|
|
* @param List - считанный список (неунифицированная переменная)
|
|
|
*
|
|
|
* Назначение: Читает массив с клавиатуры
|
|
|
* При вызове: List неунифицированная
|
|
|
* По завершении: List содержит введенные пользователем элементы
|
|
|
*/
|
|
|
task28_read(List) :-
|
|
|
write('Введите элементы массива (завершите ввод точкой): '), nl,
|
|
|
read_list(List).
|
|
|
|
|
|
/**
|
|
|
* task28_logic(+List, -ElementsBetween)
|
|
|
* Предикат логики работы для задачи 28
|
|
|
*
|
|
|
* @param List - исходный список (унифицированная переменная)
|
|
|
* @param ElementsBetween - элементы между первым и последним максимумом (неунифицированная)
|
|
|
*
|
|
|
* Назначение: Находит максимальный элемент, первую и последнюю его позицию, извлекает элементы между ними
|
|
|
* При вызове: List унифицированная с исходным массивом, ElementsBetween неунифицированная
|
|
|
* По завершении: ElementsBetween содержит элементы между первым и последним вхождением максимума
|
|
|
*/
|
|
|
task28_logic(List, ElementsBetween) :-
|
|
|
find_max_element(List, MaxElement),
|
|
|
find_first_occurrence(List, MaxElement, 1, FirstPos),
|
|
|
find_last_occurrence(List, MaxElement, LastPos),
|
|
|
extract_elements_between_positions(List, FirstPos, LastPos, ElementsBetween).
|
|
|
|
|
|
/**
|
|
|
* task28_output(+Result)
|
|
|
* Предикат вывода для задачи 28
|
|
|
*
|
|
|
* @param Result - результирующий список элементов (унифицированная переменная)
|
|
|
*
|
|
|
* Назначение: Выводит результат на экран
|
|
|
* При вызове: Result унифицированная со списком элементов
|
|
|
* По завершении: результат выведен, переменные остаются без изменений
|
|
|
*/
|
|
|
task28_output(Result) :-
|
|
|
write('Элементы между первым и последним максимальным: '), write(Result), nl.
|
|
|
|
|
|
% ===============================================
|
|
|
% ВСПОМОГАТЕЛЬНЫЕ ПРЕДИКАТЫ
|
|
|
% ===============================================
|
|
|
|
|
|
% Переиспользуем предикат из task1 для чтения списка
|
|
|
/**
|
|
|
* read_list(-List)
|
|
|
* Читает список целых чисел с клавиатуры
|
|
|
* Переиспользуется из task1
|
|
|
*/
|
|
|
read_list(List) :-
|
|
|
write('Введите элементы списка через пробел, завершив точкой: '),
|
|
|
read_term(List, []).
|
|
|
|
|
|
% ----------------------------------------------
|
|
|
% Вспомогательные предикаты для задачи 4
|
|
|
% ----------------------------------------------
|
|
|
|
|
|
/**
|
|
|
* create_index_value_pairs(+List, +CurrentIndex, -Pairs)
|
|
|
* Создает список пар (индекс, значение)
|
|
|
*
|
|
|
* @param List - исходный список (унифицированная)
|
|
|
* @param CurrentIndex - текущий индекс (унифицированная)
|
|
|
* @param Pairs - результирующий список пар (неунифицированная)
|
|
|
*/
|
|
|
create_index_value_pairs([], _, []).
|
|
|
create_index_value_pairs([Head|Tail], Index, [(Index, Head)|RestPairs]) :-
|
|
|
NextIndex is Index + 1,
|
|
|
create_index_value_pairs(Tail, NextIndex, RestPairs).
|
|
|
|
|
|
/**
|
|
|
* sort_pairs_by_value_desc(+Pairs, -SortedPairs)
|
|
|
* Сортирует пары по убыванию значений
|
|
|
*
|
|
|
* @param Pairs - список пар (индекс, значение) (унифицированная)
|
|
|
* @param SortedPairs - отсортированные пары (неунифицированная)
|
|
|
*/
|
|
|
sort_pairs_by_value_desc(Pairs, SortedPairs) :-
|
|
|
sort(2, @>=, Pairs, SortedPairs).
|
|
|
|
|
|
/**
|
|
|
* extract_indices(+Pairs, -Indices)
|
|
|
* Извлекает индексы из списка пар
|
|
|
*
|
|
|
* @param Pairs - список пар (индекс, значение) (унифицированная)
|
|
|
* @param Indices - список индексов (неунифицированная)
|
|
|
*/
|
|
|
extract_indices([], []).
|
|
|
extract_indices([(Index, _)|RestPairs], [Index|RestIndices]) :-
|
|
|
extract_indices(RestPairs, RestIndices).
|
|
|
|
|
|
% ----------------------------------------------
|
|
|
% Вспомогательные предикаты для задач 16 и 28
|
|
|
% ----------------------------------------------
|
|
|
|
|
|
/**
|
|
|
* find_max_element(+List, -MaxElement)
|
|
|
* Находит максимальный элемент в списке
|
|
|
*
|
|
|
* @param List - исходный список (унифицированная)
|
|
|
* @param MaxElement - максимальный элемент (неунифицированная)
|
|
|
*/
|
|
|
find_max_element([Head|Tail], MaxElement) :-
|
|
|
find_max_element_helper(Tail, Head, MaxElement).
|
|
|
|
|
|
/**
|
|
|
* find_max_element_helper(+List, +CurrentMax, -MaxElement)
|
|
|
* Вспомогательный предикат для поиска максимума
|
|
|
*/
|
|
|
find_max_element_helper([], CurrentMax, CurrentMax).
|
|
|
find_max_element_helper([Head|Tail], CurrentMax, MaxElement) :-
|
|
|
( Head > CurrentMax ->
|
|
|
find_max_element_helper(Tail, Head, MaxElement)
|
|
|
; find_max_element_helper(Tail, CurrentMax, MaxElement)
|
|
|
).
|
|
|
|
|
|
/**
|
|
|
* find_first_occurrence(+List, +Element, +CurrentPos, -Position)
|
|
|
* Находит первое вхождение элемента в список
|
|
|
*
|
|
|
* @param List - исходный список (унифицированная)
|
|
|
* @param Element - искомый элемент (унифицированная)
|
|
|
* @param CurrentPos - текущая позиция (унифицированная)
|
|
|
* @param Position - позиция первого вхождения (неунифицированная)
|
|
|
*/
|
|
|
find_first_occurrence([Element|_], Element, CurrentPos, CurrentPos) :- !.
|
|
|
find_first_occurrence([_|Tail], Element, CurrentPos, Position) :-
|
|
|
NextPos is CurrentPos + 1,
|
|
|
find_first_occurrence(Tail, Element, NextPos, Position).
|
|
|
|
|
|
/**
|
|
|
* find_second_occurrence(+List, +Element, +CurrentPos, +FirstPos, -SecondPos)
|
|
|
* Находит второе вхождение элемента в список
|
|
|
*
|
|
|
* @param List - исходный список (унифицированная)
|
|
|
* @param Element - искомый элемент (унифицированная)
|
|
|
* @param CurrentPos - текущая позиция (унифицированная)
|
|
|
* @param FirstPos - позиция первого вхождения (унифицированная)
|
|
|
* @param SecondPos - позиция второго вхождения (неунифицированная)
|
|
|
*/
|
|
|
find_second_occurrence([], _, _, _, fail) :- !, fail.
|
|
|
find_second_occurrence([Element|Tail], Element, CurrentPos, FirstPos, SecondPos) :-
|
|
|
CurrentPos > FirstPos, !,
|
|
|
SecondPos = CurrentPos.
|
|
|
find_second_occurrence([_|Tail], Element, CurrentPos, FirstPos, SecondPos) :-
|
|
|
NextPos is CurrentPos + 1,
|
|
|
find_second_occurrence(Tail, Element, NextPos, FirstPos, SecondPos).
|
|
|
|
|
|
/**
|
|
|
* find_last_occurrence(+List, +Element, -LastPos)
|
|
|
* Находит последнее вхождение элемента в список
|
|
|
*
|
|
|
* @param List - исходный список (унифицированная)
|
|
|
* @param Element - искомый элемент (унифицированная)
|
|
|
* @param LastPos - позиция последнего вхождения (неунифицированная)
|
|
|
*/
|
|
|
find_last_occurrence(List, Element, LastPos) :-
|
|
|
find_last_occurrence_helper(List, Element, 1, -1, LastPos).
|
|
|
|
|
|
/**
|
|
|
* find_last_occurrence_helper(+List, +Element, +CurrentPos, +LastFound, -LastPos)
|
|
|
* Вспомогательный предикат для поиска последнего вхождения
|
|
|
*/
|
|
|
find_last_occurrence_helper([], _, _, LastFound, LastFound).
|
|
|
find_last_occurrence_helper([Element|Tail], Element, CurrentPos, _, LastPos) :-
|
|
|
NextPos is CurrentPos + 1,
|
|
|
find_last_occurrence_helper(Tail, Element, NextPos, CurrentPos, LastPos).
|
|
|
find_last_occurrence_helper([_|Tail], Element, CurrentPos, LastFound, LastPos) :-
|
|
|
NextPos is CurrentPos + 1,
|
|
|
find_last_occurrence_helper(Tail, Element, NextPos, LastFound, LastPos).
|
|
|
|
|
|
/**
|
|
|
* extract_elements_between_positions(+List, +StartPos, +EndPos, -Elements)
|
|
|
* Извлекает элементы между двумя позициями (исключая границы)
|
|
|
*
|
|
|
* @param List - исходный список (унифицированная)
|
|
|
* @param StartPos - начальная позиция (унифицированная)
|
|
|
* @param EndPos - конечная позиция (унифицированная)
|
|
|
* @param Elements - элементы между позициями (неунифицированная)
|
|
|
*/
|
|
|
extract_elements_between_positions(List, StartPos, EndPos, Elements) :-
|
|
|
StartPos < EndPos,
|
|
|
extract_elements_between_helper(List, StartPos, EndPos, 1, Elements).
|
|
|
extract_elements_between_positions(_, StartPos, EndPos, []) :-
|
|
|
StartPos >= EndPos.
|
|
|
|
|
|
/**
|
|
|
* extract_elements_between_helper(+List, +StartPos, +EndPos, +CurrentPos, -Elements)
|
|
|
* Вспомогательный предикат для извлечения элементов между позициями
|
|
|
*/
|
|
|
extract_elements_between_helper([], _, _, _, []).
|
|
|
extract_elements_between_helper([Head|Tail], StartPos, EndPos, CurrentPos, Elements) :-
|
|
|
CurrentPos > StartPos,
|
|
|
CurrentPos < EndPos, !,
|
|
|
Elements = [Head|RestElements],
|
|
|
NextPos is CurrentPos + 1,
|
|
|
extract_elements_between_helper(Tail, StartPos, EndPos, NextPos, RestElements).
|
|
|
extract_elements_between_helper([_|Tail], StartPos, EndPos, CurrentPos, Elements) :-
|
|
|
NextPos is CurrentPos + 1,
|
|
|
extract_elements_between_helper(Tail, StartPos, EndPos, NextPos, Elements).
|
|
|
|
|
|
% ===============================================
|
|
|
% ИНФОРМАЦИОННЫЕ И ТЕСТОВЫЕ ПРЕДИКАТЫ
|
|
|
% ===============================================
|
|
|
|
|
|
/**
|
|
|
* task_info/0
|
|
|
* Выводит информацию о реализованных задачах
|
|
|
*/
|
|
|
task_info :-
|
|
|
write('РЕАЛИЗОВАННЫЕ ЗАДАЧИ TASK3 (Вариант 4):'), nl,
|
|
|
write('Задача 4: Индексы элементов в убывающем порядке'), nl,
|
|
|
write('Задача 16: Элементы между первым и вторым максимальным'), nl,
|
|
|
write('Задача 28: Элементы между первым и последним максимальным'), nl, nl,
|
|
|
write('Использование:'), nl,
|
|
|
write('?- task4_main(Result). % Задача 4'), nl,
|
|
|
write('?- task16_main(Result). % Задача 16'), nl,
|
|
|
write('?- task28_main(Result). % Задача 28'), nl.
|
|
|
|
|
|
/**
|
|
|
* show_examples/0
|
|
|
* Показывает примеры использования с готовыми данными
|
|
|
*/
|
|
|
show_examples :-
|
|
|
write('ПРИМЕРЫ РАБОТЫ ЗАДАЧ:'), nl, nl,
|
|
|
|
|
|
write('Задача 4 - Индексы в убывающем порядке для [3,1,4,1,5]:'), nl,
|
|
|
task4_logic([3,1,4,1,5], Result4),
|
|
|
write('Результат: '), write(Result4), nl, nl,
|
|
|
|
|
|
write('Задача 16 - Элементы между первым и вторым максимальным для [1,5,2,3,5,4]:'), nl,
|
|
|
task16_logic([1,5,2,3,5,4], Result16),
|
|
|
write('Результат: '), write(Result16), nl, nl,
|
|
|
|
|
|
write('Задача 28 - Элементы между первым и последним максимальным для [1,5,2,3,5,4]:'), nl,
|
|
|
task28_logic([1,5,2,3,5,4], Result28),
|
|
|
write('Результат: '), write(Result28), nl.
|
|
|
|
|
|
/**
|
|
|
* interactive_demo/0
|
|
|
* Интерактивная демонстрация всех задач
|
|
|
*/
|
|
|
interactive_demo :-
|
|
|
write('=== ИНТЕРАКТИВНАЯ ДЕМОНСТРАЦИЯ TASK3 ==='), nl,
|
|
|
write('Выберите задачу:'), nl,
|
|
|
write('4. Индексы в убывающем порядке'), nl,
|
|
|
write('16. Элементы между первым и вторым максимальным'), nl,
|
|
|
write('28. Элементы между первым и последним максимальным'), nl,
|
|
|
write('0. Выход'), nl,
|
|
|
write('Введите номер задачи: '),
|
|
|
read(Choice),
|
|
|
handle_choice(Choice).
|
|
|
|
|
|
/**
|
|
|
* handle_choice(+Choice)
|
|
|
* Обрабатывает выбор пользователя в интерактивном режиме
|
|
|
*/
|
|
|
handle_choice(4) :-
|
|
|
task4_main(_),
|
|
|
interactive_demo.
|
|
|
handle_choice(16) :-
|
|
|
task16_main(_),
|
|
|
interactive_demo.
|
|
|
handle_choice(28) :-
|
|
|
task28_main(_),
|
|
|
interactive_demo.
|
|
|
handle_choice(0) :-
|
|
|
write('До свидания!'), nl.
|
|
|
handle_choice(_) :-
|
|
|
write('Неверный выбор! Попробуйте снова.'), nl,
|
|
|
interactive_demo. |