655 lines
52 KiB
HTML
655 lines
52 KiB
HTML
<html>
|
||
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
|
||
<title></title>
|
||
<link rel="StyleSheet" href="../../default.css">
|
||
</head>
|
||
|
||
<body>
|
||
<a name="main"></a>
|
||
|
||
<h1>Задания, связанные с ЕГЭ по информатике
|
||
</h1>
|
||
|
||
|
||
|
||
<hr>
|
||
<h2>Пример 1. Простая задача на реализацию базовых алгоритмов
|
||
</h2>
|
||
<hr>
|
||
<p>Группа заданий ExamBegin посвящена базовым алгоритмическим задачам,
|
||
включенным в кодификатор ЕГЭ по информатике. Процесс выполнения подобных заданий мы рассмотрим на примере
|
||
одной из простых задач, связанных с нахождением максимумов и минимумов из двух, трех или четырех чисел
|
||
без использования массивов и циклов.
|
||
</p>
|
||
<p class="task">ExamBegin2°. На вход подаются три вещественных числа; числа расположены в одной строке.
|
||
Вывести вначале минимальное, а затем максимальное из них. Каждое число должно выводиться на новой строке
|
||
и снабжаться комментарием: «MIN=» для минимального, «MAX=»
|
||
для максимального.
|
||
</p>
|
||
<hr>
|
||
<h3>Создание программы-заготовки и знакомство с заданием
|
||
</h3>
|
||
<p>Напомним, что программу-заготовку для решения этого задания можно создать с помощью
|
||
команды
|
||
меню «Модули | Создать шаблон программы», кнопки
|
||
<img border="0" src="gif/Load.gif" width="16" height="17"> или клавиатурной
|
||
комбинации <b>Shift+Ctrl+L</b>. Приведем текст созданной заготовки:
|
||
</p>
|
||
<blockquote><code><b>uses</b> PT4Exam;
|
||
|
||
<b><br><br>begin</b>
|
||
<br>
|
||
Task('ExamBegin2');
|
||
|
||
<b><br>end</b>.
|
||
</code></blockquote>
|
||
<p>После запуска программы на экране появится <a href="../PT4/window.html">окно задачника</a>:
|
||
</p>
|
||
<blockquote>
|
||
<img border="0" src="gif/ExamBegin2-1.png">
|
||
</blockquote>
|
||
|
||
<p>Обсудим особенности программы-заготовки и окна задачника.
|
||
</p>
|
||
<p>В программе-заготовке вместо модуля <code>PT4</code>
|
||
подключается модуль <code>PT4Exam</code>, специально предназначенный для использования при выполнении
|
||
заданий групп Exam. Данный модуль содержит реализацию единственной процедуры <code>Task</code>,
|
||
инициализирующей задание. Никакие дополнительные процедуры, связанные с вводом-выводом, в него не включены.
|
||
Это обусловлено тем, что ввод-вывод при выполнении заданий групп Exam надо выполнять, используя
|
||
<i>стандартные процедуры языка Pascal</i>.
|
||
</p>
|
||
<p>Основной особенностью окна задачника является то, что в разделе исходных данных отсутствуют данные,
|
||
выделенные желтым цветом (напомним, что желтый цвет используется для выделения данных, которые необходимо
|
||
вводить с помощью специальных процедур ввода задачника). Вместо этого в окне отображается
|
||
строка бирюзового цвета, содержащая числовые данные. Вид строки подчеркивает то обстоятельство,
|
||
что вводить данные требуется не с помощью специальных процедур ввода, имеющихся в задачнике,
|
||
а с помощью стандартных процедур языка Pascal. Отметим, что бирюзовый цвет используется в окне задачника
|
||
для отображения «внешних» данных (содержащихся в файлах или динамических структурах), доступ к которым
|
||
должен осуществляться с помощью стандартных средств используемого языка программирования.
|
||
</p>
|
||
<p>Пример верного решения выделяется серым цветом
|
||
(в отличие от «настоящих» результатов, выведенных программой учащегося, которые, как и входные данные,
|
||
выделяются бирюзовым цветом), однако <i>представление</i> выходных данных совпадает с
|
||
представлением входных: это набор строк,
|
||
содержащих числовые данные (дополненные комментариями). Вид данных в разделе результатов показывает,
|
||
что для их вывода, как и для ввода исходных данных, необходимо использовать стандартные процедуры языка Pascal.
|
||
</p>
|
||
<p>
|
||
<b>Примечание.</b>
|
||
Если вы уже выполняли задания, связанные с обработкой файлов, то можете заметить, что отображение данных
|
||
в заданиях групп Exam
|
||
в точности соответствует способу отображения содержимого <i>текстовых файлов</i>. Это совпадение не случайно.
|
||
На самом деле во всех заданиях групп Exam все исходные данные хранятся в специальном входном текстовом файле,
|
||
а все результаты должны записываться в специальный выходной текстовый файл. Однако при этом не требуется
|
||
выполнять особых действий, связанных с определением имен этих файлов, связыванием файлов с файловыми
|
||
переменными, открытием и закрытием файлов (все эти действия выполняются задачником автоматически).
|
||
Для программы, выполняющей задание, эти файлы играют роль <i>стандартных потоков ввода-вывода</i>,
|
||
поэтому для доступа к ним достаточно использовать обычные процедуры ввода-вывода языка Pascal.
|
||
</p>
|
||
<hr>
|
||
<h3>Ввод исходных данных и их обработка
|
||
</h3>
|
||
<p>Приступим к выполнению задания. В данном случае следует использовать алгоритм, не требующий
|
||
применения массивов, поэтому опишем три простые переменные вещественного типа и введем в них исходные данные:
|
||
</p>
|
||
<blockquote><code><b>uses</b> PT4Exam;
|
||
<b><br><br>begin</b> <br>
|
||
Task('ExamBegin2');
|
||
<br>
|
||
<b>var</b>
|
||
(a,b,c) := ReadReal3;
|
||
<b><br>end</b>.
|
||
</code></blockquote>
|
||
<p>Мы воспользовались стандартной функцией ввода <code>ReadReal3</code>, введя все три исходных числа за один ее вызов.
|
||
</p>
|
||
<p>При запуске приведенного выше варианта программы вид окна не изменится, поскольку мы не вывели никаких данных.
|
||
В заданиях групп Exam запуск программы считается ознакомительным до тех пор, пока программа не выведет
|
||
хотя бы один элемент результирующих данных. Кроме того, задачник не контролирует,
|
||
каким образом программа читает исходные данные (например, мы могли бы ввести всю исходную строку
|
||
в переменную типа <code>string</code>, а затем «разобрать» эту строку, выделив из нее три числа
|
||
и преобразовав их к типу <code>real</code>). Отмеченные особенности характерны именно для заданий групп Exam,
|
||
в которых для ввода данных не используются специальные средства задачника.
|
||
</p>
|
||
<p>Реализуем алгоритм нахождения минимального и максимального элемента. Для этого опишем еще две
|
||
переменные <code>min</code> и <code>max</code> типа <code>real</code> и добавим в конец программы следующие операторы:
|
||
</p>
|
||
<blockquote><code><b>if</b> a < b <b>then</b>
|
||
<b><br>begin</b>
|
||
<br>
|
||
min := a;
|
||
<br> max := b;
|
||
<b><br>end</b>
|
||
<b><br>else</b>
|
||
<b><br>begin</b> <br>
|
||
min := b;
|
||
<br> max := a;
|
||
<b><br>end</b>;
|
||
<b><br>if</b> c < min <b>then</b> <br>
|
||
min := c
|
||
<b><br>else</b>
|
||
<b>if</b> c > max <b>then</b> <br>
|
||
max := c;
|
||
|
||
</code></blockquote>
|
||
<p>Таким образом, для одновременного нахождения минимального и максимального из трех чисел требуется
|
||
не более трех операций сравнения и не более трех операций присваивания.
|
||
</p>
|
||
|
||
<hr>
|
||
<h3>Вывод результатов и их форматирование
|
||
</h3>
|
||
<p>Осталось вывести полученные результаты. Вывод, как и ввод, следует выполнять с помощью стандартных процедур
|
||
языка Pascal, учитывая их особенности.
|
||
</p>
|
||
<p>Вначале, в качестве примера, организуем вывод, не соответствующий условиям задачи. Для этого добавим в конец программы
|
||
следующий оператор:
|
||
</p>
|
||
<blockquote><code>Println(min, max); </code></blockquote>
|
||
<p>Приведем вид окна задачника при запуске полученной программы:
|
||
</p>
|
||
|
||
<blockquote>
|
||
<img border="0" src="gif/ExamBegin2-2.png">
|
||
</blockquote>
|
||
|
||
<p>Мы видим, что минимум и максимум найдены правильно, однако выведены не в том формате,
|
||
который требовался (требуемый формат приводится в разделе с примером верного решения).
|
||
Мы допустили при выводе три ошибки: во-первых, вывели оба числа в одной строке
|
||
(при этом они «слились», поскольку мы не предусмотрели вывод пробела-разделителя), во-вторых,
|
||
не снабдили числа комментариями и, в-третьих, не настроили их отображение в формате
|
||
с двумя дробными знаками (первое число было выведено с единственным знаком после точки).
|
||
</p>
|
||
<p>
|
||
<b>Примечание.</b> Следует обратить внимание на панель индикаторов, которая отображается между информационной панелью
|
||
и разделом с формулировкой задания в случае, если запуск программы не является
|
||
ни демонстрационным, ни ознакомительным. Обычно на этой панели выводятся три индикатора: первый указывает
|
||
количество введенных исходных данных, второй — количество выведенных результатов, а третий —
|
||
количество успешно пройденных тестовых испытаний. При выполнении заданий, связанных с ЕГЭ, первые два
|
||
индикатора являются неактивными, поскольку, как было отмечено выше, для получения исходных данных
|
||
и записи результатов не используются средства задачника, и поэтому он не в состоянии
|
||
проконтролировать каждую операцию ввода-вывода.
|
||
</p>
|
||
<p>Для исправления первых двух ошибок достаточно изменить вывод следующим образом:
|
||
</p>
|
||
<blockquote><code>Println('MIN=', min); <br>Println('MAX=', max); </code></blockquote>
|
||
<p>Однако в этом случае числа по-прежнему могут содержать неверное число дробных знаков.
|
||
Для исправления этой последней ошибки проще всего использовать
|
||
<i>атрибуты форматирования</i>, начинающиеся с символа «:» (двоеточие):
|
||
</p>
|
||
<blockquote><code>Println('MIN=', min:0:2); <br>Println('MAX=', max:0:2); </code></blockquote>
|
||
<p>Первый атрибут определяет <i>ширину поля вывода</i> (если ширина равна 0, то используется минимально
|
||
необходимое поле вывода). Наличие второго атрибута (допустимого только для вещественных чисел) означает,
|
||
что число надо вывести в формате с фиксированной точкой, причем его значение равно количеству дробных знаков.
|
||
</p>
|
||
<p>При запуске исправленной программы будет выведено сообщение о верном решении, а после трех
|
||
запусков — сообщение о том, что задание выполнено:
|
||
</p>
|
||
|
||
<blockquote>
|
||
<img border="0" src="gif/ExamBegin2-3.png">
|
||
</blockquote>
|
||
|
||
|
||
<p>В случае успешного прохождения тестового испытания в окно задачника не включается
|
||
раздел с примером верного решения, поскольку данные этого раздела совпадают
|
||
с результатами, полученными программой.
|
||
</p>
|
||
|
||
<p>
|
||
<b>Примечание.</b>
|
||
В системе PascalABC.NET,
|
||
благодаря специальному механизму перенаправления данных, стандартные процедуры <code>read-write</code> можно использовать
|
||
и при выполнении заданий из других групп, однако важно учитывать ряд особенностей использования этих процедур
|
||
в заданиях групп Exam. Во-первых, только в заданиях групп Exam будут проявляться различия в использовании
|
||
процедур <code>read-write</code> и <code>readln-writeln</code> (в остальных группах для ввода-вывода можно использовать как вариант
|
||
процедуры с суффиксом «ln», так и вариант без этого суффикса). Во-вторых, только в заданиях
|
||
групп Exam можно при необходимости <i>использовать атрибуты форматирования</i> при выводе результатов,
|
||
а также <i>выводить дополнительные комментарии</i>, если этого требует условие задачи. В-третьих,
|
||
только в заданиях групп Exam можно вводить и выводить элементы данных несколькими способами, с использованием переменных
|
||
различных типов; например, исходную строку можно либо сразу прочесть в строковую переменную, либо вводить
|
||
посимвольно в цикле (в других группах заданий проводится более строгая проверка на соответствие типа переменной
|
||
типу элемента исходных или результирующих данных).
|
||
</p>
|
||
|
||
|
||
<hr>
|
||
<h2>Пример 2. Ввод и вывод массивов
|
||
</h2>
|
||
<hr>
|
||
|
||
<p>Рассмотрим еще одно задание группы ExamBegin, особенностью которого является вывод в качестве результата
|
||
элементов двумерного массива.
|
||
</p>
|
||
|
||
<p class="task">ExamBegin28°. На вход в первой строке подаются два целых положительных числа <i>M</i> и <i>N</i>,
|
||
во второй строке — вещественное число <i>D</i>, а в третьей строке — набор из <i>M</i> вещественных чисел.
|
||
Сформировать и вывести двумерный вещественный массив размера <i>M</i> × <i>N</i>, у которого первый
|
||
столбец совпадает с исходным набором чисел, а элементы каждого следующего столбца равны сумме соответствующего
|
||
элемента предыдущего столбца и числа <i>D</i> (в результате каждая строка массива будет содержать
|
||
элементы <i>арифметической прогрессии</i>). Каждую строку элементов массива выводить на новой экранной строке,
|
||
для каждого числа отводить 7 экранных позиций.
|
||
</p>
|
||
|
||
|
||
<p>При запуске программы-заготовки, созданной для этого задания, окно задачника примет следующий вид:
|
||
</p>
|
||
|
||
<blockquote>
|
||
<img border="0" src="gif/ExamBegin28-1.png">
|
||
</blockquote>
|
||
|
||
|
||
<p>Анализируя исходные данные, можно заметить, что полученная матрица должна иметь 8 строк, тогда как
|
||
на экране отображаются только первые пять.
|
||
Это связано с тем, что по умолчанию используется режим «свернутого» отображения данных, при котором
|
||
на экране выводится только несколько начальных строк. Признаком того, что имеются данные,
|
||
не выведенные на экране, является кнопка, которая отображается в правом верхнем углу раздела исходных данных
|
||
(на этой кнопке изображается стилизованная стрелка, направленная вниз).
|
||
Для вывода всех данных достаточно нажать эту кнопку; можно также нажать клавишу <b>Ins</b> или выполнить
|
||
щелчок мышью в любом месте раздела с данными задания (кроме раздела, содержащего формулировку).
|
||
Если выполнить эти действия для нашего окна, то оно изменится следующим образом:</p>
|
||
<blockquote>
|
||
<img border="0" src="gif/ExamBegin28-2.png">
|
||
</blockquote>
|
||
<p>Повторный щелчок мышью, нажатие клавиши <b>Ins</b> или кнопки (на которой в данной ситуации будет отображаться
|
||
стрелка, направленная вверх — см. рисунок) восстанавливает «сокращенное»
|
||
отображение данных. Заметим, что в режиме «сокращенного» отображения нумеруется только первая строка данных,
|
||
а в режиме полного отображения нумерацией снабжаются все строки.</p>
|
||
|
||
<p>
|
||
<a href="#scroll">Дополнительные возможности</a>, связанные с просмотром
|
||
данных большого размера, будут описаны далее, в пункте, посвященном задачам повышенной сложности.
|
||
</p>
|
||
|
||
<p>Если закрыть окно задачника, находясь в режиме отображения всех данных,
|
||
то при последующих запусках программы окно будет сразу отображаться в этом режиме.
|
||
</p>
|
||
|
||
<p>Приведем вариант правильного решения данной задачи (в этом варианте учитывается, что результирующий
|
||
двумерный массив имеет не более 10 строк и столбцов; соответствующее условие приведено в
|
||
преамбуле к описанию
|
||
группы ExamBegin):
|
||
</p>
|
||
|
||
<blockquote><code><pre><b>uses</b> PT4Exam;
|
||
<b>var</b>
|
||
m, n, i, j: integer;
|
||
d: real;
|
||
a: array[1..10, 1..10] of real;
|
||
<b>begin</b>
|
||
Task('ExamBegin28');
|
||
readln(m, n, d);
|
||
<b>for</b> i := 1 <b>to</b> m <b>do</b>
|
||
read(a[i, 1]);
|
||
<b>for</b> j := 2 <b>to</b> n <b>do</b>
|
||
<b>for</b> i := 1 <b>to</b> m <b>do</b>
|
||
a[i, j] := a[i, j - 1] + d;
|
||
<b>for</b> i := 1 <b>to</b> m <b>do</b>
|
||
<b>begin</b>
|
||
<b>for</b> j := 1 <b>to</b> n <b>do</b>
|
||
write(a[i, j]:7:2);
|
||
writeln;
|
||
<b>end</b>;
|
||
<b>end</b>.
|
||
</pre></code></blockquote>
|
||
|
||
<p>В приведенном решении следует обратить особое внимание на организацию ввода-вывода.
|
||
Укажем две особенности, связанные с вводом. Во-первых, несмотря
|
||
на то что по условию число <code>d</code> находится во второй строке, мы смогли включить его в один список с
|
||
предшествующими числами <code>m</code> и <code>n</code> (поскольку при чтении числовых данных переход на новую строку выполняется
|
||
автоматически). Во-вторых, при чтении элементов исходного набора <i>необходимо</i> использовать вариант
|
||
процедуры <code>read</code> без суффикса «ln», чтобы не пропустить оставшиеся в этой строке числа.
|
||
</p>
|
||
<p>При выводе полученного двумерного массива необходимо обеспечить его правильное <i>форматирование</i>:
|
||
каждый элемент должен выводиться на семи экранных позициях с двумя дробными знаками и, кроме того,
|
||
каждая строка массива должна выводиться на новой экранной строке. Это достигается за счет использования
|
||
соответствующих атрибутов форматирования и явного перехода на новую строку с помощью процедуры
|
||
<code>writeln</code> без параметров.
|
||
</p>
|
||
<p>
|
||
<b>Примечание.</b>
|
||
Заметим, что в заданиях группы Matrix,
|
||
также посвященной обработке двумерных массивов, специальные действия по форматированию полученных массивов
|
||
выполнять не требуется, так как задачник автоматически форматирует все полученные результаты.
|
||
Таким образом, задания группы ExamBegin «более приближены» к реальной экзаменационной ситуации,
|
||
в которой программа учащегося должна не только обрабатывать исходные данные, но и обеспечивать наглядное
|
||
отображение результатов.
|
||
</p>
|
||
|
||
<hr>
|
||
<a name="taskc"></a>
|
||
<h2>Пример 3. Обработка сложных наборов данных
|
||
</h2>
|
||
<hr>
|
||
|
||
<p>Группа ExamTaskC содержит 100 типовых заданий, аналогичных заданиям,
|
||
которые предлагаются на ЕГЭ по информатике
|
||
в качестве задач повышенной сложности (задача C4). Основную часть данной группы составляют
|
||
задания на обработку сложных наборов данных (записей) с элементами-полями различных типов.
|
||
В подобных заданиях требуется правильно выбрать способ хранения данных и организовать их эффективную обработку;
|
||
при этом обычно требуется применить <i>несколько</i> базовых алгоритмов, например, алгоритм суммирования
|
||
или нахождения минимума/максимума и алгоритм поиска нужного элемента или сортировки набора данных по требуемому ключу.
|
||
В группу ExamTaskC включены также задания повышенной сложности на обработку текстовых данных
|
||
(подобные задания содержатся в завершающем разделе данной группы).
|
||
</p>
|
||
<p>Следует заметить, что возможность автоматической генерации
|
||
больших наборов исходных данных, предоставляемая задачником Programming Taskbook, позволяет существенно ускорить
|
||
тестирование учебных программ и сделать его более надежным, что, в свою очередь, повышает эффективность изучения
|
||
типовых приемов решения задач группы C.
|
||
</p>
|
||
<p>В заданиях группы ExamTaskC ввод и вывод имеет те же особенности,
|
||
что и в заданиях группы ExamBegin.
|
||
</p>
|
||
<p>Рассмотрим следующее задание.
|
||
</p>
|
||
|
||
<p class="task">ExamTaskC25°. На вход подаются сведения об абитуриентах. В первой строке
|
||
указывается количество абитуриентов <i>N</i>, каждая из последующих <i>N</i> строк имеет
|
||
формат<br> <tt><Номер школы> <Год поступления> <Фамилия></tt><br>
|
||
Номер школы содержит не более двух цифр, годы лежат в диапазоне от 1990 до 2010. Для каждого года,
|
||
присутствующего в исходных данных, вывести общее число абитуриентов, поступивших в этом году
|
||
(вначале выводить год, затем число абитуриентов). Сведения о каждом годе выводить на новой строке
|
||
и упорядочивать по возрастанию номера года.</p>
|
||
|
||
|
||
<p>Программа-заготовка, созданная для этого задания, подобно заготовкам для заданий группы ExamBegin,
|
||
будет использовать специальный модуль <code>PT4Exam</code>:
|
||
</p>
|
||
|
||
<blockquote><code><pre><b>uses</b> PT4Exam;
|
||
|
||
<b>begin</b>
|
||
Task('ExamTaskC25');
|
||
|
||
<b>end</b>.
|
||
</pre></code></blockquote>
|
||
|
||
<p>При запуске этой программы на экране появится окно задачника, содержащее следующие данные:
|
||
</p>
|
||
|
||
<blockquote>
|
||
<img border="0" src="gif/ExamTaskC25-1.png">
|
||
</blockquote>
|
||
|
||
<p>Окно будет иметь такой вид, если при его предшествующем закрытии оно находилось в режиме
|
||
отображения всех данных.
|
||
Для отображения всех данных на экране может потребоваться увеличить высоту окна; для этого достаточно
|
||
зацепить мышью заголовок окна и переместить его вверх (для перемещения заголовка окна задачника вверх и вниз
|
||
можно также воспользоваться клавиатурными комбинациями <b>Ctrl+Up</b> и <b>Ctrl+Down</b>).
|
||
</p>
|
||
<p>При первом тестовом испытании программы ей будет предложен для обработки
|
||
набор данных не слишком большого размера (порядка 10–20 элементов).
|
||
</p>
|
||
<p>Вначале следует определиться со структурами данных, которые будут использоваться в программе. Поскольку
|
||
требуется найти одну характеристику для каждого года, а число лет невелико, можно использовать
|
||
числовой массив <code>year</code>, каждый элемент которого соответствует определенному году. Так как в языке Pascal можно
|
||
использовать произвольные границы индексов, удобно в качестве диапазона индексов указать диапазон лет,
|
||
который требуется проанализировать: <code>1990..2010</code>. В начале программы выполним инициализацию элементов массива,
|
||
положив их значения равными <code>0</code>
|
||
(заметим, что если после обработки исходных данных некоторые элементы массива <code>year</code>
|
||
останутся нулевыми, то это будет означать, что соответствующие годы не были представлены в наборе исходных данных,
|
||
и выводить информацию о них не следует).
|
||
</p>
|
||
|
||
<p>После инициализации массива следует прочесть информацию о количестве абитуриентов и организовать цикл,
|
||
в котором будут обрабатываться данные о каждом абитуриенте и соответствующим образом корректироваться
|
||
элементы массива <code>year</code>. В дальнейшем сведения об уже обработанном абитуриенте нам не будут нужны, поэтому сохранять
|
||
их в специальном наборе данных (например, массиве) не требуется. Заметим также, что фамилия абитуриента
|
||
для решения задачи не требуется, поэтому после чтения двух числовых данных можно сразу переходить к новой строке,
|
||
пропуская строковый элемент данных (фамилию). В задаче не нужно использовать
|
||
и номера школ, однако их придется считывать, так как только после номера школы указывается интересующий
|
||
нас год поступления абитуриента.
|
||
</p>
|
||
|
||
<p>Когда данные обо всех абитуриентах будут обработаны,
|
||
в массиве <code>year</code> будет содержаться вся необходимая информация, которую останется
|
||
вывести в формате, указанном в условии задачи.
|
||
</p>
|
||
|
||
<p>Приведем первый вариант решения (этот вариант содержит одну ошибку):
|
||
</p>
|
||
|
||
<blockquote><code><pre><b>uses</b> PT4Exam;
|
||
<b>var</b>
|
||
n, i, k, m: integer;
|
||
year: array[1990..2010] of integer;
|
||
<b>begin</b>
|
||
Task('ExamTaskC25');
|
||
<b>for</b> i := 1990 <b>to</b> 2010 <b>do</b>
|
||
year[i] := 0;
|
||
readln(n);
|
||
<b>for</b> i := 1 <b>to</b> n <b>do</b>
|
||
<b>begin</b>
|
||
readln(k, m); <i>{ k - номер школы, m - год поступления }</i>
|
||
Inc(year[m]);
|
||
<b>end</b>;
|
||
<b>for</b> i := 1990 <b>to</b> 2010 <b>do</b>
|
||
writeln(i, ' ', year[i]);
|
||
<b>end</b>.
|
||
</pre></code></blockquote>
|
||
|
||
<p>Ошибка связана с тем, что на экран выводится информация о годах, отсутствующих в наборе исходных данных.
|
||
Поэтому она сразу будет выявлена при обработке наборов данных небольшого размера,
|
||
предлагаемых программе при первом тестовом запуске
|
||
(для большей наглядности приведем окно задачника в режиме сокращенного отображения данных, при котором
|
||
выводятся только пять первых элементов из каждого набора данных):
|
||
</p>
|
||
|
||
<blockquote>
|
||
<img border="0" src="gif/ExamTaskC25-2.png">
|
||
</blockquote>
|
||
<p>Для исправления ошибки достаточно добавить в последний цикл условный оператор:
|
||
</p>
|
||
|
||
<blockquote><code><pre><b>for</b> i := 1990 <b>to</b> 2010 <b>do</b>
|
||
<b>if</b> year[i] > 0 <b>then</b>
|
||
writeln(i, ' ', year[i]);
|
||
</pre></code></blockquote>
|
||
|
||
|
||
<p>Теперь все 9 тестовых испытаний программы, требуемых для того, чтобы решение было зачтено как выполненное,
|
||
будут пройдены успешно.
|
||
</p>
|
||
<a name="scroll"></a><p>Завершая рассмотрение этого задания, опишем некоторые дополнительные возможности, связанные
|
||
с просмотром больших наборов данных.
|
||
</p>
|
||
<p>Начиная со второго испытания,
|
||
программе может быть предложен для обработки набор исходных данных большего размера (порядка 50–100
|
||
элементов). При этом уже не удастся отобразить на экране все данные, связанные с заданием.
|
||
В подобной ситуации у правой границы окна задачника появится <i>полоса прокрутки</i>, позволяющая
|
||
перемещаться к той части данных, которая первоначально не отображается на экране.
|
||
Прокрутку данных можно выполнять не только с помощью полосы прокрутки, но и используя
|
||
клавиши со стрелками, <b>PgUp</b>, <b>PgDn</b>, <b>Home</b>, <b>End</b>, а также колесико мыши.
|
||
</p>
|
||
<p>Помимо стандартных действий по прокрутке данных, в окне задачника предусмотрены возможности
|
||
«интеллектуальной» прокрутки,
|
||
позволяющие быстро перейти к началу каждого раздела задания, а также сравнить соответствующие фрагменты
|
||
полученных результатов и примера верного решения. Для циклического перебора разделов сверху вниз
|
||
предназначена клавиша <b>[+]</b> (а также комбинация <b>Ctrl+PgDn</b>), для циклического перебора разделов снизу вверх
|
||
— клавиша <b>[–]</b> (а также комбинация <b>Ctrl+PgUp</b>). Для быстрого переключения между
|
||
соответствующими фрагментами разделов с результатами и с примером верного решения предназначена клавиша <b>[/]</b>
|
||
(а также комбинация <b>Ctrl+Tab</b>). Все эти действия можно выполнить и с помощью мыши; для этого
|
||
предусмотрены кнопки в левом верхнем углу прокручиваемой области окна, отведенной под отображение разделов задания
|
||
(эти кнопки отображаются
|
||
на экране, если размер данных, связанных с заданием, превышает размеры окна).
|
||
Приведем вид окна задачника с полосой прокрутки и дополнительными кнопками:
|
||
</p>
|
||
<blockquote>
|
||
<img border="0" src="gif/ExamTaskC25-3.png">
|
||
</blockquote>
|
||
<p>Обозначения на кнопках совпадают с клавишами,
|
||
выполняющими те же действия; при наведении мышью на кнопку рядом с ней появляется всплывающая подсказка.
|
||
</p>
|
||
<p>Кроме трех кнопок, связанных с «интеллектуальной» прокруткой,
|
||
в приведенном на рисунке окне отображаются еще две дополнительные кнопки.
|
||
Первая из них располагается в правом верхнем углу раздела с формулировкой
|
||
и позволяет временно скрыть (а в дальнейшем опять отобразить)
|
||
раздел с формулировкой (эти же действия можно выполнить с помощью клавиши <b>Del</b> или щелчка мышью
|
||
на разделе с формулировкой).
|
||
Вторая дополнительная кнопка расположена в правом верхнем углу раздела с исходными данными.
|
||
Как уже отмечалось ранее, эта кнопка позволяет переключаться между полным
|
||
и сокращенным отображением наборов данных. Напомним, что
|
||
изображение на этой кнопке показывает текущий режим отображения данных. Например, если на кнопке изображена
|
||
стилизованная стрелка, направленная вверх (как на приведенном выше рисунке),
|
||
значит, в данный момент в окне отображаются все данные, а нажатие на эту кнопку переведет окно
|
||
в режим отображения нескольких начальных (как правило, пяти) элементов каждого набора данных.
|
||
</p>
|
||
<p>Дополнительная информация о возможностях
|
||
режима окна с динамической компоновкой приведена в <a href="../PT4/window.html#dynmode">соответствующем разделе</a>
|
||
страницы, посвященной описанию окна задачника.
|
||
</p>
|
||
|
||
<hr>
|
||
<h2>Пример 4. Более сложное задание на обработку наборов данных
|
||
</h2>
|
||
<hr>
|
||
|
||
<p class="task">ExamTaskC53°. На вход подаются сведения о ценах на бензин на автозаправочных станциях (АЗС).
|
||
В первой строке содержится значение <i>M</i> одной из марок бензина, во второй строке указывается
|
||
целое число <i>N</i>, а каждая из последующих <i>N</i> строк имеет формат<br>
|
||
<tt><Марка бензина> <Улица> <Компания> <Цена 1 литра (в копейках)></tt><br>
|
||
Имеется не более 20 различных компаний и не более 30 различных улиц; названия компаний и улиц
|
||
не содержат пробелов. В качестве марки бензина указываются числа 92, 95 или 98. Цена задается целым числом
|
||
в диапазоне от 2000 до 3000. Каждая компания имеет не более одной АЗС на каждой улице;
|
||
цены на разных АЗС одной и той же компании могут различаться. Для каждой улицы, на которой имеются
|
||
АЗС с бензином марки <i>M</i>, определить максимальную цену бензина этой марки (вначале выводить максимальную
|
||
цену, затем название улицы). Сведения о каждой улице выводить на новой строке и упорядочивать
|
||
по возрастанию максимальной цены, а для одинаковой цены — по названиям улиц в алфавитном порядке.
|
||
Если ни одной АЗС с бензином марки <i>M</i> не найдено, то вывести текст «Нет».
|
||
</p>
|
||
|
||
|
||
|
||
<p>Приведем окно задачника, которое появится на экране при запуске программы-заготовки для данного задания
|
||
(в данном окне скрыт раздел с формулировкой; в результате оказались скрытыми и кнопки,
|
||
отвечающие за «интеллектуальную» прокрутку, поскольку в окне полностью отображается
|
||
содержимое оставшихся разделов):
|
||
</p>
|
||
<blockquote>
|
||
<img border="0" src="gif/ExamTaskC53-1.png">
|
||
</blockquote>
|
||
|
||
|
||
<p>Выясним, какая структура является наиболее подходящей для хранения информации, необходимой для решения задачи.
|
||
Нам требуется информация, связанная с различными улицами, которых по условию не более 30, причем для каждой улицы
|
||
надо хранить сведения двух видов: ее название и максимальную цену бензина марки <i>M</i>. Поэтому мы можем либо завести
|
||
массив из 30 элементов-записей с двумя полями, либо два массива: один содержащий названия улиц, а другой —
|
||
максимальные цены. Учитывая, что в конце программы нам потребуется выполнять сортировку полученных данных,
|
||
целесообразнее использовать массив записей, поскольку это позволит записать алгоритм сортировки
|
||
в более компактной форме.
|
||
</p>
|
||
|
||
<p>Определим запись <code>Street</code> с двумя полями <code>name</code> и <code>max</code> и опишем массив <code>s</code>
|
||
из 30 элементов типа <code>Street</code>.
|
||
Следует также завести переменную <code>ns</code>, в которой будет храниться количество заполненных элементов массива <code>s</code>.
|
||
</p>
|
||
|
||
<p>При обработке каждой строки с исходными данными нам будут нужны прежде всего сведения о марке бензина.
|
||
Если марка бензина не равна <code>M</code>, то оставшуюся часть строки обрабатывать не требуется, и можно сразу перейти
|
||
к разбору следующей строки. Если марка бензина равна <code>M</code>, то необходимо узнать название улицы <code>s0</code> и цену бензина <code>p</code>.
|
||
Заметим, что название компании для решения задачи не требуется, однако его необходимо прочесть, чтобы определить
|
||
следующий элемент данных — цену бензина.
|
||
</p>
|
||
|
||
<p>Если улица с названием <code>s0</code> еще не была включена в массив <code>s</code>, то ее необходимо включить в массив, присвоив
|
||
полю <code>max</code> значение <code>p</code>. Если же улица уже присутствует в массиве, то необходимо сравнить поле <code>max</code> для данной улицы
|
||
и значение <code>p</code>, изменив при необходимости поле <code>max</code> (здесь мы используем базовый алгоритм нахождения
|
||
максимального значения).
|
||
</p>
|
||
|
||
<p>Для ввода названий улиц и компаний в нашем случае удобно организовать <i>посимвольное</i> чтение строковых данных;
|
||
признаком завершения такого чтения будет обнаружение пробельного символа.
|
||
</p>
|
||
|
||
<p>После обработки набора исходных данных необходимо проверить, найдена ли хотя бы одна улица с АЗС,
|
||
предлагающей марку бензина <code>M</code> (для этого достаточно сравнить значение <code>ns</code> с нулем). Если ни одна улица
|
||
не найдена, то надо вывести строку «Нет»; в противном случае требуется выполнить сортировку
|
||
массива <code>s</code> по указанному набору ключей и вывести полученные данные в требуемом порядке. Поскольку размер
|
||
массива невелик, для его сортировки вполне допустимо использовать один из простых алгоритмов,
|
||
например, алгоритм <i>пузырьковой сортировки</i>.
|
||
</p>
|
||
|
||
<p>Приведем один из вариантов правильного решения задачи:
|
||
</p>
|
||
|
||
<blockquote><code><pre><b>uses</b> PT4Exam;
|
||
<b>type</b>
|
||
Street = <b>record</b>
|
||
name: string;
|
||
max: integer;
|
||
<b>end</b>;
|
||
<b>var</b>
|
||
m, n, ns, i, j, k, p: integer;
|
||
s: array[1..30] of Street;
|
||
s0: string;
|
||
x: Street;
|
||
c: char;
|
||
<b>begin</b>
|
||
Task('ExamTaskC53');
|
||
readln(m); <i>{ m - марка бензина }</i>
|
||
readln(n);
|
||
ns := 0;
|
||
<b>for</b> i := 1 <b>to</b> n <b>do</b>
|
||
<b>begin</b>
|
||
read(k);
|
||
<b>if</b> k <> m <b>then</b>
|
||
readln <i>{ пропускаем оставшуюся часть строки }</i>
|
||
<b>else</b>
|
||
<b>begin</b>
|
||
s0 := '';
|
||
read(c); <i>{ пропускаем пробел после первого числа }</i>
|
||
read(c); <i>{ читаем первый символ названия улицы }</i>
|
||
<b>while</b> c <> ' ' <b>do</b>
|
||
<b>begin</b>
|
||
s0 := s0 + c;
|
||
read(c);
|
||
<b>end</b>;
|
||
read(c); <i>{ читаем первый символ названия компании }</i>
|
||
<b>while</b> c <> ' ' <b>do</b>
|
||
read(c); <i>{ название компании не сохраняем }</i>
|
||
readln(p); <i>{ читаем цену бензина и переходим на новую строку }</i>
|
||
<i>{ Обработка прочитанной информации }</i>
|
||
k := 0;
|
||
<b>for</b> j := 1 <b>to</b> ns <b>do</b>
|
||
<b>if</b> s[j].name = s0 <b>then</b> <i>{ улица уже содержится в массиве s }</i>
|
||
<b>begin</b>
|
||
k := 1;
|
||
<b>if</b> s[j].max < p <b>then</b>
|
||
s[j].max := p;
|
||
break;
|
||
<b>end</b>;
|
||
<b>if</b> k = 0 <b>then</b> <i>{ улица еще не содержится в массиве s }</i>
|
||
<b>begin</b>
|
||
Inc(ns);
|
||
s[ns].name := s0;
|
||
s[ns].max := p;
|
||
<b>end</b>;
|
||
<b>end</b>;
|
||
<b>end</b>;
|
||
<b>if</b> ns = 0 <b>then</b> <i>{ ни одной улицы не найдено }</i>
|
||
writeln('Нет')
|
||
<b>else</b>
|
||
<b>begin</b>
|
||
<i>{ Сортировка по возрастанию максимальной цены,</i>
|
||
<i> а для одинаковых цен - по названиям улиц }</i>
|
||
<b>for</b> k := 1 <b>to</b> ns - 1 <b>do</b>
|
||
<b>for</b> i := 1 <b>to</b> ns - k <b>do</b>
|
||
<b>if</b> (s[i].max > s[i + 1].max) <b>or</b>
|
||
(s[i].max = s[i + 1].max) <b>and</b>
|
||
(s[i].name > s[i + 1].name) <b>then</b>
|
||
<b>begin</b>
|
||
x := s[i];
|
||
s[i] := s[i + 1];
|
||
s[i + 1] := x;
|
||
<b>end</b>;
|
||
<i>{ Вывод результатов в требуемом порядке }</i>
|
||
<b>for</b> i := 1 <b>to</b> ns <b>do</b>
|
||
writeln(s[i].max,' ',s[i].name);
|
||
<b>end</b>;
|
||
<b>end</b>.
|
||
</pre></code></blockquote>
|
||
|
||
|