Сегодня, 3 августа 2024 года, был последний день подачи документов в вузы России на бюджет.
Ситуация нервная: слишком много факторов.
Предварительно подать заявления можно в 5 вузов.
В каждом вузе — заявления на 5 направлений.
Направления в пределах вуза нужно ранжировать по приоритетам.
Документы нужно отнести только в один вуз.
Вузы публикуют так называемые конкурсные списки. Это списки заявлений по направлениям. Для каждого направления — кто подал, сколько баллов, какой приоритет этого конкретного направления у этого конкретного заявителя.
Просто смотреть в конкурсные списки полезно, если вы гарантированно проходите на первое из выбранных направлений. Это посчитать легко.
Всё остальное — туман.
Яжемать!
А ребёнок, между прочим, на информатику во всех видах поступать категорически отказывается. Остаются какие-то совершенно неведомые специальности — строительство, что это вообще?
Психовать было очень утомительно. Допсиховалась до того, что написала несколько скриптов, предсказывающих поступление.
Что происходит в этих скриптах.
Заявления упорядочиваются по убыванию баллов, а для одного человека — по убыванию приоритета.
Таким образом мы получаем очередь, основное свойство которой: в каждый момент времени первое заявление в очереди имеет максимальный приоритет для рассмотрения. Потому что в этом заявлении больше всех баллов и у него (если следующее заявление от того же человека с теми же баллами) самый высокий приоритет.
Очередь можно рассматривать постепенно, выбрасывая каждый элемент навсегда. Возвращаться к заявлениям не нужно: отработали — выбросили.
Как только мы удовлетворили заявление конкретного человека, все остальные его заявления становятся неактуальными. В очереди пусть болтаются, просто когда до них дойдёт дело — выбросим.
Заявление можно удовлетворить, если в нём указано направление, в котором на момент рассмотрения есть свободные места.
Как только мы удовлетворили заявление, абитуриент оказывается окончательно приписан к направлению. Поступил, всё.
И в этот же момент у направления уменьшается количество оставшихся свободных мест.
Если заявление указывает на направление, на которое нет мест, мы его выбрасываем. Если у человека есть ещё заявления в общей очереди (а они точно на другие направления) — у них ещё, возможно, есть шанс. Дойдёт дело — рассмотрим и их.
Будут люди, до которых дойдёт очередь только тогда, когда все места на всех направлениях будут заняты. Они не поступили.
Основной C-скрипт короче, чем описание его поведения.
Этот код на языке C (а не C++, как думает Хабр) не про эстетику, он просто сработал и дал ответ
#include <stdio.h>
#include <mysql/mysql.h>
#include <string.h>
#define HOST "localhost"
#define USER "root"
#define PSWD ""
#define DBASE "spiski"
int main() {
MYSQL *mysql = mysql_init(NULL);
mysql_real_connect(mysql,
HOST, USER, PSWD, DBASE,
3306, NULL, 0);
// Очистить результаты предыдущих попыток распределения по направлениям
mysql_query(mysql, "UPDATE departments SET counter=0");
mysql_query(mysql, "UPDATE candidates SET department=NULL");
// Получить список всех заявлений
mysql_query(mysql, "SELECT * FROM inbox ORDER BY points DESC, id ASC, priority ASC");
MYSQL_RES * inbox = mysql_store_result(mysql);
// Обработать список заявлений
MYSQL_ROW application;
while ((application = mysql_fetch_row(inbox))) {
// Получить запись о кандидате в таблице кандидатов
char select_candidate[200] = {0};
strcat(select_candidate, "SELECT * FROM candidates WHERE id='");
strcat(select_candidate, application[0]); // id
strcat(select_candidate, "'");
mysql_query(mysql, select_candidate);
MYSQL_RES *candidate_search_result = mysql_store_result(mysql);
MYSQL_ROW candidate = mysql_fetch_row(candidate_search_result);
if (candidate[1] == NULL) { // ещё не распределён
// Получить информацию о направлении, указанном в заявлении
char select_department[200] = {0};
strcat(select_department, "SELECT * from departments WHERE id='");
strcat(select_department, application[3]);
strcat(select_department, "'");
mysql_query(mysql, select_department);
MYSQL_RES *department_search_result = mysql_store_result(mysql);
MYSQL_ROW department = mysql_fetch_row(department_search_result);
// Если есть места — зачислить кандидата на направление
int department_budget;
sscanf(department[2], "%d", &department_budget);
int department_counter;
sscanf(department[4], "%d", &department_counter);
if (department_budget > department_counter) {
// Увеличиваем счётчик зачисленных на направление (можно обойтись сложным SQL-запросом)
char increase_counter[200] = {0};
strcat(increase_counter, "UPDATE departments SET counter = counter + 1 WHERE id='");
strcat(increase_counter, application[3]);
strcat(increase_counter, "'");
mysql_query(mysql, increase_counter);
// Записываем кандидата на направление
char set_department[200] = {0};
strcat(set_department, "UPDATE candidates SET department='");
strcat(set_department, application[3]);
strcat(set_department, "', points='");
strcat(set_department, application[1]);
strcat(set_department, "', priority='");
strcat(set_department, application[2]);
strcat(set_department, "' WHERE id='");
strcat(set_department, application[0]);
strcat(set_department, "'");
mysql_query(mysql, set_department);
}
mysql_free_result(department_search_result);
}
mysql_free_result(candidate_search_result);
}
// Освобождаем ресурсы
mysql_free_result(inbox);
mysql_close(mysql);
}
Всё работает. Ответ «поступило ли дитё» получен (ну так, средней радости, но всё-таки не мимо с песнями).
Технические нюансы
Это скрипты, а не программа. Никаких проверок и обработки исключений, никакого изящества в коде, никакого интерфейса. Просто запускаешь — и получаешь результат.
Где взять данные по вузу? Скопипастить с сайта вуза. У всех разные форматы, Selenium помог слабо — а копипаст и Google Sheets сильно. Оказалось, что не так всё и страшно (в МГУ ребёнок не поступал, а на вузы поменьше ручная работа посильна).
Linux Mint + MySQL + gcc. Просто что под рукой было. Извините, Windows у меня просто-напросто нет.
Язык C — тоже из серии «что под рукой было». Наверное, на Python было бы проще, но книжка про Python лежала на полке повыше — лень тянуться.
Возможны мелкие погрешности, связанные с кодировками. Разбираться пока не стала, потому что этот нюанс всплыл уже после получения от системы основных ответов.
Можно вкуривать на Github. И ещё разок: суть в поиске ответа, а не в качестве кода.
В этом году система уже никому не пригодится, но — будут и ещё годы. У желающих есть время допилить. Что непонятно — расскажу, дёргайте.
Комментарии (45)
NeoCode
03.08.2024 18:48А ребёнок, между прочим, на информатику во всех видах поступать категорически отказывается.
Необычно:) (хотя разумеется это мое предвзятое мнение, а в реальности у людей бывают очень разные интересы)
ChessMax
03.08.2024 18:48Ну главное, чтобы ребенку нравилось. Смысл идти, если не твое? Ну и если что, вернуться в где можно же?
piuzziconezz
03.08.2024 18:48+1Вот мой тоже поступил на физику в МИСИС. Хочет физику и все тут. Что потом с ней делать пока не ясно.
propulsive
03.08.2024 18:48+1olgapavlova Автор
03.08.2024 18:48+2Огонь!
Интересно, что и в том проекте узкое место — парсинг данных. Ну, тема открытых данных у государства нынче не в моде, так что на удобные форматы выгрузки пока не надеемся.
nicknov_17
03.08.2024 18:48>> А ребёнок, между прочим, на информатику во всех видах поступать категорически отказывается.
Все из-за того, что поступил в ВУЗ на спец. номер 123456 , вот по ней и учись все 4-5-6 лет.
Интересно, сейчас в ВУЗах реально перевестись на другую специальность во время учебы? Когда учился в 90-е годы постоянно что-то появлялось новое из направлений подготовки (типа сертификация, приборно-информационная медицина...) и переводились даже из машиностроительных спецух на информационные, досдав предметы которых не было (зачастую чисто формально сходить к преподу и получить зачет, экзамен)
olgapavlova Автор
03.08.2024 18:48+1Сейчас на сайтах некоторых вузов я видела отдельной строчкой в списке преимуществ что-то вроде «Возможность перевода между направлениями».
У нас в большом универе (Питер) сейчас точно работает перевод с физфака на матмех. В 90-е были люди, переходившие из ИТМО на матмех.
Насчёт того, на тот же курс или нет, я не знаю. Вроде там есть понятие академической разницы, и для перевода она должна быть в пределах некоторых норм.
Ну и конечно, многие просто перепоступают в другой вуз. С программиста на художника, с физика на лингвиста и даже с одного дизайнера на другого — запросто!
piuzziconezz
03.08.2024 18:48Все возможно при условии что есть вакантные бюджетные места.
olgapavlova Автор
03.08.2024 18:48Дикое количество народу не доживает до третьего курса. Так что места часто образуются.
ntimalyov
03.08.2024 18:48Перевестись сейчас можно при определённых условиях.
Должны быть места, это очевидно.
Разница в программах не должна превышать N предметов (на практике можно даже если много, но сильно труднее, зависит от деканата. У нас в Питерском вузе переводились с 3-4 предметами досдачи, один уникум перевёлся в ИТМО с 6 или 7 предметами)
Могут быть переводы с потерей года (могут не отчислить, а предложить перевестись на прошлый курс или даже на другой факультет, если с 1го курса отлетаешь)
Если хочется перевестись с бакалавра на специалитет - разница должна быть год, а не полтора, иначе потеря отсрочки (у нас в вузе бакалавриат 4 года, специалитет - 5,5, из-за этого не смог перевестись)
slonopotamus
03.08.2024 18:48+1суть в поиске ответа, а не в качестве кода
Я всё понимаю, но нахрена sudo-то???
olgapavlova Автор
03.08.2024 18:48Отличный вопрос!
Права на папку /var/lib/mysql-files/ и её содержимое устроены затейливо: как только ты их меняешь — MySQL замечает недоброе и отказывается грузить файлы из этой папки (а из других даже и не думает). Приходится не только sudo, но и chown делать.
Альтернатива есть: нужно правильно настроить MySQL-переменные secure_file_priv и local_infile. Тогда, как я понимаю, файлы можно грузить откуда угодно, в том числе (при правильных local_infile во всех местах) с клиентской машины. Но у меня за полчаса не получилось, и я решила, что больше тратить время на это не хочу. В реальных условиях, конечно, нужно дожимать до победного.jackcrane
03.08.2024 18:48+1Права на папку /var/lib/mysql-files/ и её содержимое устроены затейливо
1) права устроены разумно. необходимо просто добавить нужного юзера в нужную группу.
2) если делать коненкт через локальный или сетевой сокет, то не нужно даже и этого.
строительство, что это вообще?
A) строительство (а не это ваше ИТ) назначено локомотивом внутреннего спроса в экономике РФ, примерно с 2008 года (или когда пошла массовая ипотека), примерно до сейчас. дальнейших прогнозов дать не могу.
B) в строительстве (а не в этом вашем ИТ) до сих пор жив фриланс. и будет жить.
C) через строительство и занятых в нем кадров хозяева РФ решают важные социально-конспирологические задачи.
slonopotamus
03.08.2024 18:48+1Окей, но зачем класть sql-файлы именно туда? Чем вас не устроила папка с вашими скриптами или tmp?
mihmig
03.08.2024 18:48Пользуясь случаем спрошу:
Известны ли кому программы для работы с БД на уровне между командной строкой и тяжеловесным Java(привет DBeaver) и, не к ночи будь помянутым Electron.
Что-то типа консольного интерфейса а-ля Turbo Pascal 90-х...
Можно получить скорость работы с удобством.
Пока на ум приходит только Far Manager (far2l - для linux, прекрасно работает) - но у него вроде плагин только для SQLLITE...
Dominux
03.08.2024 18:48+1А о чем статья в итоге? О том, как вы собрали данные в одну таблицу и сделали один простенький селект?
redfox0
03.08.2024 18:48+1О! Процедура приоритетного зачисления на самом деле немного сложнее, чем в статье. По факту это практическое применение "задачи о разборчивой невесте".
У автора статьи не учтены случаи, когда необходимо делать "откат" алгоритма - поступающий проходит на другую специальность, но с текущей специальности его нужно убрать, тем самым появляется незанятое место и нужно пересчитать всех поступающих в конкурсном списке ниже. А ещё у одного поступающего может быть разная сумма баллов для разных конкурсных групп из-за того, что учитываются разные предметы (например, русский+математика+физика и русский+химия+биология). Проблема полупроходников вообще не решаема алгоритмически или сложнорешаема (когда на последнее место претендуют сразу несколько абитуриентов с полностью одинаковой суммой баллов).
tlnr: в статье приведена неплохая попытка оценить собственные шансы на поступление, особенно с учётом того, что так называемый высший приоритет в конкурсных списках вузы рассчитывают кто как понял. Но настоящий алгоритм зачисления может немно-о-ожко отличаться от того, какой используется в конкретном вузе.
olgapavlova Автор
03.08.2024 18:48Разница в сумме баллов как раз учтена. Потому что обрабатываются заявления, а не абитуриенты. Но там осталось одно неявное предположение, что приоритеты человек выставляет в соответствии со своими баллами. Это, вообще говоря, не так, но исправить [будет] несложно.
Вы словом «проходит» назвали ситуацию, когда чел делает свободный выбор и идёт не по первому доступному к реализации приоритету? Да, этого нет, потому что информации об этом тоже нет. Или «проходит» — это про что-то другое?
Проблема нескольких абитуриентов не решаема полностью, но достаточно обозначить в выходных данных «серую зону». Тоже не сделано, потому что мне не было актуально.
В целом да, вы правы, это скорее помогалка при оценке вероятностей, чем поиск точного ответа. На фоне треша с конкурсными списками — очень помогает сориентироваться.
Было бы интересно узнать, как на самом деле устроены схемы приёма в разных вузах. Если, например, за кадром остаётся система, когда высокобалльникам дают ещё один шанс втихаря под подушкой пересмотреть список своих приоритетов — жди беды :) Или, например, алгорифм может быть радикально другой: «сначала заполняем места первоприоритетниками, потом смотрим дальше» — справедливости в этом ноль, но такое возможно.
На такую разведку нужно время и силы. Возможно, времени достаточно, и в течение следующего года кто-то оставит комментарий по существу, который поможет кому-то ещё улучшить понимание алгорифмов и сделать новую версию реализации.redfox0
03.08.2024 18:48«Проходит [по конкурсу]», то есть место в конкурсной группе ещё осталось, все поступающие с более высокими баллами уже зачислены, и набранной суммы баллов достаточно для зачисления. Проходить по конкурсу можно не обязательно по первому приоритету, тогда делается попытка зачислить поступающего на второй приоритет, третий и т. д.
У меня есть надежда, что зачисление в вузах происходит по одному алгоритму (регламентировано Порядком Приёма). Но зачисление и так сложная штука, проходит в несколько этапов, сначала приоритетный этап зачисления на квоты (20-30%, в медицинских вузах - до 100% целевых мест). Эти сроки уже прошли. Потом зачисление на общий конкурс (что вы и показываете в статье). Но наряду с общим конкурсом ещё идут всякие олимпиадники/без экзаменов, они тоже откусывают часть мест кпц.
olgapavlova Автор
03.08.2024 18:48Ага, эта логика как раз и реализована. Иначе зачем всё.
Олимпиадники идут в волне приоритетного зачисления (это я по старшему знаю 100%). А тут да, только уже общий конкурс.
Настройки «сколько куда в реальности осталось мест» вынесены в отдельную таблицу, без неё бы тоже смысла в скрипте было мало. Обычно вузы стараются поддерживать эти данные в актуальном состоянии, хотя я заметила несколько странностей. Но в целом стараются.
olgapavlova Автор
03.08.2024 18:48О, а расскажете, какой именно простенький селект решает задачу? Мне интересно! Возможно, не только мне.
Статья о том, что простенькие программы писать не зазорно, а использовать полезно. Буду рада, если в следующем году это сделает на актуальных данных какой-нибудь бодрый школьник, а не подуставшая от мира за окном мать семейства :)Dominux
03.08.2024 18:48+1Во первых, не очень понял, зачем нужно писать программу на С, если все можно составить на чистом SQL?
olgapavlova Автор
03.08.2024 18:48Даже на чистом Google Sheets можно её составить. Оптимизация технологического стека в мои планы не входила и вряд ли уже войдёт.
Dominux
03.08.2024 18:48Статья о том, что простенькие программы писать не зазорно, а использовать полезно. Буду рада, если в следующем году это сделает на актуальных данных какой-нибудь бодрый школьник
Я вас правильно понимаю, что проще выучить С и SQL, чем немного дооптимизировать 1 SQL-запрос? Особенно, какому-нибудь "бодрому школьнику". Две технологии вместо одной?
olgapavlova Автор
03.08.2024 18:48Не совсем. Основная часть статьи всё-таки о том, что делать по сути. А на каких технологиях, абсолютно всё равно. Например, подозреваю, что большинство бодрых школьников предпочтёт Python, продвинутые — C++.
Также подозреваю, что вместо SQL они будут использовать непосредственно CSV-файлы, потому что жизнь школьников редко их готовит к работе с базами данных (хотя нас в своё время готовила, но вряд ли всем так повезло).
Что до одного простого SQL-запроса — каким должен быть этот запрос? Мне вот в голову ничего именно простого (а не монструозного с использованием всяких там вложенностей и группировок) не приходит. Поделитесь? Наверняка пригодится не только мне.
Dominux
03.08.2024 18:48бодрых школьников предпочтёт Python, продвинутые — C++
Уверен, тут все зависит от того, чему их учили в школе. Сам в школе не изучал ни одного языка, так что не знаю, могу лишь предполагать, что вряд ли школьники выбирают язык индивидуально, т.к. не знают, что лучше, да и тогда пришлось бы делить их на группы по выбранному языку и учить по отдельности.
Что до самого языка, в целом, формирование SQL-запроса путем форматирования строк - задача простейшая, знание основ любого из C/C++/Java/Python не будет слишком различным по сложности, все же мы говорим об азах.
монструозного с использованием всяких там вложенностей и группировок
Проще вложенных запросов, группировок и джоинов - только базовый селект, ну максимум с
WHERE
-clause. Ну думаю, что это стоит называть монструозным.Я уже не говорю о том, что вы банально приучаете делать 20 запросов вместо того, чтобы сделать все в рамках одного, без необходимости производить некоторые CPU-действия на стороне ЯПа, где вам ещё повезет, если это будет язык на уровне языка, на котором написана сама бд, потому что так вы сильно замедлите скорость выполнения, и без необходимости гонять данные туда-сюда, создавая нагрузку на сеть, которая сожрёт 99% всего времени ожидания программы, и не важно, как бы ученик написал обратку - на питоне или с супер-топовым алгоритмом на C с наилучшей асимптотической сложностью. Дело же в том, что ребята просто прочтут и будут повторять за вами, понимаете?
olgapavlova Автор
03.08.2024 18:48Насчёт количества запросов вы абсолютно правы, в серьёзных задачах так делать, мягко говоря, не стоит.
Ребята! Не надо повторять за мной и вообще ни за кем. Своей головой надо думать.
u007
03.08.2024 18:48>...имею право
С 2012 года мы сделали 385 дизайн-проектов. Умеем. Нравится. Продолжаем.
JohnDoe_71Rus
на скриншоте они в распространяемых данных светят СНИЛС абитуриентов? и много таких "одаренных" вузов у вас в статистике?
sixxio
Это общепринято: несколько лет назад правила поменялись и в конкурсных списках используют СНИЛС в качестве ID вместо ФИО, как это было ранее.
Efrem3112
Практически все. СНИЛС как основной идентификатор идёт.
olgapavlova Автор
Иногда используют номер анкеты или какой-то аналог. Но это редкость. Проверила: у меня в рабочей базе 2998 заявлений идут по СНИЛС и только 81 — по номеру анкеты.
redfox0
Потому что вузы прогнули и заставили или собирать СНИЛС (есть почти у всех граждан РФ), и вуз набивает данные поступающего в ССПВО руками (api не даёт загрузить гражданина РФ без СНИЛС).
JohnDoe_71Rus
СНИЛС понятно, надо как то учитывать абитуриента в разных вузах. Вузы сливают данные в общую базу. На ГосУслугах подавать электронно. Но вот светить его моветон. Номер анкеты/личного дела известный абитуриенту.
redfox0
Года два назад и ранее выкладывались прям полные ФИО поступающих и выкладывались в публичный доступ приказы с ФИО поступивших. И всем было норм.
ntimalyov
Была проблема (пусть и не очень распространённая), когда абитуриенты/их мамы находили человека в списке выше и писали ему в соц сетях, мол, "забери документы, у тебя баллов много"
Поэтому в 2021 (когда я поступал) всё заменили на голые снилсы, без фио. Так что по сути (если я правильно понимаю) никакой инфы из них без фио не достать
redfox0
В 2022 году вузы могли из ССПВО по голому СНИЛС достать довольно много инфы о совершенно любом поступающем: фио, дату рождения, пол, телефон, email, адрес регистрации/фактического места жительства, номере и серии всех паспортов (которые вбиты в ЕПГУ), номера документов образовании. С другой стороны это работало очень нестабильно и с большими задержками, чтобы на это всерьёз полагаться. Но недобросовестные вузы могли бы спарсить списки СНИЛС других вузов и начать обзванивать/писать письма или прийти домой к поступающему.