Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
24
Добавлен:
19.05.2015
Размер:
719.36 Кб
Скачать

Var c:char;

num, ind:array[0..9] of integer;

I, j, k:integer;

begin

{ начальные значения }

for i:=0 to 9 do begin

num[i] := 0;

ind[i] := i;

end;

{ ввод данных, подсчет цифр в массиве num }

read(c);

while c <> '.' do begin

k := Ord(c) - Ord('0');

num[k] := num[k] + 1;

read(c);

end;

{ сортировка «пузырьком» }

for i:=0 to 8 do

for j:=8 downto i do

if num[ind[j]] > num[ind[j+1]] then begin

k:=ind[j]; ind[j]:=ind[j+1]; ind[j+1]:=k

end;

{ вывод результата }

for i:=0 to 9 do

if num[ind[i]]<>0 then write(ind[i])

end.

В чем отличие? Во-первых, цикл ввода изменен так, чтобы избавиться от условного оператора. Мы знаем, что по условию кроме цифр и точки никаких других символов быть не может, поэтому отдельно нужно обработать только точку. Для этого цикл с постусловием repeat заменен на цикл с предусловием while, оператор read перенесен в конец цикла, но перед циклом пришлось поставить еще один оператор read (иначе на первом проходе в переменной c будет неопределенное значение).

Во-вторых, здесь применяется сортировка по индексам. Элементы массива ind представляют собой уже не цифры, а индексы элементов массива num в отсортированном порядке. Поэтому при сортировке можно переставлять только индексы, а элементы массива num не трогать. За такую оптимизацию приходится расплачиваться менее понятной записью: к элементу отсортированного массива num приходится обращаться с помощью двойной адресации типа num[ind[i]], что означает «значение элемента массива num, номер которого находится в элементе массива ind с номером i». Это стандартный профессиональный прием, но для его использования нужно хорошо понимать, что вы делаете.

Ещё одно интересное решение задачи предложил Е.И. Тищенко (ОГОУ Полянская школа-интернат Рязанской обл.):

Var num: array['0'..'9'] of integer;

I, min: integer;

c, iMin: char;

begin

for c:='0' to '9' do num[c] := 0;

{ ввод данных, подсчет цифр в массиве num }

repeat

read(c);

if ('0' <= c) and (c <= '9') then

num[c] := num[c] + 1;

until c = '.';

{ вывод результата совместно с сортировкой }

for i:=1 to 10 do begin

min := maxInt;

for c:='0' to '9' do

if (num[c] > 0) and (num[c] < min) then begin

min:=num[c];

iMin:=c

end;

if min = maxInt then break;

write(iMin);

num[iMin]:=0;

end;

end.

Во-первых, здесь использован массив с символьными индексами (это можно делать в Паскале), что позволило упростить цикл ввода данных: получив очередную цифру, не требуется специально вычислять индекс нужного элемента массива.

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

for i:=1 to 10 do begin

{ ищем индекс iMin минимального ненулевого элемента в num }

{ если не нашли, то выйти из цикла }

write(iMin);

num[iMin]:=0;

end;

На каждом щаге цикла ищем минимальный ненулевой элемент в массиве num. Если такой элемент не найден (все оставшиеся элементы нулевые), выходим из цикла с помощью оператора break. Если такой элемент найден, выводим на экран его символьный индекс iMin и обнуляем соответствующий элемент массива num[iMin], чтобы не «захватить» его при следующем проходе.

Для поиска минимального элемента используем стандартный алгоритм с запоминанием значения минимального элемента и его номера, причем в начале в переменную min записывается наибольшее целое число maxInt:

min := maxInt;

for c:='0' to '9' do

if (num[c] > 0) and (num[c] < min) then begin

min:=num[c];

iMin:=c

end;

Если в переменной min осталось это значение maxInt, все элементы массива num нулевые и нужно выйти из цикла:

if min = maxInt then break;

  1. Как и в двух предыдущих задачах, нас интересует только количество разных цифр. Поэтому ввод данных и подсчет цифр выполняется так же, как и в задаче 24 (с помощью массива num). Разница только в том, что здесь индексы массива начинаются не с нуля, а с 1 (ноль нам не нужен, это признак окончания ввода):

for i:=1 to 9 do num[i] := 0;

repeat

read(c);

if ('1' <= c) and (c <= '9') then begin

k := Ord(c) - Ord('0');

num[k] := num[k] + 1;

end;

until c = '0';

Главный вопрос – как найти число-палиндром, и притом минимальное из всех возможных? Палиндром можно разбить на три части – два «крыла», симметричных относительно вертикальной оси, и центральная часть – она может состоять из одного символа или вообще отсутствовать:

Палиндром

Левое крыло

Центр

Правое крыло

1234554321

12345

54321

12345654321

12345

6

54321

Если в левую часть входит некоторая цифра, то она входит и в правую часть, поэтому «крылья» образованы парами цифр. Причем для того, чтобы число было минимальным, числа в левом крыле должны увеличиваться, а в правом – уменьшаться.

Удобнее всего ввести две символьных переменных sL и sR, которые будут обозначать соответственно левое и правое крылья. Сначала запишем в них пустые строки:

sL := '';

sR := '';

Затем просматриваем все цифры с младшей до старшей, чтобы числа в левом крыле увеличивались. Пока для очередного числа i есть пара (счетчик num[i]>1), приписываем эту цифру в конец левого крыла и в начало правого, после этого уменьшаем счетчик num[i] на 2 (пара цифр израсходована):

for i:=1 to 9 do

while num[i] > 1 do begin

c := Chr(i+Ord('0'));

sL := sL + с;

sR := c + sR;

num[i] := num[i] - 2;

end;

После этого парных цифр уже нет. Какой выбрать центральную цифру? Чтобы число было минимальным, она должна быть минимальной. Поэтому ищем с помощью цикла while первую цифру, счетчик которой больше нуля.

i := 1;

while (i < 10) and (num[i] = 0) do

i := i + 1;

Если такая обнаружена, ставим ее в центр, то есть приписываем в конец левого крыла (вариант – в начало правого):

if i < 10 then sL := sL + Chr(i+Ord('0'));

Остается вывести результат – сцепить строки sL и sR:

writeln(sL + sR);

Вот полная программа:

Соседние файлы в папке ЕГЗ_2012_Поляков_май