На вход программе подаются сведения о номерах школ

advertisement
Задачи на обработку текста
Задача 1
На вход программе подаются сведения о номерах школ учащихся, участвовавших в олимпиаде. В первой
строке сообщается количество учащихся N, каждая из следующих N строк имеет формат:
<Фамилия> <Инициалы> <номер школы>
где <Фамилия> – строка, состоящая не более чем из 20 символов, <Инициалы> – строка, состоящая из 4-х
символов (буква, точка, буква, точка), <номер школы> – не более чем двузначный номер. <Фамилия> и
<Инициалы>, а также <Инициалы> и <номер школы> разделены одним пробелом. Пример входной строки:
Иванов П.С. 57
Требуется написать как можно более эффективную программу (укажите используемую версию языка
программирования, например, Borland Pascal 7.0), которая будет выводить на экран информацию, из какой
школы было меньше всего участников (таких школ может быть несколько). При этом необходимо вывести
информацию только по школам, пославшим хотя бы одного участника. Следует учитывать, что N>=1000.
Вариант решения PascalABC.NET
var
N, k, x, min, err :integer;
s :string;
uchastnikov :array[1..99] of Integer; {номер школы - индекс, храним количество}
begin
for k := 1 to 99 do uchastnikov[k] := 0; {зануляем счетчики}
Readln(N); {считываем количество участников
for k := 1 to N do
begin
{считываем фамилию и инициалы и номер школы}
Readln(s);
{добываем номер школы}
s := s[Length(s)-1] + s[Length(s)]; {два последних символа}
Val(s, x, err);
{обработка - увеличение количества участников от соответствующей школы}
Inc(uchastnikov[x]); {c++}
end;
{находим минимум в массиве количества участников, но не ноль}
min := MaxInt;
for k := 1 to 99 do
if (uchastnikov[k] <> 0) and (uchastnikov[k] < min) then
min := uchastnikov[k];
{выводим все школы, где количество участников равно найденному min}
for k := 1 to 99 do
if uchastnikov[k] = min then
Writeln(k);
end.
Вариант решения от К. Полякова
const LIM = 99;
var C:array[1..LIM] of integer;
i, p, N, k, r, Min: integer;
s:string;
begin
for k:=1 to 99 do C[k]:=0;
readln(N);
for i:=1 to N do begin
readln(s); { читаем очередную строку }
{ выделяем часть после второго пробела }
p := Pos(' ', s);
Delete(s, 1, p+5);
{ определяем номер школы k }
Val(s, k, r);
C[k] := C[k] + 1; { увеличиваем счетчик k-ой школы }
end;
Min := N;
for k:=1 to LIM do
if (C[k] <> 0) and (C[k]<Min) then Min := C[k];
for k:=1 to LIM do
if C[k] = Min then writeln(k);
end.
Задача 2
На вход программы подается текст на английском языке, заканчивающийся точкой (другие символы “.” в
тексте отсутствуют). Требуется написать программу, которая будет определять и выводить на экран
английскую букву, встречающуюся в этом тексте чаще всего, и количество там таких букв. Строчные и
прописные буквы при этом считаются не различимыми. Если искомых букв несколько, то программа
должна выводить на экран первую из них по алфавиту. Например, пусть файл содержит следующую запись:
It is not a simple task. Yes!
Чаще всего здесь встречаются буквы I, S и T (слово Yes в подсчете не учитывается, так как расположено
после точки). Следовательно, в данном случае программа должна вывести два символа, разделенных
пробелом: I 3
Решение от Т. Хирьянова (PascalABC.NET)
var
kolichestvo :array['a'..'z'] of Integer; {индекс - буква}
max :integer;
c, max_c :char;
begin
for c := 'a' to 'z' do kolichestvo[c] := 0;
read(c);
while c <> '.' do
begin
{обработка}
if (c >= 'A') and (c <= 'Z') then
c := LowerCase(c); {c := Chr(Ord('A') + Ord(c) - Ord('a'))}
if (c >= 'a') and (c <= 'z') then
kolichestvo[c] += 1;
{считывание следующей буквы}
read(c);
end;
max := 0;
for c := 'a' to 'z' do
if kolichestvo[c] > max then
begin
max := kolichestvo[c];
max_c := c;
end;
Writeln(max_c, ' ', max);
end.
Задача 3
На вход программы подается 366 строк, которые содержат информацию о среднесуточной температуре всех
дней 2008 года. Формат каждой из строк следующий: сначала записана дата в виде dd.mm (на запись номера
дня и номера месяца в числовом формате отводится строго два символа, день от месяца отделен точкой),
затем через пробел записано значение температуры — число со знаком плюс или минус, с точностью до 1
цифры после десятичной точки. Данная информация отсортирована по значению температуры, то есть
хронологический порядок нарушен. Требуется написать программу на языке Паскаль или Бейсик, которая
будет выводить на экран информацию о месяце (месяцах), среднемесячная температура у которого
(которых) наименее отклоняется от среднегодовой. В первой строке вывести среднегодовую температуру.
Найденные значения для каждого из месяцев следует выводить в отдельной строке в виде: номер месяца,
значение среднемесячной температуры, отклонение от среднегодовой температуры.
Решение от Т. Хирьянова (PascalABC.NET)
const N = 366;
const days_in_month :array[1..12] of Integer =
(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
var
average_for_month :array [1..12] of Real;
day, month :integer;
c1, c2 :char;
temp, diff, average_for_year :Real;
begin
for month := 1 to 12 do
average_for_month[month] := 0;
{найдем суммы температур за каждый месяц}
for day := 1 to N do
begin
Read(c1); Read(c1); Read(c1); {день мне не важен}
Read(c1, c2);
month := (Ord(c1)-Ord('0'))*10 + Ord(c2)-Ord('0'); {month := StrToInt(c1 + c2)}
Read(temp); {считываем температуру}
average_for_month[month] += temp;
end;
{найдем сумму температур за весь год}
average_for_year := 0;
for month := 1 to 12 do
average_for_year += average_for_month[month];
{нормируем на количество дней в году и в месяце}
average_for_year /= N;
for month := 1 to 12 do
average_for_month[month] /= days_in_month[month];
{найдем месяц, в котором средняя температура наиболее близка к среднегодовой}
diff := average_for_month[1] - average_for_year;
for month := 2 to 12 do
if abs(average_for_month[month] - average_for_year) < abs(diff) then
diff := average_for_month[month] - average_for_year;
for month := 1 to 12 do
if abs(average_for_month[month] - average_for_year) = abs(diff) then
Writeln(month, ' ', average_for_month[month], ' ',
average_for_month[month] - average_for_year);
end.
Download