CFA LogoCFA Logo Computer
Новости Статьи Магазин Драйвера Контакты
Новости
RSS канал новостей
В конце марта компания ASRock анонсировала фирменную линейку графических ускорителей Phantom Gaming. ...
Компания Huawei продолжает заниматься расширением фирменной линейки смартфонов Y Series. Очередное ...
Компания Antec в своем очередном пресс-релизе анонсировала поставки фирменной серии блоков питания ...
Компания Thermalright отчиталась о готовности нового высокопроизводительного процессорного кулера ...
Компания Biostar сообщает в официальном пресс-релизе о готовности флагманской материнской платы ...
Самое интересное
Программаторы 25 SPI FLASH Адаптеры Optibay HDD Caddy Драйвера nVidia GeForce Драйвера AMD Radeon HD Игры на DVD Сравнение видеокарт Сравнение процессоров

АРХИВ СТАТЕЙ ЖУРНАЛА «МОЙ КОМПЬЮТЕР» ЗА 2003 ГОД

Конкурсы на ладони

Дмитрий ПАВЛОВ dpav@ukrpost.net

Давным-давно, когда автор получил номер МК с результатами третьего трурлевого конкурса и подсчитал свой результат, оставляющий желать лучшего, он задался вопросом: а как же идут дела у остальных участников? Насколько лучше или хуже? Бодренько подсчитав результаты еще для двух участников, понял, что так дело не пойдет. А не поручить ли это дело компьютеру? Но для этого надо писать программу! Прикинув, что все равно это будет быстрее, чем считать вручную, я сделал выбор. Доставать с полки свой любимый Turbo Assembler почему-то не хотелось, однако на старых дискетах нашелся tpc.exe. Так появилась программа — герой этой статьи, о всех подробностях рождения которой я и хочу поведать читателям. Для этого давайте забудем, что программа уже написана, и представим, что есть только реальная жизненная задача…

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

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

Оба стиля имеют и достоинства, и недостатки. Стиль «снизу вверх» дает оточенные, оптимизированные отдельные процедуры и подпрограммы, однако весьма трудозатратен, а также приводит к ситуации, когда за деревьями (отдельными подпрограммами) не видно леса (самой программы), причем чем деревьев больше, тем труднее. Стиль «сверху вниз» изначально оперирует более крупными блоками, поэтому здесь скорее виден лес, но не видно деревьев, из-за чего в целом программа получается неоптимальной. Идеальным является применение стиля «сверху вниз» на начальных этапах и «снизу вверх» на конечных.

Каждый программист может овладеть и тем, и другим стилем, однако предпочтения, по-видимому, индивидуальны и определяются психологическими различиями. Впрочем, это уже тема отдельной статьи.

Итак, опишем нашу будущую программу таким образом:

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

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

Теперь надо произвести дальнейшую конкретизацию. Давайте подумаем над вводом-выводом. Очевидно, в данном случае лучший выход — ввод-вывод из файлов/в файл, так как перспектива вводить данные с клавиатуры вручную может понравится только Трурлю (он же робот, ему все равно :-)). Дальше, как вы заметили, я написал цикл в максимально общем виде, не задавая его тип. Давайте подумаем, какой именно тип цикла будет наилучшим здесь. Для цикла типа for обязательно надо знать число повторений. В нашем случае, конечно, это число известно — это количество конкурсов; однако эту величину нужно знать и компьютеру. А поскольку это величина переменная, ее надо либо ввести с клавиатуры (что неприятно, хотя и не настолько, как если бы пришлось вводить все результаты), либо из файла, однако в файл нам ее тоже придется вводить самим. А нельзя ли заставить компьютер подсчитывать эту величину?

Предлагаю следующее решение. Давайте представим, что данные находятся в файлах с последовательными названиями, скажем, 1.dat, 2.dat, …, n.dat. Тогда, перебирая названия начиная с 1 до n, компьютер сможет считать из них информацию, однако на файле n+1 возникнет ошибка — «файл не найден», что и будет служить сигналом того, что информации больше нет, а количество конкурсов равно n. Для такого цикла лучше всего подходит цикл типа while или repeat..until.

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

Итак, теперь наш алгоритм выглядит так:

На этом я предлагаю закончить теоретические рассуждения по пошаговой конкретизации алгоритма, хотя это можно делать еще долго, и перейти сразу к конечной стадии этого процесса — работающей программе. В качестве языка реализации я выбрал, как вы уже догадались, Turbo Pascal 7.0. А после листинга программы я попытаюсь пояснить значения тех или иных блоков программы. Заранее прошу извинить за англо-русско-мумбо-юмбский диалект, использованный в именах переменных :-).

Итак, вот исходный текст программы.

В программе не применяются никакие дополнительные библиотеки, в частности модуль Crt (uses Crt), чтобы выполнение программ не вызывало сообщений об ошибках на быстрых компьютерах (знаменитая runtime error 200). К тому же размер откомпилированной программы крайне невелик — около 5 Кб.

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

В блоке описания переменных самыми интересными являются массивы Peoples (имена участников), Results (все результаты всех конкурсов для каждого участника), Sum (сума баллов по всем конкурсов для участников). Массив Key является массивом ключей для окончательной сортировки. А в переменной N_People хранится текущее количество участников.

Процедуры: SwapInt — вспомогательная процедура для подпрограммы Sort, меняющая местами значения двух переменных, а сама Sort, понятно, служит для сортировки. К своему стыду, автор не смог вспомнить «в полевых условиях» более сложный и эффективный алгоритм, чем пузырьковая сортировка (немного улучшенная), которую называют «самым медленный алгоритмом всех времен и народов». Однако пусть читатель не волнуется — при таких объемах информации алгоритм сортировки маловажен, для пользователя ведь все равно, выполнится сортировка за 0.1 или 0.01 секунды.

В процедуре ScanPeople проводится накопление результатов уже описанным выше способом: программа ищет участника в массиве Peoples, при нахождении текущие баллы добавляются к уже имеющейся сумме в массиве Sum, а если такого там нет, новичок вносится в список участников со своими текущими баллами, а количество участников увеличивается на 1.

В теле основной программы выполняются следующие действия: в цикле находятся файлы вида konkurs. 1, konkurs. 2, konkurs. 3 и т.д., из каждого файла по две строки считывается информация об участнике (первая строка — имя участника, вторая — его балл за этот конкурс), и выполняется процедура ScanPeople. Таким образом обрабатываются все участники всех конкурсов.

Далее производится сортировка, и вывод результатов в файл !rating.txt.

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

Автор не является программистом и даже не претендует на это звание. Однако работа собственноручно написанной программы дает ощущение, которое несравнимо ни с чем. Ведь компьютер выполняет именно то, что вам нужно, при этом именно вы объяснили, что именно нужно. И если читатели, которые считают, что писать программы — это очень сложно и наверняка не для них, попробуют встать на такой путь общения с компьютером, я буду считать свою задачей выполненной. Удачи вам на этом пути!

Рекомендуем ещё прочитать:






Данную страницу никто не комментировал. Вы можете стать первым.

Ваше имя:
Ваша почта:

RSS
Комментарий:
Введите символы или вычислите пример: *
captcha
Обновить





Хостинг на серверах в Украине, США и Германии. © sector.biz.ua 2006-2015 design by Vadim Popov