Задачи на обработку текста Задача 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.