Последнее время Яндекс стал часто мне присылать письма о том как индексируется мой блог optozorax.github.io, и он оказывается по каким-то запросам даже есть в поиске, и на него раз в сто лет даже кто-то кликает! Это оказалось достаточно мотивирующим, чтобы я решился добавить на свой блог весь крутой контент, что лежит у меня на github.
Я сделал так, чтобы при помощи чёрной магии и git submodules в моём блоге публиковались посты, в которых находится содержимое файлов README.md из репозиториев, которые я указал.
Мой блог построен на Jekyll - дефолтном генераторе статических сайтов на GitHub Pages, поэтому я хакал именно его.
В итоге я смог этого добиться, но парой костылей. Я написал об этом пост в блоге: https://optozorax.github.io/submodules-jekyll
Кстати, там добавилось много статей, которые вам могут быть интересны, но вы их раньше никогда не видели, их можно посмотреть на главной странице: optozorax.github.io.
Я сделал так, чтобы при помощи чёрной магии и git submodules в моём блоге публиковались посты, в которых находится содержимое файлов README.md из репозиториев, которые я указал.
Мой блог построен на Jekyll - дефолтном генераторе статических сайтов на GitHub Pages, поэтому я хакал именно его.
В итоге я смог этого добиться, но парой костылей. Я написал об этом пост в блоге: https://optozorax.github.io/submodules-jekyll
Кстати, там добавилось много статей, которые вам могут быть интересны, но вы их раньше никогда не видели, их можно посмотреть на главной странице: optozorax.github.io.
optozorax.github.io
Один репозиторий = Один пост в блоге — Блог optozorax'а
Делаем такое возможным с помощью `git submodules` на Jekyll + GitHub Pages.
#мысли #вода_дарует_мысли
В Rust'е обработка ошибок хороша тем, что ты видишь в сигнатуре функции что возвращается
Но вот чтобы отслеживать какой метод паникует, необходимо читать доку. Например, метод
И это натолкнуло меня на мысль, что язык программирования будущего, который должен заменить Rust, должен уметь следующую вещь: возможность помечать методы или фунции какой-то меткой, которая будет заражать всё что будет это использовать.
Поясняю: вот есть в Rust паникующие методы/функции. Хотелось бы их помечать их меткой аля
Следующей такой меткой может быть
Ещё можно ввести метку
Отличие этих всех меток от
Что дадут все эти метки? Ну во-первых, код с метками
Например, если переписывать ядро Линукса на расте, то там определённо никто не хочет чтобы метод паниковал (наверное).
Я понимаю, что с точки зрения синтаксиса это будет очень запарно писать. Но такова цена. Типизацию тоже надо везде прописывать)
Может быть это можно будет использовать в библиотеках, вводя свои метки, упрощающие понимание/написание кода.
В Rust'е обработка ошибок хороша тем, что ты видишь в сигнатуре функции что возвращается
Option<_>, Result<_, _>. За это его все любят, и за это же не любят концепцию исключений в языках типо C++. В расте ещё есть механизм под названием "паника" - это когда вся программа падает. Перехватывать панику - крайне плохой тон, потому что считается что это ошибка программирования, поэтому это никто не делает. Все перехватывают ошибки через Option/Result Поэтому все стараются писать код так, чтобы он не паниковал.Но вот чтобы отслеживать какой метод паникует, необходимо читать доку. Например, метод
remove на контейнере паникует, если данный элемент не найдётся. Кстати метода try_remove нету, и не очень хотят подобное что-то добавлять (подробности).И это натолкнуло меня на мысль, что язык программирования будущего, который должен заменить Rust, должен уметь следующую вещь: возможность помечать методы или фунции какой-то меткой, которая будет заражать всё что будет это использовать.
Поясняю: вот есть в Rust паникующие методы/функции. Хотелось бы их помечать их меткой аля
panicking, и далее, если ты в своей функции используешь panicking функцию, то и свою функцию ты обязан пометить так же.Следующей такой меткой может быть
allocating. Аналогично, если ты используешь что-то, что аллоцирует память, то ты помечаешь такой штукой свою функцию.Ещё можно ввести метку
nopure, которая ставится если ты модифицируешь какое-то глобальное состояние. Например, вызываешь print!().Отличие этих всех меток от
unsafe в расте в том, что unsafe можно отключить у метода. А эти метки должно быть нельзя отключить. Ну или можно отключить, но через unsafe {}.Что дадут все эти метки? Ну во-первых, код с метками
panicking, allocating, nopure будет считаться либо плохим, либо неподходящим для использования в библиотеках, и все будут стараться делать библиотеки с не-паникующими не-аллоцирующими чистыми методами. Это будет означать что такие методы вероятно очень быстрые и что они очень надёжные.Например, если переписывать ядро Линукса на расте, то там определённо никто не хочет чтобы метод паниковал (наверное).
Я понимаю, что с точки зрения синтаксиса это будет очень запарно писать. Но такова цена. Типизацию тоже надо везде прописывать)
Может быть это можно будет использовать в библиотеках, вводя свои метки, упрощающие понимание/написание кода.
Хочу трейт коллекции (а для него надо Generic Associated Types 😭), чтобы можно было в стандартную библиотеку добавить:
Чтобы я мог собирать итератор из пар в:
Без трейта коллекции можно написать что-то такое:
Но мне кажется такое невозможно написать, либо оно будет слишком
impl<K, V, C: Collection<V>> FromIterator<(K, V)> for BTreeMap<K, C>
Чтобы я мог собирать итератор из пар в:
.collect::<BTreeMap<_, Vec<_>>>()
Без трейта коллекции можно написать что-то такое:
impl<K, V, C: FromIterator<V>> FromIterator<(K, V)> for BTreeMap<K, C>
Но мне кажется такое невозможно написать, либо оно будет слишком
unsafe, либо будет оверюзать умные указатели типо RefCell.Отказ от телеги.
Я заметил, что трачу на телеграм очень много времени. Я читаю кучу чатов, отвечаю, и даже с кем-то спорю (в интернете кто-то неправ!). Это вылилось в то, что когда я планировал в какой-то день что-то делать, я просто не мог это делать, потому что всё свободное время я уже потратил на телеграм. Особенно всё это ухудшилось, когда появились комментарии к каналам. Тогда я решил поступить радикально, как радикально я поступал раньше со всем - удалить телеграм (ну, на время).
Подобное я практиковал ещё давно. Пожалуй мой самый радикальный, и самый первый опыт подобного случился в 11 классе. Перед 11 классом я напрокрастинировал всё лето, хотя на это лето у меня были планы по написанию одного проекта. Я понял, что всё своё время я трачу куда-то в интернет, не только в один вконтакт или ютуб. Поэтому на сентябрь 11 класса я принял радикальное решение - отказаться от интернета на месяц. Это было тяжело. Мне пришлось скачать кучу документации на комп заранее. Скачать музыку заранее. По вечерам я ощущал вакуум. Но уже в первые дни я заметил, что оказывается за 2 часа свободного времени можно сделать очень много, и мне это понравилось. После того опыта я не стал снова отрубать интернет на месяц, а уже пользовался интернетом далее, но благодаря таким радикальным действиям я смог научить себя тратить на него меньше времени.
Затем уже в университете я заметил, что очень много времени смотрю ютуб. Поэтому я внёс ютуб в файл hosts, и по сути заблокировал его на компьютере, и разрешал себе смотреть его только через телефон. А через телефон мне дико неудобно смотреть, поэтому получилось хорошо. Таким макаром я держал ютуб заблокированным на компьютере около 2 лет, и уже после возвращения ютуба на компьютер, я не трачу на него столько времени.
Тоже самое было с вконтакте, но там всё обошлось тем что я отписался от всех групп и в приложении Kate Mobile настроил так, чтобы при включении приложения открывалась страница с сообщениями, а не новостями, и вообще кнопки "новости" не было.
Сейчас с телеграмом у меня проблема, что я чёртов перфекционист на эти непрочитанные сообщения, и я не могу держать кучу чатов непрочитанными. Поэтому я и вышел из чатов по расту, потому что поток сообщений там был колоссальным.
С телеграмом я начал с малого - удалил телегу на три дня. И эти три дня было сложно, снова было ощущение информационного вакуума. Но в итоге в первый же день отказа от телеги я на работе очень хорошо и быстро выполнил свои задания, и после работы ещё смог сделать что запланировал. Так было и с последующими днями.
Удаление на три дня показало себя хорошо, и поэтому следующим шагом я удалил телеграм на неделю, с запланированным возвращением в субботу. И вот сейчас уже стукнуло 2 недели как я это делаю.
После двух недель, я не знаю что и сказать. Это круто. Для меня уже стало естественно, что у меня оказывается есть так много времени, и что я больше успеваю, и больше делаю. Я перестал отвлекаться, и каждые 10-30 минут чекать что там в каких чатах написали. Соответственно повысилась концентрация.
⬇️
Я заметил, что трачу на телеграм очень много времени. Я читаю кучу чатов, отвечаю, и даже с кем-то спорю (в интернете кто-то неправ!). Это вылилось в то, что когда я планировал в какой-то день что-то делать, я просто не мог это делать, потому что всё свободное время я уже потратил на телеграм. Особенно всё это ухудшилось, когда появились комментарии к каналам. Тогда я решил поступить радикально, как радикально я поступал раньше со всем - удалить телеграм (ну, на время).
Подобное я практиковал ещё давно. Пожалуй мой самый радикальный, и самый первый опыт подобного случился в 11 классе. Перед 11 классом я напрокрастинировал всё лето, хотя на это лето у меня были планы по написанию одного проекта. Я понял, что всё своё время я трачу куда-то в интернет, не только в один вконтакт или ютуб. Поэтому на сентябрь 11 класса я принял радикальное решение - отказаться от интернета на месяц. Это было тяжело. Мне пришлось скачать кучу документации на комп заранее. Скачать музыку заранее. По вечерам я ощущал вакуум. Но уже в первые дни я заметил, что оказывается за 2 часа свободного времени можно сделать очень много, и мне это понравилось. После того опыта я не стал снова отрубать интернет на месяц, а уже пользовался интернетом далее, но благодаря таким радикальным действиям я смог научить себя тратить на него меньше времени.
Затем уже в университете я заметил, что очень много времени смотрю ютуб. Поэтому я внёс ютуб в файл hosts, и по сути заблокировал его на компьютере, и разрешал себе смотреть его только через телефон. А через телефон мне дико неудобно смотреть, поэтому получилось хорошо. Таким макаром я держал ютуб заблокированным на компьютере около 2 лет, и уже после возвращения ютуба на компьютер, я не трачу на него столько времени.
Тоже самое было с вконтакте, но там всё обошлось тем что я отписался от всех групп и в приложении Kate Mobile настроил так, чтобы при включении приложения открывалась страница с сообщениями, а не новостями, и вообще кнопки "новости" не было.
Сейчас с телеграмом у меня проблема, что я чёртов перфекционист на эти непрочитанные сообщения, и я не могу держать кучу чатов непрочитанными. Поэтому я и вышел из чатов по расту, потому что поток сообщений там был колоссальным.
С телеграмом я начал с малого - удалил телегу на три дня. И эти три дня было сложно, снова было ощущение информационного вакуума. Но в итоге в первый же день отказа от телеги я на работе очень хорошо и быстро выполнил свои задания, и после работы ещё смог сделать что запланировал. Так было и с последующими днями.
Удаление на три дня показало себя хорошо, и поэтому следующим шагом я удалил телеграм на неделю, с запланированным возвращением в субботу. И вот сейчас уже стукнуло 2 недели как я это делаю.
После двух недель, я не знаю что и сказать. Это круто. Для меня уже стало естественно, что у меня оказывается есть так много времени, и что я больше успеваю, и больше делаю. Я перестал отвлекаться, и каждые 10-30 минут чекать что там в каких чатах написали. Соответственно повысилась концентрация.
⬇️
Немного иронично, что в этот период отказа от телеги, Павел Дуров пишет пост: медуза, оригинал; где говорит что злые корпорации хотят чтобы мы потребляли как можно больше.
Но конечно это не проходит бесследно, как точно заметил один человек: пока я учусь обходиться без телеги, люди с кем я общаюсь через неё учатся обходиться без меня... И ведь действительно есть в телеграме некоторые коммьюнити, где я активный участник. Но ради своего времени этим всем приходится жертвовать.
Сейчас я смотрю на это всё, и понимаю что к сожалению я дофаминовый наркоман, и мне придётся так радикально бороться с каждой новой возникающей технологией по захвату внимания.
И видимо поэтому мне не стоит устанавливать тикток.
Кстати, глобально по этой теме рекомендую книгу "Пустышка. Что интернет делает с нашими мозгами.".
Но конечно это не проходит бесследно, как точно заметил один человек: пока я учусь обходиться без телеги, люди с кем я общаюсь через неё учатся обходиться без меня... И ведь действительно есть в телеграме некоторые коммьюнити, где я активный участник. Но ради своего времени этим всем приходится жертвовать.
Сейчас я смотрю на это всё, и понимаю что к сожалению я дофаминовый наркоман, и мне придётся так радикально бороться с каждой новой возникающей технологией по захвату внимания.
И видимо поэтому мне не стоит устанавливать тикток.
Кстати, глобально по этой теме рекомендую книгу "Пустышка. Что интернет делает с нашими мозгами.".
А ещё я смотрел стримы великого гроссмейстера neal_wu, где он за полтора часа решает то, на решение чего у меня уйдёт 7+ часов, и у него есть такая штука, которая позволяет очень быстро прогонять тесты по его задачке на основе
В ней особо ничего интересного нету, разве что когда я её делал, параллельно запилил макрос для работы с библиотекой termcolor, которая позволяет рисовать цвета в консоль кросс-платформенно, для винды и для линукса. Макрос хранится тут: termcolor_macro, и его использование выглядит следующим образом: .
Здесь текст
Во время олимпиадок или решения задач это очень удобно, так что не зря написал.
⬇️
*.in и *.out файлов, которые он создаст. Соответственно я захотел тоже себе такую фигню, но для раста. И сделал такую программку olytest. В ней я храню все тесты в двух файлах: in.txt, out.txt, и разделяю их символом \, чтобы не создавать кучу файлов для каждого теста.В ней особо ничего интересного нету, разве что когда я её делал, параллельно запилил макрос для работы с библиотекой termcolor, которая позволяет рисовать цвета в консоль кросс-платформенно, для винды и для линукса. Макрос хранится тут: termcolor_macro, и его использование выглядит следующим образом: .
clrln!(stdout: b u (Color::Black)[Color::White] "Error:"; " cannot find file {}", filename);Здесь текст
"Error:" выведется жирным (буква b), подчёркнутым (буква u), чёрным цветом (круглые скобки) на белом фоне (квадратные скобки), а после него будет обычный println! без форматирования и цветов, с одним аргументом. Кстати на этом макросе очень хорошо можно увидеть что macro_rules у растишки довольно юзабельный, ибо я такой сложный макрос написал довольно легко.Во время олимпиадок или решения задач это очень удобно, так что не зря написал.
⬇️
Олимпиадное программирование.
В этом году я закончил бакалавриат, и уже работаю около года. И периодически я задумываюсь о том насколько хорошо развиваюсь. И понимаю, что в плане развития работа значительно отличается от учёбы. На работе изучаю меньше нового, ведь там я уже влился в процесс. И это немного непривычное состояние для меня, ведь всю жизнь я только и знал что учиться и решать сложные задачи в школе, учиться в универе, и параллельно делать кучу всяких проектов.
Плюс третий-четвёртый курсы прошли без математики, и от её отсутствия я тоже заметил, что получаю меньше умственного стресса, и меньше челленджей.
В итоге это всё вылилось в то, что мне теперь кажется, что я деградирую и у меня отсыхают мозги. А единственный известный мне способ не деградировать и увлажнять мозги - это обучаться, и лучше обучаться математике, ну или решать олимпиадные задачи (ведь они сложные). Поэтому где-то в глубине головы у меня посеялась эта мысль, что мне надо начать либо математику, либо олимпиадки.
Затем, я делаю свои проекты, о которых пишу в этом канале. Но даже с этими проектами мне кажется что мозги отсыхают, потому что у меня по ним либо не идёт ничего хорошего, либо они не являются каким-то челлендежем, а являются просто рутиной.
Затем я посмотрел сериал "Ход королевы", суть которого я к сожалению не буду рассказывать, ибо не люблю спойлерить, советую просто посмотреть.
Затем ещё у нас в университете проходила олимпиада, на которую я решил не идти, ведь там мне придётся прогать на C++, а я такой вот вредный растоман, и вообще на Раст я решил окончательно уйти из-за олимпиады в Барнауле, где я хотел написать что-то на плюсах, и это было дико неудобно, а на расте ведь есть итераторы. И вот я решил не идти на олимпиаду, а меня туда позвал преподаватель, с которым я хорошо знаком. И стало как-то неловко.
Ну и плюс в это время я отказался от телеги и у меня появилось свободное время.
А ещё какой-то чувак усомнил мою веру в себя, сказав что "мне надо больше читать, чем писать".
И вот все эти вещи наложились друг на друга, и теперь я очень активно занимаюсь олимпиадным программированием на codeforces.com, и поставил на паузу развитие всех своих текущих проектов, и написание всяких статей.
Я начал участвовать в своём первом контесте, и сразу почувствовал себя дико тупым, ведь я не могу найти решение простых задач, или запрограммировать их нормально, качественно и быстро. Но почему-то меня это не остановило и я начал участвовать в каждом рейтинговом соревновании.
А ещё на этом сайте есть раздел EDU, и там можно посмотреть лекции по типичным олимпиадным темам и отправить свои решения упражнений на проверку. Советую хотя бы ознакомиться с тем что такое Z-функция. Для меня это стало открытием и взрывом мозга. Особенно мне понравились задачи на Z-функцию, ведь там я на полную катушку использую Растовские итераторы, и прокачиваю скилл их использования.
⬇️
В этом году я закончил бакалавриат, и уже работаю около года. И периодически я задумываюсь о том насколько хорошо развиваюсь. И понимаю, что в плане развития работа значительно отличается от учёбы. На работе изучаю меньше нового, ведь там я уже влился в процесс. И это немного непривычное состояние для меня, ведь всю жизнь я только и знал что учиться и решать сложные задачи в школе, учиться в универе, и параллельно делать кучу всяких проектов.
Плюс третий-четвёртый курсы прошли без математики, и от её отсутствия я тоже заметил, что получаю меньше умственного стресса, и меньше челленджей.
В итоге это всё вылилось в то, что мне теперь кажется, что я деградирую и у меня отсыхают мозги. А единственный известный мне способ не деградировать и увлажнять мозги - это обучаться, и лучше обучаться математике, ну или решать олимпиадные задачи (ведь они сложные). Поэтому где-то в глубине головы у меня посеялась эта мысль, что мне надо начать либо математику, либо олимпиадки.
Затем, я делаю свои проекты, о которых пишу в этом канале. Но даже с этими проектами мне кажется что мозги отсыхают, потому что у меня по ним либо не идёт ничего хорошего, либо они не являются каким-то челлендежем, а являются просто рутиной.
Затем я посмотрел сериал "Ход королевы", суть которого я к сожалению не буду рассказывать, ибо не люблю спойлерить, советую просто посмотреть.
Затем ещё у нас в университете проходила олимпиада, на которую я решил не идти, ведь там мне придётся прогать на C++, а я такой вот вредный растоман, и вообще на Раст я решил окончательно уйти из-за олимпиады в Барнауле, где я хотел написать что-то на плюсах, и это было дико неудобно, а на расте ведь есть итераторы. И вот я решил не идти на олимпиаду, а меня туда позвал преподаватель, с которым я хорошо знаком. И стало как-то неловко.
Ну и плюс в это время я отказался от телеги и у меня появилось свободное время.
А ещё какой-то чувак усомнил мою веру в себя, сказав что "мне надо больше читать, чем писать".
И вот все эти вещи наложились друг на друга, и теперь я очень активно занимаюсь олимпиадным программированием на codeforces.com, и поставил на паузу развитие всех своих текущих проектов, и написание всяких статей.
Я начал участвовать в своём первом контесте, и сразу почувствовал себя дико тупым, ведь я не могу найти решение простых задач, или запрограммировать их нормально, качественно и быстро. Но почему-то меня это не остановило и я начал участвовать в каждом рейтинговом соревновании.
А ещё на этом сайте есть раздел EDU, и там можно посмотреть лекции по типичным олимпиадным темам и отправить свои решения упражнений на проверку. Советую хотя бы ознакомиться с тем что такое Z-функция. Для меня это стало открытием и взрывом мозга. Особенно мне понравились задачи на Z-функцию, ведь там я на полную катушку использую Растовские итераторы, и прокачиваю скилл их использования.
⬇️
А вот как-то так выглядит использование этой программки.
И вот недавно, 4 декабря, прошёл ещё один контест на этом сайте, и мне очень понравилось как он прошёл. Я быстро решил задачу А, а потом прочитал задачу Б и офигел от её сложности и моего непонимания как решать... Я подумал сдаться, но потом сказал себе что нельзя, взял бумажку и карандаш, и начал крутить эту задачу и так и эдак, в итоге математически вывел что оказывается там что-то независимо, и полностью понял как её решить. Затем уже быстро запрограммировал и она прошла. Затем я пытался решить задачу Ц, но во время олимпиады не смог, ибо неправильно прочитал условие. Меня вдохновило что я осилил задачу Б (хотя она была второй по лёгкости), и я решил после контеста решать дальше. В итоге я смог полностью своим умом добить задачу Ц. Затем снова при помощи бумажки обнаружил решение задачи Д. Затем подумал что понял как решать задачу Е, запрограммировал и она не прошла, затем взялся за бумажку, и её тоже добил. И вот я дошёл до задачи Ф. Это последняя и самая сложная задача, у которой в тэгах написано страшное словосочетание: "динамическое программирование". Я начал её крутить, исследовать, а затем понял что уже 5 утра, и надо бы спать.
Но эта задача меня не отпускала, я не мог после такого продуктивного дня так просто остановиться, поэтому вместо того чтобы спать, я лежал с закрытыми глазами, и докручивал эту задачу у себя в голове, без всякой бумажки, спорил с собой какие действия я могу оптимизировать, а какие не могу и почему. В итоге пришёл к решению, которое использует: динамическое программирование, очередь с приоритетом, бинарный поиск и суффиксный массив минимумов. 🤯
В этот момент я почувствовал себя Бет Хармон из сериала "Ход королевы" 😂
Теперь я мог со спокойной совестью спать. И на следующий день, когда запрограммировал эту задачу, и отладил на примере из условия, она сразу же полностю правильно прошла на всех других тестах, и не упала по времени.
А самое главное что все эти задачи я прорешал полностью сам, без подглядывания в разбор или чужие решения. Очень горд собой.
В общем благодаря этому я вспомнил что такое по-настоящему думать, увлажнил мозги, и хочу дальше развиваться на этом сайте.
⬇️
Но эта задача меня не отпускала, я не мог после такого продуктивного дня так просто остановиться, поэтому вместо того чтобы спать, я лежал с закрытыми глазами, и докручивал эту задачу у себя в голове, без всякой бумажки, спорил с собой какие действия я могу оптимизировать, а какие не могу и почему. В итоге пришёл к решению, которое использует: динамическое программирование, очередь с приоритетом, бинарный поиск и суффиксный массив минимумов. 🤯
В этот момент я почувствовал себя Бет Хармон из сериала "Ход королевы" 😂
Теперь я мог со спокойной совестью спать. И на следующий день, когда запрограммировал эту задачу, и отладил на примере из условия, она сразу же полностю правильно прошла на всех других тестах, и не упала по времени.
А самое главное что все эти задачи я прорешал полностью сам, без подглядывания в разбор или чужие решения. Очень горд собой.
В общем благодаря этому я вспомнил что такое по-настоящему думать, увлажнил мозги, и хочу дальше развиваться на этом сайте.
⬇️
Ну и конечно, все задачи я решаю на расте, ведь я очень упоротый максималист! Хоть это иногда и доставляет мне проблем, но я стараюсь писать более-менее идиоматичный код. Зато на этих олимпиадках как никогда понимаешь насколько же Растовские итераторы офигенны.
Ну и кстати, когда я делал дерево отрезков, я понял что его концепция идеально ложится на идею Раста: заимствование. Когда создаёшь дерево отрезков на каком-то массиве, ты можешь взять его в займы, даже в мутабельные займы, и никто не может модифицировать извне этот массив, потому что тогда дерево будет невалидным. А если хочешь модифицировать массив, то можно сделать специальные методы для дерева, которые модифицируют и массив и соответствующие элементы дерева.
Ещё в процессе я нахожу чего не хватает стандартной библиотеке, например вот понял что метод scan какой-то неправильный, и в процессе олимпиадок мне пригодились бы описанные там
Так же я придумал ещё один метод над
Так же мне нравится политика codeforces в том, что я могу использовать заранее написанный код, поэтому я собираю коллекцию полезных штук для олимпиадок, отлаживаю их и покрываю тестами: olymp/templates.
⬇️
Ну и кстати, когда я делал дерево отрезков, я понял что его концепция идеально ложится на идею Раста: заимствование. Когда создаёшь дерево отрезков на каком-то массиве, ты можешь взять его в займы, даже в мутабельные займы, и никто не может модифицировать извне этот массив, потому что тогда дерево будет невалидным. А если хочешь модифицировать массив, то можно сделать специальные методы для дерева, которые модифицируют и массив и соответствующие элементы дерева.
Ещё в процессе я нахожу чего не хватает стандартной библиотеке, например вот понял что метод scan какой-то неправильный, и в процессе олимпиадок мне пригодились бы описанные там
scan_before и scan_after.Так же я придумал ещё один метод над
Option: any_or_both_with, при помощи которого можно считать минимум или максимум засунутых в Option величин (надо бы в далёком и прекрасном будущем создать на это MR как сделал вафель >_<).Так же мне нравится политика codeforces в том, что я могу использовать заранее написанный код, поэтому я собираю коллекцию полезных штук для олимпиадок, отлаживаю их и покрываю тестами: olymp/templates.
⬇️
Вот я вернулся, и тупая телега расположила посты в неправильном порядке -_- Сорян.
В свободное время я продолжаю развивать
Последние фичи:
1. Возможность тестировать конкретный экзешник -
2. Появились CLI команды для генерации и удаления кода экзешников.
Следующие фичи будут обозначаться отдельно, потому что я хочу их прокомментировать.
Фича #3: Автоматический парсинг страницы на codeforces, извлечение имён всех задач и тестов с входными и выхоными данными.
Я парсю html через соответствующие библиотеки, и обращаюсь к результату через селекторы, например все входные данные описываются так:
Фича #4: Возможность указывать в тесте чекер (который ты напишешь как обычный экзешник), который будет интерактивно общаться с программой, и проверять её результат.
А вот это уже интересно. Чтобы понимать что такое интерактивное общение, можете прочитать условия этой задачи: https://codeforces.com/contest/1451/problem/E2. Очевидно, что такую задачу тестировать довольно нетривиально. Нужно написать две программы: одна решает саму задачу, другая осуществляет интерактивное общение для заданного массива.
То есть, у нас есть программы А и Б. А решает задачу, а Б общается с А, предоставляя ей информацию на вход. Что есть тест? Например, у нас есть массив
Значит, изначально, тест мы записываем в stdin Б, затем stdout от Б мы направляем на stdin А, а stdout от A направляем на stdin Б. А как можно после этого узнать правильный ли выдала ответ программа А или нет? Б может записывать вердикт в свой stderr.
И существует два вида тестов:
* Обычный тест: вход теста подаётся на stdin программы, а выход теста сравнивается с stdout программы.
* Тест с чекером: вход теста подаётся чекеру на вход, а выход теста сравнивается с stderr чекера.
Что интерено, такой схемой можно описать любой из вариантов тестирования олимпиадной задачи:
* Когда ответов существует множество, и ответ нужно проверять какой-то программой.
* Когда нужно сгенерировать большой тест для тестирования программы на скорость.
* Ну и конечно, интерактивное общение как в той задаче.
Например, если у нас задача подразумевает простые тесты, то встаёт вопрос, а как быть когда у нас выход теста сравнивается от чекера, а не от программы? Можно просто написать в чекере, чтобы он весь stdout программы транслировал в свой stderr.
А теперь самое интересно, как это запрограммировать? Окей, создаём два процесса через std::process::Command, берём их входы и выходы, и пытаемся читать и писать через read-write. И сталкиваемся с проблемой, что ввод в расте по умолчанию блокирующий. Это означает, что если прямщас байтов нету, то вызов
А это серьёзная проблема, ведь как можно видеть по этой задаче E2, одна программа начинает выводить результат исключительно после того как получит информацию от другой. При этом у нас вывод может быть неизвестного размера, и может не поместиться в буфер сразу, а может и вообще быть кратен буферу. И у нас нет способа узнать когда мы прочитали все байты что программа вывела прям щас, а когда нет.
Это приводит к тому, что нужно использовать неблокирующий ввод-вывод. А как я понял, официально, и кросс-платформенно он существует только в виде машинерии async/await, и, например, в tokio.
⬇️
olytest - прогу для быстрого тестирования программ во время олимпиадного программирования.Последние фичи:
1. Возможность тестировать конкретный экзешник -
a, b, e1. Раньше тестирование запускалось только из main.rs файла, и прошлый код приходилось стирать.2. Появились CLI команды для генерации и удаления кода экзешников.
Следующие фичи будут обозначаться отдельно, потому что я хочу их прокомментировать.
Фича #3: Автоматический парсинг страницы на codeforces, извлечение имён всех задач и тестов с входными и выхоными данными.
Я парсю html через соответствующие библиотеки, и обращаюсь к результату через селекторы, например все входные данные описываются так:
"div.input pre". Что удивительно, для растишки все такие библиотеки есть, и подключаются в два клика.Фича #4: Возможность указывать в тесте чекер (который ты напишешь как обычный экзешник), который будет интерактивно общаться с программой, и проверять её результат.
А вот это уже интересно. Чтобы понимать что такое интерактивное общение, можете прочитать условия этой задачи: https://codeforces.com/contest/1451/problem/E2. Очевидно, что такую задачу тестировать довольно нетривиально. Нужно написать две программы: одна решает саму задачу, другая осуществляет интерактивное общение для заданного массива.
То есть, у нас есть программы А и Б. А решает задачу, а Б общается с А, предоставляя ей информацию на вход. Что есть тест? Например, у нас есть массив
0 0 2 3. Как нам протестировать что программа А способна получить этот массив? Можно подать его на вход Б, Б выведет нужную информацию и далее будет общаться с А.Значит, изначально, тест мы записываем в stdin Б, затем stdout от Б мы направляем на stdin А, а stdout от A направляем на stdin Б. А как можно после этого узнать правильный ли выдала ответ программа А или нет? Б может записывать вердикт в свой stderr.
И существует два вида тестов:
* Обычный тест: вход теста подаётся на stdin программы, а выход теста сравнивается с stdout программы.
* Тест с чекером: вход теста подаётся чекеру на вход, а выход теста сравнивается с stderr чекера.
Что интерено, такой схемой можно описать любой из вариантов тестирования олимпиадной задачи:
* Когда ответов существует множество, и ответ нужно проверять какой-то программой.
* Когда нужно сгенерировать большой тест для тестирования программы на скорость.
* Ну и конечно, интерактивное общение как в той задаче.
Например, если у нас задача подразумевает простые тесты, то встаёт вопрос, а как быть когда у нас выход теста сравнивается от чекера, а не от программы? Можно просто написать в чекере, чтобы он весь stdout программы транслировал в свой stderr.
А теперь самое интересно, как это запрограммировать? Окей, создаём два процесса через std::process::Command, берём их входы и выходы, и пытаемся читать и писать через read-write. И сталкиваемся с проблемой, что ввод в расте по умолчанию блокирующий. Это означает, что если прямщас байтов нету, то вызов
read будет ждать пока программа не выведет данные.А это серьёзная проблема, ведь как можно видеть по этой задаче E2, одна программа начинает выводить результат исключительно после того как получит информацию от другой. При этом у нас вывод может быть неизвестного размера, и может не поместиться в буфер сразу, а может и вообще быть кратен буферу. И у нас нет способа узнать когда мы прочитали все байты что программа вывела прям щас, а когда нет.
Это приводит к тому, что нужно использовать неблокирующий ввод-вывод. А как я понял, официально, и кросс-платформенно он существует только в виде машинерии async/await, и, например, в tokio.
⬇️
Я про async/await не знал абсолютно ничего, и очень тяжело было прийти к первому рабочему прототипу. Я всё же хотел сделать всё очень императивно, найти такой метод, который мне мог бы чётко сказать:
У нас может быть две главные футуры:
* Чтение stdout чекера
* Чтение stdout программы
После того как мы прочитали хоть сколько-нибудь информации из каждого источника, мы можем сразу записывать в stdin другого. Так что макрос
Затем благодаря помощи Вафеля обнаружился метод
В итоге я пришёл к такому коду: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=163960a0f7031364984e2099c0a4de66 .
Он вроде работал, и всё было хорошо, но затем я заметил, что когда один из процессов начинает паниковать и выводить кучу инфы в stderr, которая не умещается в буфер, у меня переставало работать считывание. Тупо зависало. Когда я пытался локализовать в каком месте оно зависало, и писал макрос
Но затем мне всё же удалось найти место, куда можно поставить
В моём методе
В общем я осознал свою ошибку и вернулся на
⬇️
ПРЯМ_ЩАС_БАЙТОВ_НЕТУ. Такой метод правда есть, и он называется poll_read, но он какой-то очень сложный, ему нужен какой-то контекст, какой-то waker, а я не знаю откуда всё это взять. Поэтому пришлось извращаться как есть, и несложными измышлениями, и поверхностным чтением документации я пришёл к тому, что нужно использовать макрос select!{}, который из нескольких футур выбирает ту, которая завершится первой.У нас может быть две главные футуры:
* Чтение stdout чекера
* Чтение stdout программы
После того как мы прочитали хоть сколько-нибудь информации из каждого источника, мы можем сразу записывать в stdin другого. Так что макрос
select!{} вполне подходит, но он мне как-то не нравится, ибо с ним надо было иметь для каждого читателя по отдельному буферу, и я хотел прийти всё же к ПРЯМ_ЩАС_БАЙТОВ_НЕТУ. Затем благодаря помощи Вафеля обнаружился метод
futures::poll_fn, который позволяет вызывать сложнющий poll_read без ручного создания всяких контекстов итд. Я как увидел этот метод, сразу понял, что мне нужен был именно он, и недоумевал, почему такой прекрасный метод не суют во все туториалы и вводные по async/await'у в расте.В итоге я пришёл к такому коду: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=163960a0f7031364984e2099c0a4de66 .
Он вроде работал, и всё было хорошо, но затем я заметил, что когда один из процессов начинает паниковать и выводить кучу инфы в stderr, которая не умещается в буфер, у меня переставало работать считывание. Тупо зависало. Когда я пытался локализовать в каком месте оно зависало, и писал макрос
dbg!(), ОНО НЕ ЗАВИСАЛО. Когда я пытался сделать работу помедленней, и ставил sleep(100ms), ОНО НЕ ЗАВИСАЛО. Я погрешил на async/await, что из-за своей сложности они создают какие-то квантовые эффекты, измерение которых приводит к их исчезновению.Но затем мне всё же удалось найти место, куда можно поставить
dbg!() без исчезновения квантовых эффектов, но это ничего не дало. Затем я нарушил своё отстранение от телеги и зашёл в async-чатик и задал там свой вопрос (и сейчас понял что там в коде неправильная ссылка): https://xn--r1a.website/rust_async/29266 (можно не читать). Мне никто не отвечал, поэтому я продолжил решать проблему самостоятельно. И как это обычно у меня бывает, благодаря тому что для чатика я очень хорошо сформулировал вопрос, я начал понимать свою проблему лучше, и потом размышлениями пришёл к такому:В моём методе
poll_read вызывается внутри цикла постоянно и через очень короткие промежутки времени. Когда я ставил задержку или dbg!(), эти промежутки времени увеличивались. А у async/await есть такая штука как waker, и по идее poll_методы нужно вызывать только после того как твоего waker'а ткнут носом что всё закончилось. А я их вызывал в цикле. И видимо, на внутреннюю машинерию асинхронного кода и регистрацию этих waker'ов тратилось время больше, чем мои промежутки времени в цикле, поэтому у меня "неблокирующее" чтение никак не могло выдать результат, который бы отличался от Pending.В общем я осознал свою ошибку и вернулся на
select!{}. И как я потом замерил, select!{} использует минимальное число обращений к чтению, потому что блокируется на всех футурах, если они все не дают результат прямщас. А это значит, что он и эффективней.⬇️
Фича #5: Модифицировал синтаксис тестов. Теперь он хранится в одном файле, поддерживает экранирование, поддерживает задание чекера, и состоит всего из трёх символов.
Более подробно:
* Вход и выход теста теперь находится в одном файле по совету Сергея Совы.
* Разные тесты разделяются символом \.
* Вход и выход разделяются либо символом ~, либо символом %. Первый символ пишется в случае обычного теста, а второй в случае наличия чекера. Если нужно, чтобы тест не сравнивался с чем-то, а его результат просто вывелся на экран, то выход может быть просто набором пробельных символов.
* Так же я сделал токенизацию выхода программы и теста, чтобы лишние пробелы и лишние пустые строки не влияли на результат, и чтобы легко было сравнивать.
* Экранировать один из трёх управляющих символов можно тупо написав его два раза.
Для синтаксиса тестов я старался выбирать символы, которые практически никогда не встречаются в тестах олимпиадных задачек, но иногда всё же могут встретиться, и экранировать их - важно. Я часто замечаю, что экранированию синтаксиса уделяется мало внимания при проектировании языка описания чего-то. Для меня растовские строки с
Далее в
* Добавить возможность писать в олимпиадной программе
* Добавить поддержку ЯП: C++ и Python/PyPy. Это самые частые языки для олимпиадного программирования.
* Написать доку на английском и русском.
После этих трёх пунктов я отлажу программу на себе, своих знакомых, и затем можно будет её официально представить на codeforces, ибо у людей спрос на что-то такое есть: они на стримах с разборами у neal'а постоянно спрашивают что у него там за скрипты и где их можно взять (кто не помнит, я вдохновился именно его скриптами).
И причём все эти три пункта относительно не сложно и быстро сделаются, а программа потенциально может стать юзабельной большим числом человек. Так что может быть, если всё получится, я наконец сделаю что-то, чем будет пользоваться большое число человек. Так что этот проект нельзя просто так бросить, как все остальные в этом канале.
⬇️
Более подробно:
* Вход и выход теста теперь находится в одном файле по совету Сергея Совы.
* Разные тесты разделяются символом \.
* Вход и выход разделяются либо символом ~, либо символом %. Первый символ пишется в случае обычного теста, а второй в случае наличия чекера. Если нужно, чтобы тест не сравнивался с чем-то, а его результат просто вывелся на экран, то выход может быть просто набором пробельных символов.
* Так же я сделал токенизацию выхода программы и теста, чтобы лишние пробелы и лишние пустые строки не влияли на результат, и чтобы легко было сравнивать.
* Экранировать один из трёх управляющих символов можно тупо написав его два раза.
Для синтаксиса тестов я старался выбирать символы, которые практически никогда не встречаются в тестах олимпиадных задачек, но иногда всё же могут встретиться, и экранировать их - важно. Я часто замечаю, что экранированию синтаксиса уделяется мало внимания при проектировании языка описания чего-то. Для меня растовские строки с
r#"text"# стали откровением в области экранирования, ведь это гениально, сделать хэши, чтобы можно было без проблем писать кавычки. Жаль что эти строки являются raw, и внутри них нельзя писать \n чтобы обознчаить перенос строки. Я бы хотел обычную строку, но с хэшами: #" "hi" - says\nsimon "#.Далее в
olytest у меня осталось три жирных пункта:* Добавить возможность писать в олимпиадной программе
include!(), чтобы вместо этого подставлялся нужный текст, и генерировался в отдельный файл, чтобы вручную не копипастить.* Добавить поддержку ЯП: C++ и Python/PyPy. Это самые частые языки для олимпиадного программирования.
* Написать доку на английском и русском.
После этих трёх пунктов я отлажу программу на себе, своих знакомых, и затем можно будет её официально представить на codeforces, ибо у людей спрос на что-то такое есть: они на стримах с разборами у neal'а постоянно спрашивают что у него там за скрипты и где их можно взять (кто не помнит, я вдохновился именно его скриптами).
И причём все эти три пункта относительно не сложно и быстро сделаются, а программа потенциально может стать юзабельной большим числом человек. Так что может быть, если всё получится, я наконец сделаю что-то, чем будет пользоваться большое число человек. Так что этот проект нельзя просто так бросить, как все остальные в этом канале.
⬇️