Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЛабПрактОАиПН111.doc
Скачиваний:
58
Добавлен:
25.02.2016
Размер:
1.38 Mб
Скачать

Задания

Разработать программу решения задачи с использованием процедур и функций над строками и операций над множествами.

1. Вывести на экран все символы кодовой таблицы ПЭВМ.

2. Ввести слово и все буквы "О" заменить в нем на "А".

3. Напечатать в столбик числовые коды букв введенного слова.

4. Написать программу подсчета количества гласных в тексте на английском языке.

5. Написать программу обращения слова.

6. Написать программу замены в тексте всех букв "а" на "о" и наоборот.

7. Написать программу, удваивающую каждый символ в заданном тексте.

8. Написать программу, выясняющую, является ли данное слово полиндромом ("перевёртышем").

9. Написать программу, вычёркивающую из данного слова все буквы "а" (так, чтобы, например, из слова "заноза" получилось "зноз").

10. Написать программу, проверяющую, является ли частью данного слова слово "сок".

11. Написать программу, подсчитывающую, сколько раз в данном слове встречается сочетание "со".

12. Написать программу, заменяющую в тексте все большие латинские буквы на маленькие.

13. Написать программу, заменяющую в тексте все маленькие латинские буквы на большие.

14. Дана строка символов, состоящая из произвольного текста на английском языке, слова отделены пробелами. После каждого гласного символа вставить символ “*”.

15. Вывести все строчные гласные латинские буквы, встречающие в данной строке ровно один раз.

16. В заданном тесте подсчитать количество четырехбуквенных слов и каждое четное из них заменить на сочетание "SsSs". Слова отделены друг от друга пробелом.

17. Отредактировать предложение, удаляя из него лишние пробелы, оставляя по одному пробелу между словами.

18. В заданном предложении указать слово, в котором доля гласных «А» максимальна.

19. Проверить, имеется ли в заданном тексте баланс открывающих и закрывающих скобок, имея в виду, что балансом, например, будет комбинация (…), в то время как комбинация )..(..)..( балансом не является.

20. Для каждого слова заданного предложения указать долю согласных. Определить слово, в котором доля согласных максимальна.

21. Найти самое длинное симметричное слово заданного предложения и указать номер позиции, с которого оно начинается.

22. Отредактировать заданное предложение, заменяя многоточия точкой, а вместо точки ставить восклицательный знак.

23. В заданном предложении найти самое короткое и самое длинное слова и указать позиции, с которых они начинаются (слова в предложении разделены пробелом).

24. Из заданного текста предложения выбрать и вывести только те символы, которые встречаются в нем только один раз (в том порядке, в котором они встречаются в тексте).

25. В заданном тексте заменить последовательность символов X(i) на X[i] и подсчитать число произведенных замен.

26. В заданном тексте предложения заменить строчные буквы на прописные и подсчитать количество произведенных замен.

27. Задан текст, состоящий из произвольной последовательности буквенных символов. Упорядочить их в алфавитном порядке, при этом повторяющиеся символы должны быть удалены.

28. Задана строка символов, состоящая из букв, цифр, точек, символов «+» и «-». Выделить подстроку, состоящую из цифр, соответствующую целому числу (т.е. начинается со знака «+» или «-» и внутри подстроки нет букв и точки).

29. В заданном тексте предложения расставить слова по алфавиту в соответствии с его первой буквой.

30. Задан текст, состоящий из произвольной последовательности буквенных символов. Упорядочить их в алфавитном порядке, при этом повторяющиеся символы должны быть удалены.

Задачи второго уровня

1. В заданном предложений поменять порядок следования слов на обратный.

2. Ввести текст, содержащий от 1 до 4 цифровых символов, отображающих целые числа от 1 до 2000. На экран вывести введенные числа и их представление в римской системе счисления.

3. В заданном предложении, состоящем из нескольких слов, поменять местами слова, стоящие на четных местах со словами, стоящими на нечетных местах.

4. В заданном тексте в каждом нечетном слове поменять местами первые два буквенных символа и заменить их на заглавные.

5. В заданном тексте в каждом четном слове заменить все строчные буквенные символы на прописные, а каждое нечетное слово заключить в круглые скобки.

6. Для встречающихся в заданном тексте пар рядом расположенных букв указать, сколько раз встречается каждое из таких двухбуквенных сочетаний.

7. Данный текст на русском языке «перекодировать» в соответствии с таблицей перекодировки, заданной двумя строками st1 и st2. Например, пусть дан текст «Данный текст на русском языке» и таблица перекодировки: st1=’аейкнут’, st2=’горелка’. Тогда в результате перекодировки должен получиться текст: «Дгнныр аоест нг ркссеом языео»

8. Определить номер позиции k-го вхождения строки st1 в строку st2. Если такого нет, возвратить 0.

9. Определить номер позиции последнего вхождения строки st1 в строку st2. Если такого нет, возвратить 0.

10. Даны две строки st1 и st2. Разработать процедуру, которая по значению первого параметра выполняет следующие операции над данными строками: находит символы, встречающиеся в обеих строках, находит символы, встречающиеся только в первой строке, только во второй строке.

Лабораторная работа 10

Методы внутренней сортировки

Цель работы: Формирование умений и навыков в разработке сложных циклических алгоритмов обработки массивов. Изучение методов внутренней сортировки. Реализация отдельных алгоритмов сортировки.

Что нужно знать для выполнения работы

1. Метод пошаговой детализации разработки алгоритмов.

2. Идеи, находящиеся в основе методов сортировки массивов.

3. Особенности использования массивов в качестве параметров в процедурах и функциях.

Существует шесть основных идей внутренней сортировки: подсчетом, обменом, выбором, вставками, слиянием, распределением. Практически каждая из этих идей имеет несколько модификаций, некоторые из которых достаточно сложны для реализации.

Рассмотрим один из методов сортировки – метод «пузырька» – один из вариантов обменной сортировки.

Данный алгоритм основан на принципе сравнения и обмена пары соседних элементов до тех пор, пока не будут рассортированы все элементы. Общий замысел любого алгоритма сортировки лучше всего раскрыть на конкретном примере сортировки последовательности целых чисел (рисунок10.1)

Исходный массив

Номер просмотра

Осортированный массив

1

2

3

4

5

6

7

45

99

99

99

99

99

99

99

81

45

81

81

81

81

81

81

13

81

45

76

76

76

76

76

04

13

76

45

50

50

50

50

76

04

13

50

45

45

45

45

50

76

04

13

37

37

37

37

28

50

50

04

13

28

28

28

22

28

37

37

04

13

22

22

99

22

28

28

28

04

13

13

37

37

22

22

22

22

04

04

Рисунок 10.1 Пример сортировки методом "пузырька"

Итак, мы видим, что после первого просмотра наибольший элемент занял свое место в конце массива; после второго - второй по величине элемент занял свое место и т.д.

Начнем разработку алгоритма на алгоритмическом языке (псевдокоде) и покажем использование метода пошаговой детализации. Заголовок и первый шаг могут быть следующими:

алг Сортировка обменами (цел N, цел таб A[1:N])

арг N,A

рез A

нач

Упорядочить элементы линейной таблицы по возрастанию

кон

Рисунок 10.2 Заголовок алгоритма и первый шаг

В дальнейшем мы не будем записывать заголовок, т.к. он остается без изменений. Очевидно, что для получения отсортированного массива достаточно выполнить N-1 просмотр, т.к. после того как N-1 элемент займут свои места, N-ому ничего не останется как занять последнее свободное место.

Таким образом, можно сказать, что для выполнения сортировки необходимо организовать цикл на N-1 повторение (рисунок10.3).

нач

цел i

для i от 1 до N-1

нц

поставить i-тый элемент таблицы на свое место

кц

кон

Рисунок 10.3 Второй шаг детализации

Что необходимо сделать, чтобы поставить i-тый элемент на свое место, т.е., в чем суть i-го просмотра? Необходимо сравнивать соседние элементы и, если предыдущий больше последующего, поменять их местами.

Максимальное число сравнений на каждом просмотре N-1. Имеем

нач

цел i,j

для i от 1 до N-1

нц

для j от 1 до N-1

нц

если A[j]>A[j+1]

то

обмен A[j] и A[j+1]

всё

кц

кц

кон

Рисунок 10.4 Третий шаг детализации

Осталось уточнить процедуру "обмен A[j] и A[j+1]"

нач

цел i,j,T

для i от 1 до N-1

нц

для j от 1 до N-1

нц

если A[j]>A[j+1]

то

T :=A[j]

A[j] :=A[j+1]

A[j+1]:=T

всё

кц

кц

кон

Рисунок 10.5 Четвёртый шаг детализации

Теперь, когда алгоритм полностью разработан, попытаемся несколько улучшить его. Т.к. после каждого просмотра хотя бы один элемент займет свое место и в дальнейшем может не участвовать в сравнениях, то с каждым просмотром количество сравнений можно уменьшить на 1. Другими словами, на i-том просмотре достаточно выполнить N-i сравнений.

нач

цел i,j,T

для i от 1 до N-1

нц

для j от 1 до N-i

нц

если A[j]>A[j+1]

то

T :=A[j]

A[j] :=A[j+1]

A[j+1]:=T

все

кц

кц

кон

Рисунок10.6 Первое уточнение

Из рисунка 10.1 видно, что после очередного просмотра свои места могут занять сразу несколько элементов, а не один. Таким образом, количество сравнений на очередном просмотре может уменьшиться не на единицу по сравнению с предыдущим просмотром, а на большую величину. Необходимо заметить номер элемента A[j], который участвовал в обмене последним при очередном просмотре. Для чего введем промежуточную величину L. На следующем просмотре будем сравнивать элементы с индексами меньшими чем L.

нач

цел i,j,T,L,K

K:=N-1

для i от 1 до N-1

нц

для j от 1 до K

нц

если A[j]>A[j+1]

то

T :=A[j]

A[j] :=A[j+1]

A[j+1]:=T

L :=j

всё

кц

K:=L-1

кц

кон

Рисунок 10.7 Второе уточнение

Из рисунка 10.1 видно также, что необязательно выполнять N-1 просмотр, что последовательность может оказаться отсортированной раньше (возможно в самом начале она уже была упорядочена!).

Введем переключатель P, который вначале каждого просмотра будем выключать, а при обмене элементов включать.

Тогда сортировка будет закончена, если на очередном просмотре не будет ни одного обмена, т.е. переключатель останется выключенным.

нач

цел i,j,T,L,K

лог P

K:=N-1

P:=истина

пока P

нц

P:=ложь

для j от 1 до K

нц

если A[j]>A[j+1]

то

T :=A[j]

A[j] :=A[j+1]

A[j+1]:=T

L :=j

P :=истина

всё

кц

K:=L-1

кц

кон

Рисунок 10.8 Третье уточнение

Последний алгоритм можно улучшать и дальше. Например, организовать попеременный просмотр массива с разных концов (шейкер-сортировка), сравнивать сначала не соседние элементы, а с определенным шагом (метод Бэтчера), разделить исходный массив на подмассивы (метод Хоара) и др.

Метод простого выбора

Данный метод основан на выборе самого маленького элемента последовательности и обмене его с первым элементом последовательности. Затем находится второй по величине элемент и меняется местами со вторым и т.д. После n-1 просмотра все элементы займут свои места. Одним из улучшений данного метода является метод пирамидальной сортировки.

Метод простых вставок

Согласно методу простых вставок элементы последовательности, начиная со второго вставляются в уже упорядоченную подпоследовательность. Для того, чтобы не проверять сложное условие в цикле-пока, очередной вставляемый элемент ставится на место нулевого и служит барьером, когда вставляемый элемент оказывается меньшим элементом подпоследовательности. Одновременно с поиском места вставки большие элементы сдвигаются на одну позицию к концу подпоследовательности. Одним из лучших методов сортировки является метод Шелла, который основан на методе простых вставок. Этот метод подобен методу Бэтчера, только подмассивы сортируются не метом обмена, а методом простых вставок.

Метод двухпутевых вставок

Считается, что слева и справа от первого элемента имеется n-1 свободное место и вставляемые элементы сравниваются либо с последним вставленным элементом справа или слева. Этот выбор зависит от того, были ли сдвиги элементов на предыдущем шаге, если были, то направление вставки меняется на противоположный.

Метод бинарных вставок

В методе простых вставок для поиска места вставки выполняются последовательные сравнения вставляемого элемента с предыдущими элементами. Метод бинарных вставок основан на дихотомии, т.е. на бинарном методе поиска места. Например, если 63 элемента уже упорядочены и необходимо найти место 64-го, то 64-й сравнивается с 32-м, затем, в зависимости от результата сравнения, либо с 16-м, либо с 48-м. Таким образом, для нахождения места 64-го элемента достаточно выполнить всего шесть сравнений, а для нахождения места вставки, скажем, 1000-го десять сравнений.

Метод подсчетом

Заготавливаем n счетчиков и обнуляем их (можно заполнить единицами). Далее, сравниваем первый элемент с остальными и, в зависимости от того какой элемент больший, счетчик этого элемента увеличиваем на единицу. Затем второй элемент сравниваем с остальными, начиная с третьего и т.д. В результате, после сравнения n-1-го c n-м, счетчики будут содержать номера элементов в отсортированной последовательности без единицы, если счетчики вначале обнулялись и номера, если им были присвоены единицы. После этого достаточно одного цикла для получения нового упорядоченного массива из старого.

Метод слияния

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

При простом слиянии исходный массив разбивается на n цепочек, в каждой из которых содержится по одному элементу. Далее выполняется слияние первой цепочки с последней, второй с предпоследней и т.д. Результаты, цепочки в два раза длиннее, записываются поочередно в начало или в конец нового массива. Так как на каждом шаге слияния длины цепочек удваиваются, то достаточно выполнить log2n шагов.

Естественное двухпутевое слияние отличается от простого только первым шагом, - первоначальным разбиением на цепочки, которое выполняется естественным способом. Например, если исходная последовательность

37 99 22 28 50 76 04 13 81 45,

то начальное разбиение на цепочки будет следующим:

37 99 | 22 28 50 76 | 04 | 13 || 81 45

Как видим, количество цепочек может быть значительно меньшеn, что позволит несколько ускорить сортировку. То, что количество элементов в сливаемых цепочках различно никакой роли при организации слияния не играет. В данном случае незначительно усложняется алгоритм из-за того, что один «средний» элемент может попасть в две цепочки (в нашем случае число 13).

Сортировка распределением

Мы рассмотрим частный случай сортировки распределением: поразрядную сортировку. Допустим, исходный массив состоит из двухразрядных десятичных чисел

37 24 99 08 22 19 28 82 50 64 11 71 95 76 04 13 81 45 53 17

Заготавливается 10 “карманов” по n элементов каждый и выполняется распределение элементов исходного массива по карманов в зависимости от значения младшего разряда. В нашем случае это распределение будет следующим:

Карманы: 0 1 2 3 4 5 6 7 8 9

50 11 22 13 24 95 76 37 08 99

71 82 53 64 45 17 28 19

81 04

Берем последовательно элементы из карманов и получаем последовательность, упорядоченную по первому разряду:

50 11 71 81 22 82 13 53 24 64 04 95 45 76 37 17 08 28 99 19.

Эту последовательность снова упорядочиваем аналогично предыдущему, но по второму разряду:

Карманы: 0 1 2 3 4 5 6 7 8 9

04 11 22 37 45 50 64 71 81 95

08 13 24 53 76 82 99

17 28

19

Получили упорядоченную последовательность:

04 08 11 13 17 19 22 24 28 37 45 50 53 64 71 76 81 82 95 99.

Если элементы исходной последовательности содержат больше десятичных разряда, то понадобится просто больше шагов распределения.

Примечание. На самом деле нет необходимости заготавливать 10 карманов и распределять физически по ним элементы. Достаточно знать о каждом элементе в какой карман он должен попасть и, по очереди выбирать их из этих виртуальных карманов.

Задания

Разработать алгоритм методом пошаговой детализации и программу, реализующую этот алгоритм.

1. Сортировка двухпутевыми вставками.

2. Сортировка подсчетом.

3. Сортировка простым обменом.

4. Сортировка простыми вставками.

5. Шейкер-сортировка.

6. Сортировка бинарными вставками.

7. Сортировка простым выбором.

8. Сортировка простым слиянием.

9. Сортировка естественным слиянием.

10. Поразрядная сортировка.

11. Найти элементы каждой строки матрицы, которые повторяются наибольшее число раз в своей строке.

12. Проверить, являются ли элементы строк данной матрицы перестановками одинаковых элементов.

13. Упорядочить строки данной матрицы в порядке возрастания количества одинаковых элементов в каждой строке.

14. Дана квадратная матрица порядка n. Переставить строки матрицы так, чтобы в результате получилась матрица, у которой строки упорядочены в порядке возрастания диагональных элементов.

15. Массив записей содержит фамилии участников соревнования и количество набранных баллов. Упорядочить записи в порядке убывания количества баллов. Если некоторые участники набрали одинаковое количество баллов, то их фамилии вывести в алфавитном порядке.

16. Массив записей содержит фамилии участников соревнования по прыжкам в длину и результаты трех попыток. Упорядочить записи в порядке занятых мест спортсменами.

17. Массив записей содержит фамилии участников соревнования и количество набранных баллов. Вывести фамилии участников, показавших три лучших результата. (Таких участников может быть больше трех (некоторые участники показали одинаковые результаты).

18. Имеется массив слов. Вывести все анаграммы введенного слова, которые имеются в массиве.

19. Найти самую длинную восходящую подпоследовательность в данной последовательности. Например, в последовательности 3, 6, 2, 7, 4, 8 такой подпоследовательностью будет 3, 6, 7, 8.

20. Расставить строки данной матрицы в порядке возрастания элементов первого столбца.

21. Расставить строки данной матрицы в порядке возрастания наибольших элементов в строках.

22. Дан двухмерный массив. Упорядочить его элементы в порядке возрастания.

23. Дан трехмерный массив. Упорядочить его элементы в порядке возрастания.

24. Имеется массив кодов групп товаров. Код группы товара - это последовательность четырех цифр. Упорядочить данный массив не используя операций сравнения.

25. Вывести в порядке возрастания их кодов все строчные буквы латинского алфавита, имеющиеся в текстовом файле.

26. Написать одноцикловую программу сортировки массива.

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

28. Упорядочить в порядке возрастания элементы строк данной матрицы, после чего упорядочить строки по возрастанию первых элементов полученных строк.

29. Упорядочить в порядке возрастания элементы строк данной матрицы, после чего упорядочить строки по убыванию последних элементов полученных строк.

30. Имеются три, упорядоченных в порядке возрастания, массива. Слить их в один упорядоченный массив.

31. Имеется массив натуральных чисел. Получить массив записей, содержащих различные числа исходного массива и их частоту в исходном массиве.

32. Расставить данный массив натуральных чисел по количеству их делителей.

Лабораторная работа 11

Рекуррентные соотношения. Рекурсии

Цель работы: Формирование умений и навыков в разработке рекурсивных процедур и функций. Дать представление о многообразии подходов к решению задач.

Что нужно знать для выполнения работы

1. Определение рекурсивных процедур и функций.

2. Структуры рекурсивных процедур и функций.

Примеры выполнения задания лабораторной работы

Пример 1

Составить программу нахождения , воспользовавшись рекурсивной функцией вычисления n!

Текст программы

program lr10_1_1;

{Нахождение C из n по m, используя формулу

m n!

C = ________

n m!(n-m)!

Вычисление факториала оформить в виде рекурсивной функции}

uses

crt;

var

n,m:integer;

Cnm:longint;

function fact(n:integer):longint;

begin

if (n=0) or (n=1) then

fact:=1

else

fact:=fact(n-1)*n;

end;

begin

clrscr;

write('Введите n и m ');

readln(n,m);

cnm:=fact(n) div (fact(m)*fact(n-m));

writeln('C из ',n, ' по ',m,' = ',cnm);

readkey;

end.

Пример 2

Составить программу нахождения воспользовавшись рекуррентной формулой .

Текст программы

program lr10_1_2;

{Нахождение C из n по m, используя рекуррентную формулу

m m m-1

C = C + C

n n-1 n-1

}

uses

crt;

var

n,m:longint;

function cnm(n,m:integer):integer;

begin

if (n=m) or (n=1) or (m=0) then

cnm:=1

else

cnm:=cnm(n-1,m)+cnm(n-1,m-1);

end;

begin

clrscr;

write('Введите n и m ');

readln(n,m);

writeln('C из ',n, ' по ',m,' = ',cnm(n,m));

readkey;

end.

Приведенные примеры иллюстрируют использование рекурсивных функций, хотя искомую величину проще было вычислить с помощью обычных нерекурсивных функций.

Рассмотрим пример, который рекурсивно реализовать значительно проще, нежели без рекурсий.

Пример 3

Задача о башне Ханоя.

Священники некой секты должны решить следующую задачу (рисунок11.1):

А

В

С

Рисунок 11.1 Ханойская башня (начальное положение)

64 кольца (на рисунке только 4), лежащие один на другом в порядке убывания размеров на основании А, должны быть перемещены на основание В при использовании промежуточного основания С. Разрешается перемещать кольцо, взятое с вершины одной пирамиды, на большее кольцо другой или на пустую пирамиду. Согласно легенде, конец мира наступит, когда будут перемещены все 64 кольца.

Приведенная ниже программа выводит на экран последовательность перекладываний колец. Рекурсивный алгоритм программы достаточно прост. Для перекладывания n колец с А на В достаточно n-1 колец переложить с А на С, используя В в качестве промежуточного, n-е кольцо переложить с А на В, а затем снова n-1 кольцо переложить с С на В, используя А в качестве промежуточного.

Примечание. Не следует запускать данную программу для больших значений n. Если количество перекладываний достаточно велико (оно равно 2n-1), то вывод следует перенаправить в текстовый файл или организовать приостановку выдачи на экран через определенное число выводимых строк. Ни один из современных компьютеров не сможет «переложить» 64 кольца.

Текст программы

program lr11_3_1;

{Ханойская башня}

uses

crt;

var

n : Integer;

k: longint;

Procedure Hanoy(n:Integer;a,b,c:char);

begin

if n>0 then

begin

Hanoy(n-1,a,c,b);

inc(k);

Writeln(k:4,' c ',a,' на ',b);

Hanoy(n-1,c,b,a);

end;

end;

begin

clrscr;

k:=0;

write('n= ');

read(n);

Hanoy(n,'A','B','C');

writeln('k= ',k);

readkey;

end.

Пример 4

В матрице А nxm , элементы которой могут принимать нулевые и единичные значения, подсчитайте число изолированных 0-областей, т.е. областей, состоящих из одних нулей и найдите размер самой большой области.

Текст программы

program lr11_4_1;

{ В матрице А nxm, элементы которой могут принимать нулевые и единичные значения, подсчитайте число изолированных 0-областей, т.е. областей, состоящих из одних нулей и найдите размер самой большой области (рекурсивный вариант).}

uses

crt;

type

m2=array[0..7,0..7] of integer;

var

a:m2;

i,j,m,n,kol,maxkol1,kol1 :integer;

ft:text;

procedure okaiml;

{Окаймление матрицы единицами. Благодаря этому для всех основных элементов матрицы проверяются одни и те же условия, так как теперь у каждого элемента четыре соседа}

begin

for i:=0 to m+1 do

begin

a[0,i]:=1;

a[n+1,i]:=1;

end;

for i:=1 to n do

begin

a[i,0]:=1;

a[i,m+1]:=1;

end;

end;

procedure obch(i,j:integer);

{Процедура обхода области}

begin

if a[i,j]=0 then

begin

a[i,j]:=kol+1;

inc(kol1);

obch(i-1,j); {вверх}

obch(i,j-1); {влево}

obch(i+1,j); {вниз}

obch(i,j+1); {вправо}

end;

end;

{Головная программа}

begin

clrscr;

assign(ft,'matr11_4.txt');

reset(ft);

readln(ft,n,m);

for i:=1 to n do

begin

for j:=1 to m do

read(ft,a[i,j]);

readln(ft);

end;

close(ft);

writeln('a[n x m]');

for i:=1 to n do

begin

for j:=1 to m do

write(a[i,j]:2);

writeln;

end;

okaiml;

kol:=0;

maxkol1:=0;

for i:=1 to n do

for j:=1 to m do

if a[i,j]=0 then

begin

inc(kol);

kol1:=0;

obch(i,j);

if kol1>maxkol1 then

maxkol1:=kol1;

end;

writeln('a[n x m]');

for i:=1 to n do

begin

for j:=1 to m do

write(a[i,j]:2);

writeln;

end;

writeln('kol= ',kol,' maxkol1= ',maxkol1);

readkey;

end.

Пример 5

Счастливые билеты

Талон для проезда в городском транспорте имеет шестизначный номер от 000000 до 999999. Будем считать талон «счастливым», если сумма первых трех цифр равна сумме последних трех. Подсчитать количество «счастливых» билетов.

Решая данную задачу, постараемся показать многообразие подходов к решению той или иной задачи.

Вариант 1

Первое решение «лобовое». Перебираем все номера от 000000 до 999999, выделяем цифры и проверяем, является ли талон «счастливым».

Текст программы

program Happy1;

{Количество счастливых билетов (вариант 1). Полный перебор с выделением цифр

числа}

uses

crt;

var

k,i,i1:longint;

j:integer;

a:array[1..6] of integer;

begin

clrscr;

k:=0;

for i:=0 to 999999 do

begin

i1:=i;

for j:=6 downto 1 do {Выделение цифр}

begin

a[j]:=i1 mod 10;

i1:=i1 div 10;

end;

if (a[1]+a[2]+a[3]=a[4]+a[5]+a[6]) then

inc(k);

end;

writeln('k= ',k);

readkey;

end.

Вариант 2

Во втором варианте формируем сразу все шесть цифр числа.

Текст программы

program Happy2;

{Количество счастливых билетов (вариант 2). Полный перебор, формируя цифры

числа}

uses

crt;

var

k:longint;

i1,i2,i3,i4,i5,i6:integer;

begin

clrscr;

k:=0;

for i1:=0 to 9 do

for i2:=0 to 9 do

for i3:=0 to 9 do

for i4:=0 to 9 do

for i5:=0 to 9 do

for i6:=0 to 9 do

if (i1+i2+i3=i4+i5+i6) then

inc(k);

writeln('k=',k);

readkey;

end.

Вариант 3

Обратим внимание на то, что в «счастливом» талоне последняя цифра i6 однозначно определяется первыми пятью:

i6=(i1+i2+i3)-(i4+i5).

Если 0<=i6<=9, то билет «счастливый», иначе - нет. Таким образом, мы можем убрать шестой вложенный цикл:

Текст программы

program Happy3;

{Количество счастливых билетов (вариант 3). Полный перебор, формируя цифры

числа с нахождением шестой цифры через первые пять}

uses

crt;

var

k:longint;

i1,i2,i3,i4,i5,i6:integer;

begin

clrscr;

k:=0;

for i1:=0 to 9 do

for i2:=0 to 9 do

for i3:=0 to 9 do

for i4:=0 to 9 do

for i5:=0 to 9 do

begin

i6:= (i1+i2+i3)-(i4+i5)

if (i6>=0) and (i6<=9) then

inc(k);

writeln('k=',k);

readkey;

end.

Вариант 4

Пусть a[sc] количество талонов с суммой первых трех цифр равной sc.

Очевидно, что количество «счастливых» талонов с определенной суммой первых трех цифр равно a[sc]2. Находим сумму первых трех цифр и увеличиваем соответствующий элемент массива на единицу.

Текст программы

program Happy4;

{Количество счастливых билетов (вариант 4). Находим количества талонов с определенной суммой первых трех цифр.}

uses

crt;

var

k:word;

i1,i2,i3:0..9;

sc:0..27;

a:array[0..27] of word;

begin

clrscr;

k:=0;

for sc:=0 to 27 do

a[sc]:=0;

for sc:=0 to 27 do

begin

for i1:=0 to 9 do

for i2:=0 to 9 do

for i3:=0 to 9 do

if i1+i2+i3=sc then

inc(a[sc]);

end;

for sc:=0 to 27 do

inc(k,sqr(a[sc]));

{ writeln('a[',sc,']= ',a[sc]);

readkey;}

writeln('k= ',k);

readkey;

end.

Вариант 5

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

Текст программы

program Happy5;

{Количество счастливых билетов (вариант 5). Находим количества талонов с

определенной суммой первых трех цифр.}

uses

crt;

var

k:word;

i1,i2,i3:0..9;

sc:0..27;

a:array[0..27] of word;

begin

clrscr;

k:=0;

for sc:=0 to 27 do

a[sc]:=0;

for i1:=0 to 9 do

for i2:=0 to 9 do

for i3:=0 to 9 do

inc(a[i1+i2+i3]);

end;

for sc:=0 to 27 do

inc(k,sqr(a[sc]));

{ writeln('a[',sc,']= ',a[sc]);

readkey;}

writeln('k= ',k);

readkey;

end.

Вариант 6

Заметим, что «счастливых» талонов с суммой sc столько же, сколько и с суммой 27-sc. Действительно, если билет i1 i2 i3 i4 i5 i6 с суммой sc - «счастливый», то таковым же является и билет (999999 - i1 i2 i3 i4 i5 i6) с суммой 27-sc. Поэтому число талонов можно вычислять и по формуле

2*(a[0]2+ ... +a[13]2),

т.е.рассматривать только суммы sc от 0 до 13.

program Happy6;

{Количество счастливых билетов (вариант 6). Находим количества талонов с определенной суммой первых трех цифр.}

uses

crt;

var

k:word;

i1,i2,i3:0..9;

sc:0..13;

a:array[0..13] of word;

begin

clrscr;

k:=0;

for sc:=0 to 13 do

a[sc]:=0;

for i1:=0 to 9 do

for i2:=0 to 9 do

for i3:=0 to 9 do

inc(a[i1+i2+i3]);

end;

for sc:=0 to 13 do

inc(k,sqr(a[sc]));

k:=2*k;

writeln('k= ',k);

readkey;

end.

Вариант 7

В предыдущем варианте мы перебирали комбинации цифр и искали количество комбинаций с суммами a[sc]. Сейчас мы пойдем от суммы sc, и по ней будем определять, какое количество комбинаций i1 i2 i3 ее имеет.

Итак sc=i1+i2+i3. Минимальное значение, которое может принимать i1, - это max(0,sc-18). Максимальное значение i1=min(9,sc).

Для цифры i2 аналогично получаем, что она лежит в пределах от max(0,sc-i1-9) до min(9,sc-i1}.

Цифра i3 по sc, i1 и i2 определяется однозначно.

Получаем, что комбинаций i1 i2 i3 с суммой sc и с первой цифрой i1 столько же, сколько возможных цифр i2, а именно min(9,sc-i1)-max(0,sc-i1-9)+1.

Как и в варианте 6 мы можем рассматривать диапазон сумм sc от 0 до 13.

Текст программы

program Happy7;

{Счастливые билеты. Два цикла}

uses

crt;

var

i1,kol,sc:integer;

k:longint;

function min(a,b:integer):integer;

begin

if a<b then

min:=a

else

min:=b;

end;

function max(a,b:integer):integer;

begin

if a>b then

max:=a

else

max:=b;

end;

begin

clrscr;

for sc:=0 to 13 do

begin

kol:=0;

for i1:=max(0,sc-18) to min(9,sc) do

inc(kol,min(9,sc-i1)-max(0,sc-i1-9)+1);

inc(k,2*sqr(kol));

end;

writeln('k = ',k);

readkey;

end.

Вариант 8

Выведя значения количества «счастливых» талонов с суммой sc:

1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 63, 69, 73, 75 и, проанализировав их, заметим закономерность, которую нетрудно реализовать программой с одним циклом.

Текст программы

program Happy8;

{Счастливые билеты. Вариант с одним циклом}

uses

crt;

var

i:integer;

k,s,ts:longint;

begin

clrscr;

s:=0;

ts:=0;

for i:=1 to 10 do

begin

inc(ts,i);

inc(s,sqr(ts));

end;

for i:=4 downto 1 do

begin

inc(ts, 2*i);

inc(s,sqr(ts));

end;

writeln('k = ',2*s);

readkey;

end.

Вариант 9

Данный вариант – другая реализация предыдущего.

Текст программы

program Happy9;

{Счастливые билеты. Вариант с одним циклом}

uses

crt;

var

i:integer;

k,s,ts:longint;

begin

clrscr;

s:=0;

ts:=0;

for i:=1 to 14 do

if i<11 then

begin

inc(ts,i);

inc(s,sqr(ts));

end

else

begin

inc(ts,2*(15-i));

inc(s,sqr(ts));

end;

writeln('k = ',2*s);

readkey;

end.

Вариант 10

Данный и последующие варианты – рекурсивные реализации предыдущего.

Текст программы

program Happy10;

{Счастливые билеты. Рекурсивный вариант 1}

uses

crt;

var

i,n:integer;

k:longint;

function tr(i:longint):longint;

var

t:longint;

begin

if i=1 then

t:=1

else

if i<11 then

t:=tr(i-1)+i

else

t:=tr(i-1)+2*(15-i);

inc(kol,2*sqr(t));

tr:=t;

end;

begin

clrscr;

k:=0;

n:=tr(14);

writeln('k= ',k);

readkey;

end.

Вариант 11

Текст программы

program Happy11;

{Счастливые билеты. Рекурсивный вариант 2}

uses

crt;

var

k:longint;

function kol(i:integer):longint;

var

ts:integer;

function cnm(n,m:integer):integer;

begin

if (n=m) or (n=1)or(m=0) then

cnm:=1

else

cnm:=cnm(n-1,m)+cnm(n-1,m-1);

end;

begin

if i=0 then

begin

kol:=k;

exit;

end

else

if i<11 then

ts:=cnm(i+1,i-1)

else

ts:=cnm(i+1,i-1)-3*cnm(i-9,i-11);

k:=k+2*sqr(ts);

kol:=kol(i-1);

end;

begin

clrscr;

k:=0;

writeln('k= ',kol(14));

readkey;

end.

Вариант 12

Текст программы

program Happy12;

{Счастливые билеты. Рекурсивный вариант 3}

uses crt;

var

k:longint;

function kol(i:integer):longint;

var

ts:integer;

function cnm(n,m:integer):integer;

begin

if (n=m) or (n=1)or(m=0) then

cnm:=1

else

cnm:=cnm(n-1,m)+cnm(n-1,m-1);

end;

begin

case i of

0 :begin

kol:=k;

exit;

end;

1..10 :ts:=cnm(i+1,i-1);

11..14:ts:=cnm(i+1,i-1)-3*cnm(i-9,i-11);

end;

k:=k+2*sqr(ts);

kol:=kol(i-1);

end;

begin

clrscr;

k:=0;

writeln('k= ‘,kol(14));

readkey;

end.

Решим данную задачу в общем виде, когда номер талона состоит из 2n цифр.

Определим через S(k,i) количество k-разрядных чисел, сумма цифр которых равна i. Например, S(2,3)=4, так как существует 4 двуразрядных числа (03,12,21,30), сумма цифр которых равна 3. Легко заметить, что S(1,i)=1 при i<10 и S(1,i)=0 при i>9. Предположим теперь, что мы сумели вычислить значения величин S(n,i) для всех i от 0 до 9*n, т.е. мы знаем, сколько существует n-разрядных чисел с суммой цифр, равной 0,1,...,9*n (максимальное число цифр в n-разрядном числе). Тогда нетрудно убедиться, что общее количество «счастливых» 2n-разрядных чисел равно

P=S(n,0)2 + S(n,1) 2 +...+S(n,9*n) 2.

Действительно, каждое «счастливое» 2n-разрядное число может быть получено склейкой двух произвольных n-разрядных чисел с одинаковой суммой цифр.

Таким образом, необходимо уметь вычислять значения величин S(k,i) для всех kn, i9*k. Определим способ вычисления S(k+1,i) через значения величин S(k,j), ji. Понятно, что любое k+1-разрядное число может быть получено из k-разрядного добавлением еще одного разряда (цифры). Следовательно

S(k+1,i) = S(k,i-ц1)+S(k,i-ц2)+...,

где ц12,... - возможные добавленные цифры. Ясно, что это 0,1,...,m где m=min(9,i). Следовательно,

S(k+1,i) = S(k,i-0)+S(k,i-1)+...+ S(k,i-m).

Текст программы

program happy2n;

{Количество счастливых талонов, состоящих из 2n цифр}

uses

crt;

var

n,i,m:integer;

kol:longint;

function min(a,b:integer):integer;

begin

if a<b then

min:=a

else

min:=b;

end;

function s(k,i:integer):longint;

var

m:integer;

ts:longint;

begin

ts:=0;

if k=1 then

if i<10 then

s:=1

else

s:=0

else

begin

for m:=0 to min(9,i) do

inc(ts,s(k-1,i-m));

s:=ts;

end;

end;

begin

clrscr;

write('n= ');

readln(n);

kol:=0;

for i:=0 to 9*n do

inc(kol,sqr(s(n,i)));

writeln('k= ',kol);

readkey;

end.

Задания

1. С помощью признака делимости на 3 проверить, кратно ли данное натуральное число 3. Написать рекурсивную процедуру.

2. С помощью признака делимости на 3 проверить, кратно ли данное натуральное число 3. Написать рекурсивную функцию.

3. С помощью признака делимости на 9 проверить, кратно ли данное натуральное число 9. Написать рекурсивную процедуру.

4. С помощью признака делимости на 9 проверить, кратно ли данное натуральное число 9. Написать рекурсивную функцию.

5. С помощью признака делимости на 11 проверить, кратно ли данное натуральное число 11. Написать рекурсивную процедуру.

6. С помощью признака делимости на 11 проверить, кратно ли данное натуральное число 11. Написать рекурсивную функцию.

7. Найти наибольший общий делитель последовательности натуральных чисел а1, а2,…аn.

8. Найти n-й член ряда Фибоначчи, используя рекурсивную функцию.

9. Найти n-ю степень (n – натуральное число) числа а, используя рекурсивную функцию.

10. В данной последовательности чисел найти подпоследовательность подряд идущих элементов, сумма которых максимальна.

11. Используя рекурсивную функцию найти n-й член арифметической прогрессии с заданными первым членом а и разностью прогрессии d.

12. Используя рекурсивную функцию найти n-й член геометрической прогрессии с заданными первым членом b и знаменателем прогрессии q.

13. Найти n членов последовательности по заданным n, а1 и an, таких что ai =ai-1+(i-1)d.

14. С помощью рекурсивной функции уточнения корня уравнения f(x)=0 методом половинного деления.

15. С помощью рекурсивной функции найти с заданной точностью квадратный корень , воспользовавшись итерационной формулой Ньютона:

Y0=1

Yi= 1/2 (Yi-1+ X/Yi-1) (i=1,2,3,...)

Вычисления производить пока |Yi - Yi-1| не станет меньше EPS.

16. Разработать рекурсивную функцию нахождения максимального элемента данной последовательности а1, а2, …, аn.

17. Дана последовательность натуральных чисел а1, а2, …, аn. Разработать рекурсивную процедуру нахождения i и j, таких что подпоследовательность аi, аi+1, …, аj является перевертышем.

18. Дана последовательность чисел а1, а2, …, аn. Разработать рекурсивную процедуру сортировки последовательности методом быстрой сортировки (Хоара).

19. Разработать рекурсивную процедуру нахождения n чисел Кнута:

К0 = 1,

, где [n/2] –наибольшее небольшее n/2.

20. На шахматной доске расставить 8 ферзей так, чтобы они не «били» друг друга.

21. Разработать рекурсивную процедуру сортировки массива методом простого выбора.

22. Разработать рекурсивную процедуру двоичного поиска элемента массива, равного данному числу.

23. Разработать рекурсивную функцию нахождения наибольшего общего делителя двух чисел m и n используя алгоритм Евклида, в соответствии с которым НОД(a,b)= НОД(max(a,b)-min(a,b),min(a,b)).

24. Разработать рекурсивную функцию нахождения наибольшего общего делителя двух чисел m и n используя алгоритм Евклида, в соответствии с которым НОД(a,b) равен последнему, отличному от нуля остатку при делении с остатком a на b, затем, полученного делителя на остаток и т.д.

Найдем, например, НОД(96,36): 96=2 . 36 + 24; 36=1 . 24 + 12; 24=2 . 12 + 0. Следовательно, НОД(96,36)=12.

25. Разработать рекурсивную функцию нахождения значения функции Аккермана, которая определяется для всех неотрицательных целых аргументов m и n следующим образом:

А(0,n)=n+1;

A(m,0)=A(m-1,1), если (m>0);

A(m,n)=A(m-1,A(m,n-1)), если (m, n >0).

26. Подсчитать количество различных представлений заданного натурального n в виде суммы не менее двух попарно различных натуральных слагаемых. Представления, отличающиеся лишь порядком слагаемых, различными не считаются.

27. Вычислить определитель заданной матрицы, пользуясь формулой разложения по первой строке: где матрица Вk получается из А вычеркиванием первой строки и k-го столбца.

28. Функция f(n) определена на множестве натуральных чисел следующим образом:

29. Строка символов состоит из букв А, В и С. Разработать рекурсивную процедуру, преобразующую данную строку по правилам:

а) удаляет четыре подряд идущих букв А;

б) удаляет из последовательности ВАВА одну пару ВА;

в) удаляет комбинацию АВС.

Преобразования выполнять до тех пор, пока ни одной из перечисленных комбинаций не останется.

30. Имеется полоска клетчатой бумаги шириной в одну клетку и длиной в n клеток. На первой клетке установлена шашка. Одним ходом шашку можно передвигать на одну или две клетки. Разработать рекурсивную функцию, определяющую количество способов продвижения шашки на n-ю клетку.

Задачи второго уровня

1. Найти количество n-значных чисел в m-ичной системе счисления, у каждого из которых сумма цифр равна k. При этом в качестве n-значного числа мы допускаем и числа, начинающиеся с одного или нескольких нулей.

2. Дана матрица a(m,n) из 0 и 1. Найти в ней квадратную подматрицу из одних единиц максимального размера.

3. Дана матрица a(m,n) из 0 и 1. Найти в ней прямоугольную подматрицу из одних единиц максимального размера (т.е. с максимальным произведением высоты на длину).

4. Дана матрица a(m,n). Найти в ней квадратную подматрицу, сумма элементов которой максимальна.

5. Дана матрица a(m,n). Найти в ней прямоугольную подматрицу, сумма элементов которой максимальна.

6. Дана матрица a(m,n). Найти в ней путь от элемента a[i1,j1] до элемента a[i2,j2] с максимальной суммой. Ходить можно по горизонталям и вертикалям. Каждый элемент матрицы может входить в путь не более одного раза.

7. Дана матрица a(m,n). Найти в ней путь от элемента a[i1,j1] до элемента a[i2,j2] с максимальной суммой. Ходить можно по горизонталям и вертикалям. Каждый элемент матрицы может входить в путь не более двух раз.

8. Дана матрица a(m,n). Найти в ней путь от элемента первой строки матрицы до элемента последней строки с максимальной суммой. Ходить можно вниз по вертикали или диагоналям.

9. Задано число А и два вектора b[1..n] и c[1..n]. Найти множество I, являющееся подмножеством множества {1,...,n}, такое, что , аявляется максимальной из всех возможных.

10. Разработать рекурсивную процедуру, находящую сумму двух натуральных чисел, заданных массивами своих цифр а1, а2, …, аn и b1, b2, …, bm.

11. Вводится три неотрицательных числа d, i, c и две строки X и Y. Найти преобразование строки X в Y минимальной стоимости. Допустимы следующие три операции:

удалить любой символ из X (стоимость операции d);

вставить любой символ в X (стоимость операции i);

заменить символ в X на произвольный (стоимость операции с).

12. Даны две строки x и y. Строка x состоит из нулей и единиц, строка y из символов A и B. Можно ли строку x преобразовать в строку y по следующему правилу: цифра 0 преобразуется в непустую последовательность букв A, а цифра 1 - либо в непустую последовательность букв A, либо в непустую последовательность букв B?

13. Дано n различных натуральных чисел. Разработать рекурсивную процедуру формирования всех перестановок этих чисел.

14. Лабиринт задан матрицей a(m,n), состоящей из 0 и 1, причем а[1,1]=0 и a[m,n]=0. Разработать рекурсивную процедуру нахождения пути из клетки а[1,1] в a[m,n]. Путь должен состоять из элементов, равных 0. Ходить можно только по вертикалям и горизонталям.

15. Даны два натуральных числа m и n. Найти НОД(m,n) и натуральные x и y такие, что mx+ny= НОД(m,n).

16. Даны три натуральных числа m, n и k, причем k делится на НОД(m,n). Найти какое-нибудь целочисленное решение уравнения mx+ny= k.

17. Разработать рекурсивную процедуру сортировки массива методом простого двухпутевого слияния.

18. Задано конечное множество жителей некоего города, прчем для каждого из жителей перечислены имена его детей. Жители X и Y считаются родственниками, если:

а) либо Х – ребенок Y,

б) либо Y – ребенок X,

в) либо существует некий Z такой, что Х является родственником Z, а Z является родственником Y.

Перечислить все пары жителей города, которые являются родственниками.

19. Имеется n населенных пунктов, перенумерованных от 1 до n. Некоторые пары пунктов соединены дорогами. Разработать рекурсивную процедуру определения, можно ли попасть по этим дорогам из 1-го пункта в n-й.

Лабораторная работа 12

Процедуры и функции модуля CRT

Цель работы: Формирование умений и навыков в разработке различных систем меню. Использование процедур и функций модулей CRT и DOS.

Что нужно знать для выполнения работы

Стандартные процедуры и функции модуля CRT и DOS.

Пример 1

Разработать вертикальное световое меню, содержащее заголовок и n пунктов меню. Значения n и названия пунктов меню ввести из текстового файла. Организовать перемещение по пунктам меню с помощью клавиш стрелка вверх и стрелка вниз. На время работы с меню спрятать курсор. После выбора какого-нибудь пункта меню клавишей «Enter» вывести в окошко текст этого пункта. При выборе последнего пункта завершить программу.

Текст программы

program L12_1;

{Создание меню}

uses

Crt{, Dos};

type

stroka=string[60];

masmen=array [1..20] of stroka;

var

men:masmen;{строки меню}

n:integer;

procedure rescur;

{Убрать курсор}

begin

asm

mov cx,$2000;

mov ax,$0100;

int $10;

end;

end;

procedure setcur;

{Показать курсор}

begin

asm

mov cx,$0c0d;

mov ax,$0100;

int $10;

end;

end;

procedure vvodpmen(var men:masmen;var n:integer);

{Ввод строк меню}

var

fin:text;

begin

assign(fin,'menul12.txt');

reset(fin);

n:=0;

while not eof(fin) do

begin

inc(n);

readln(fin,men[n]);

end;

close(fin);

end;

procedure menu(title:stroka;men:masmen;n:integer;

x0,y0:integer;cf0,cf1,cpp0,cpp1:integer);

{Вывод меню и обработка выбранного пункта}

var

k,i,xn,yn:integer;

kod:char;

function maxl(men:masmen;n:integer):integer;

{Нахождение максимальной длины строки меню}

var

maxt,i:integer;

begin

maxt:=length(men[1]);

for i:=2 to n do

if maxt<length(men[i]) then

maxt:=length(men[i]);

maxl:=maxt;

end;

procedure ramka(x0,y0,xn,yn:integer);

{Вывод рамки в окне меню}

var

i1:integer;

begin

textcolor(7);

gotoxy(1,1);

write('г');

for i1:=1 to (xn-x0-1) do

write('=');

write('¬');

for i1:=2 to yn-y0 do

begin

gotoxy(1,i1);

write('');

end;

for i1:=2 to yn-y0 do

begin

gotoxy(xn-x0+1,i1);

write('');

end;

gotoxy(1,yn-y0);

write('');

for i1:=1 to (xn-x0-1) do

write('=');

write('-');

end;

{Формирование меню и анализ нажатых клавиш}

begin

k:=1;

xn:=x0+maxl(men,n)+3;

yn:=y0+n+5;

{Бесконечный цикл. Выход после выбора последнего пункта меню}

while true do

begin

textmode(co80);

textbackground(0);

textcolor(7);

clrscr;

window(x0,y0,xn,yn);

textbackground(6);

textcolor(0);

clrscr;

ramka(0,0,xn-x0,yn-y0);

gotoxy((xn-x0) div 2 - length(title) div 2,2);

write(title); {Вывод заголовка}

kod:=' ';

while kod<>#13 do {Цикл пока не нажата клавиша Enter}

begin

rescur;

for i:=1 to n do

begin

if i=k then

begin

textbackground(cf1);

textcolor(cpp1);

end

else

begin

textbackground(cf0);

textcolor(cpp0);

end;

gotoxy(3,i+3); {Вывод пунктов меню}

write(men[i]);

end;

kod:=readkey;

sound(100);

delay(5);

nosound;

if kod=#0 then {Если нажата клавиша управления кутсором}

begin

kod:=readkey;

if kod=#72 then {Стрелка вверх}

begin

if k>1 then

k:=k-1

else

k:=n

end;

if kod=#80 then {Стрелка вниз}

begin

if k<n then

k:=k+1

else

k:=1;

end;

end;

end;

setcur;

if k=n then

begin {Стандартное окно и выход из меню}

window(1,1,80,25);

clrscr;

exit;

end

else

begin {Вывод сообщения о выбранном пункте меню}

window(x0,yn+2,xn,yn+4);

textbackground(3);

textcolor(6);

clrscr;

gotoxy(2,1);

write(men[k]);

readkey;

end;

end;

end;

{Головная программа}

begin

vvodpmen(men,n);

menu('Меню',men,n,7,8,6,1,7,6);

end.

Вместо использования вставки на ассемблере можно воспользоваться процедурой intr модуля DOS для выключения и включения курсора.

procedure rescur;

{Убрать курсор}

var

r:registers;

begin

with r do

begin

cx:=$2000;

ax:=$0100;

intr($10,r);

end;

end;

procedure setcur;

{Показать курсор}

var

r:registers;

begin

with r do

begin

cx:=$0c0d;

ax:=$0100;

intr($10,r);

end;

end;

Эти две процедуры можно объединить в одну, задав в качестве параметра содержимое регистра счетчика cx.

procedure setcur(scx:word);

{Установить курсор}

var

r:registers;

begin

with r do

begin

cx:=scx;

ax:=$0100;

intr($10,r);

end;

end;

Пример 2

Составить программу вывода на экран трех окон. В первое окно ввести вертикальную строку текста. Нажатием клавиши "Ввод" организовать непрерывное движение строки последовательно через второе и третье окно. Направление "бегущей строки" сверху вниз. После того, как строка придет в исходное положение, программа завершается.

Текст программы

program L12_2;

{Строка бежит по вертикали через три окна в текстовом режиме}

uses

crt,dos;

type

mas1=array[1..7] of char;

const

c:mas1=('1','2','3','4','5','6',' ');

var

m1,n1,m2,n2,k:integer;

ch:char;

fl:boolean;

i1,i2,i3:integer;

scx:word;

procedure setcur(scx:word);

{Установить размер курсора}

var

r:registers;

begin

with r do

begin

cx:=scx;

ax:=$0100;

intr($10,r);

end;

end;

procedure step(nomw1,nomw2:integer);

{Вывод бегущей строки}

begin

for i1:=1 to 6 do

begin

window(30,nomw1,50,nomw1+6);

setcur($2000);

gotoxy(3,i1);

write(' ');

delay(50);

for i2:=1 to 6-i1 do

begin

gotoxy(3,i2+i1);

write(c[i2]);

delay(50);

end;

window(30,nomw2,50,nomw2+6);

for i3:=1 to i1 do

begin

gotoxy(3,i3);

write(c[6+i3-i1]);

delay(50);

end;

end;

end;

begin

setcur($2000);

textbackground(15);

clrscr;

textcolor(4);

gotoxy(2,24);

write(' Для начала нажмите <Enter>');

{Формирование окон}

window(30,10,50,16);

textbackground(2);

clrscr;

textcolor(6);

window(30,19,50,25);

textbackground(2);

clrscr;

textcolor(6);

window(30,1,50,7);

textbackground(2);

clrscr;

textcolor(6);

{Вывод строки}

for i1:=1 to 6 do

begin

gotoxy(3,i1);

writeln(c[i1]);

end;

ch:=readkey;

if ch=#13 then

begin

step(1,10); {идем по первому окну}

step(10,19);{идем по второму окну}

step(19,1); {идем по третьему окну}

end;

readkey;

setcur($0c0d);

window(1,1,80,25);

end.

Пример 3

Разработать программу вычисления таблицы значений функции на заданном отрезке с заданным шагом. Аналитическое задание функции, границы отрезка и шаг изменения аргумента ввести с клавиатуры.

Данную задачу можно решить разработав синтаксический анализатор выражений. Но это достаточно сложная для нас задача. Поэтому воспользуемся другой идеей. Заготовим шаблон программы для вычисления значения функции и записи результата в типизированный файл. В головной программе скопируем шаблон в текстовый файл, зададим функцию и добавим нужные операторы в текст шаблона программы. Далее, с помощью компилятора командной строки, подготовим выполняемую программу и будем запускать его в цикле для вычисления таблицы значений.

Текст программы

program L12_3;

{Вычисление таблицы значений заданной функции

Устанавливаем размеры стека и хип-области}

{$M 32000,0,16000}

uses

crt,dos;

type

sst=string[80];

var

fres:file of real;

prpas:text;

stf:sst;

c:char;

arg,fn,a,b,h:real;

i,j:integer;

x,y:array[1..100] of real;

procedure Fun(x:real);

{Вычисление очередного значения функции и

запись значений аргумента и функции в типизированный файл}

begin

write(fres,x);

close(fres);

swapvectors;

exec('rezfunc.exe','');

swapvectors;

end;

{Головная программа}

Begin

repeat

clrscr;

swapvectors;

{Вызов командного процессора для копирования файла

zagfunc.pas в rezfunc.pas - заготовки программы,

описания функции }

exec('c:\command.com','/c copy zagfunc.pas rezfunc.pas>nul');

swapvectors;

{Назначение и открытие типизированного файла для

записи результатов}

assign(fres,'data.dat');

rewrite(fres);

{Назначение и открытие текстового файла для

добавления конца программы}

assign(prpas,'rezfunc.pas');

append(prpas);

{Ввод отрезка и шага табуляции}

write('a= ');

readln(a);

write('b= ');

readln(b);

write('h= ');

readln(h);

{Ввод аналитического задания функции в соответствии

с синтаксисом Паскаля}

write('y= ');

readln(stf);

{Дополнение программы описывающей функцию}

write(prpas,stf);

stf:=';'+#10#13+' write(fres,y);'+#10#13+' close(fres);'+#10#13+'end.';

writeln(prpas,stf);

close(prpas);

{Вызов компилятора командной строки для компиляции

сформированной программы}

swapvectors;

exec('c:\command.com','/c tpc.exe rezfunc.pas>nul');

swapvectors;

{Вычисление таблицы функции,

чтение значений из типизированного файла

и формирование массивов значений аргумента и функции}

arg:=a;

i:=0;

while arg<=b+0.1*h do

begin

inc(i);

fun(arg);

reset(fres);

seek(fres,filesize(fres)-2);

read(fres,x[i]);

read(fres,y[i]);

arg:=arg+h;

end;

writeln(' Таблица значений функции ');

writeln('-----------------------------');

writeln(' x y ');

writeln('-----------------------------');

for j:=1 to i do

writeln(x[j]:5:2,' ',y[j]:12:4);

writeln('-----------------------------');

write('Другая функция? Д/Н ');

readln(c);

until c in ['Y','y','Н','н'];

close(fres);

End.

Текст шаблона программы zagfunc.pas

program zagfunc;

{Заготовка программы для вычисления значения функции}

uses

crt;

var

fres:file of real;

x,y:real;

begin

assign(fres,'data.dat');

reset(fres);

seek(fres,filesize(fres)-1);

read(fres,x);

y:=

Текст программы вычисления функции после добавления строк rezfunc.pas

program zagfunc;

{Заготовка программы для вычисления значения функции}

uses

crt;

var

fres:file of real;

x,y:real;

begin

assign(fres,'data.dat');

reset(fres);

seek(fres,filesize(fres)-1);

read(fres,x);

y:=x;

write(fres,y);

close(fres);

end.