Контрольная работа. Timus 2002

2002. Тестовое задание

 

Условие

Это было обычное хмурое октябрьское утро. Небо было затянуто тяжёлыми серыми тучами, накрапывал дождь. Капли падали на стёкла автомобилей, били в окна домов. Илья сидел за компьютером и угрюмо взирал на унылый пейзаж за окном. Внезапно его взгляд привлекла надпись, появившаяся в правом нижнем углу экрана: «You have 1 unread email message(s)». Заранее приготовившись удалить бесполезный спам, Илья открыл письмо. Однако оно оказалось куда интереснее…
Вас приветствует отдел по работе с персоналом компании «Рутнок БКС»!
Мы рассмотрели вашу заявку на вакансию разработчика программного обеспечения и были заинтересованы вашей кандидатурой. Для оценки ваших профессиональных навыков мы предлагаем вам выполнить несложное тестовое задание: необходимо реализовать систему регистрации для форума. Она должна поддерживать три операции:

  • «register username password» — зарегистрировать нового пользователя с именем «username» и установить для него пароль «password». Если такой пользователь уже есть в базе данных, необходимо выдать ошибку «fail: user already exists». Иначе нужно вывести сообщение «success: new user added».
  • «login username password» — войти в систему от имени пользователя «username» с паролем «password». Если такого пользователя не существует в базе данных, необходимо выдать «fail: no such user». Иначе, если был введен неправильный пароль, нужно выдать «fail: incorrect password». Иначе, если пользователь уже находится в системе в данный момент, необходимо вывести «fail: already logged in». Иначе нужно вывести сообщение «success: user logged in».
  • «logout username» — выйти из системы пользователем «username». Если такого пользователя не существует, необходимо вывести «fail: no such user». Иначе, если пользователь не находится в системе в данный момент, следует выдать «fail: already logged out». Иначе необходимо выдать сообщение «success: user logged out».

Пользуйтесь этим письмом как формальным описанием алгоритма и строго соблюдайте порядок обработки ошибок. Желаем вам удачи!

И вот Илья, откинув все дела, уже решает тестовое задание. Попробуйте и вы выполнить его!

 

Исходные данные

В первой строке дано целое число [latex]n[/latex] — количество операций [latex]\left( 1 \leq n \leq 100 \right)[/latex]. В каждой из следующих [latex]n[/latex] строк содержится один запрос в соответствии с форматом, описанным выше. В качестве «username» и «password» могут выступать любые непустые строки длиной до [latex]30[/latex] символов включительно. Строки могут состоять только из символов с кодами от [latex]33[/latex] до [latex]126[/latex].

 

Результат

Для каждой операции выведите в отдельной строке сообщение в соответствии с форматом, описанным выше. Строго соблюдайте расстановку пробелов и знаков препинания в этих сообщениях.

 

Ограничения

  • Время: 0.5 секунды
  • Память: 64 МБ

 

Код

 

Решение

Сначала мной была создана структура в которой содержалась информация о пользователе (пароль и состояние: в сети/не в сети) и класс, в котором перечислил все комментарии, которые может выдавать программа. Далее я использовал HashMap для хранения пар вида [latex]\left\{ login => \left(password , status \right)\right\}[/latex], что позволило мне за константное время проверять указанные в задаче условия. Существование пользователя (был ли он зарегистрирован ранее) я определяю с помощью метода HashMap.containsKey(T key), что позволяет мне не заводить дополнительные структуры данных.

 

Описание функций

 

main

Главная функция программы. Считывает число запросов [latex]n[/latex], и [latex]n[/latex] раз считывает массив строк с помощью getRequest и и сразу же передает его в функцию Query, после чего программа завершает свою работу.

 

getRequest

Считывает строку и разбивает ее с помощью метода split по пробелу. Возвращает полученный массив.

 

Query

Функция — распределитель. Принимает массив строк и проверяет его первый элемент.
Если он оказался равен «register» — вызывает функцию Registration. Параметрами служат второй и третий элемент входного массива.
Если он оказался равен «login» — вызывает функцию Login. Параметрами служат второй и третий элемент входного массива.
Если он оказался равен «logout» — вызывает функцию Logout. Параметром служит второй элемент входного массива.

 

Request

Принимает две строки, которые определяет как логин и пароль пользователя. Проверяет несуществование пользователя. Если пользователь с таким логином не существует — добавляет запись в DataBase и печатает строку «success: new user added». Иначе — печатает соответствующую ошибку.

 

Login

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

 

Logout

Принимает одну строку, которую определяет как логин. Проверяет существование пользователя и его статус. Если пользователь существует и статус — «в сети» — меняет статус и печатает об успехе. Иначе печатает соответствующую ошибку.

Результат проверки на acm.timus.ru

Вердикт Время работы Использованная Память
Accepted 0.078 548 КБ

Двоичное дерево поиска

Задача

Реализовать структуру «Двоичное дерево поиска» в соответствии с этим шаблоном.

Решение

По моему субъективному мнению, тут следует привести более ли менее детальное описание только операций вставки и удаления вершины.

Операция вставки

Пусть у нас есть вершина с ключом [latex]key[/latex] и дерево [latex]T[/latex], в которое нам нужно вставить нашу вершину. Сразу у нас есть ссылка только на корень дерева, поэтому посмотрим на значение ключа в корне дерева. Если оно вдруг совпало с нашим [latex]key[/latex], то, в этой реализации, мы заменяем поля этой вершины на новые. Если оно не совпало, то так как нам нужно найти незанятое место, куда бы мы могли вставить нашу вершину, мы проверяем: если значение нашего [latex]key[/latex] больше значения в корне — правое поддерево [latex]T[/latex], иначе — левое. Можно заметить, что ситуация изменилась только значением ключа в корне, поэтому можно применить наши прошлые действия. Так мы будем делать, пока наш выбор не остановится на пустом поддереве, то есть — пока не найдется места для нашей вершины. Теперь, когда мы нашли приют нашей вершине, мы вставляем ее на это место.

Операция удаления

Для того, чтобы удалить вершину, нам, очевидно, нужно ее сначала найти, при этом, у нас есть только ключ этой вершины. И да, мы будем не одни, с нами пойдет указатель на предыдущую вершину в дереве. Искать мы будем способом, описанным в предыдущем пункте. Если значение нашего ключа и ключа в корне совпало — мы нашли обреченную вершину, если же мы попали в пустое поддерево — можно считать, что наша работа выполнена (нет вершины — нет проблемы). Однако рассмотрим первый случай.
Пусть правое (левое) поддерево пусто. Тогда удалить вершину просто — мы заменяем адрес удаляемой вершины у предыдущей вершины (там ведь стоит указатель) на адрес левого (правого) поддерева удаляемой вершины.
Если же правое поддерево не пусто, мы уже не можем просто удалить вершину. Чтобы сохранить основное свойство дерева мы должны найти замену. В правом поддереве мы найдем вершину с наименьшим ключом и поменяем с удаляемой вершиной (если есть еще какие-то поля — их тоже заменяем). Задача свелась к первому случаю.

Код

Java Collections Framework: Map. Частотный словарь.

Задача 1:

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

Задача 2:

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

Ссылка на Ideone