А вот как-то так выглядит использование этой программки.
Ну и конечно, все задачи я решаю на расте, ведь я очень упоротый максималист! Хоть это иногда и доставляет мне проблем, но я стараюсь писать более-менее идиоматичный код. Зато на этих олимпиадках как никогда понимаешь насколько же Растовские итераторы офигенны.
Ну и кстати, когда я делал дерево отрезков, я понял что его концепция идеально ложится на идею Раста: заимствование. Когда создаёшь дерево отрезков на каком-то массиве, ты можешь взять его в займы, даже в мутабельные займы, и никто не может модифицировать извне этот массив, потому что тогда дерево будет невалидным. А если хочешь модифицировать массив, то можно сделать специальные методы для дерева, которые модифицируют и массив и соответствующие элементы дерева.
Ещё в процессе я нахожу чего не хватает стандартной библиотеке, например вот понял что метод 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'а постоянно спрашивают что у него там за скрипты и где их можно взять (кто не помнит, я вдохновился именно его скриптами).
И причём все эти три пункта относительно не сложно и быстро сделаются, а программа потенциально может стать юзабельной большим числом человек. Так что может быть, если всё получится, я наконец сделаю что-то, чем будет пользоваться большое число человек. Так что этот проект нельзя просто так бросить, как все остальные в этом канале.
⬇️
С НГ! Желаю в этом году чтобы произошёл качественный переход, после которого от тебя все отстанут и будут меньше трепать нервы и отнимать время
dev optozorax
5-бальная шкала оценки неверна. #мысли На данный пост меня вдохновило следующее сообщение: klavaorgwork/159174. В нём чувак говорит что оценка 3 - это оценка "удовлетворительно", когда сервис работает как полагается. 4 он ставит когда есть что-то действительно…
В копилочку о том почему шкалам оценки нужно переосмысление, которое я описывал в этом посте.
How gamers see review scores now.
How gamers see review scores now.
dev optozorax
5-бальная шкала оценки неверна. #мысли На данный пост меня вдохновило следующее сообщение: klavaorgwork/159174. В нём чувак говорит что оценка 3 - это оценка "удовлетворительно", когда сервис работает как полагается. 4 он ставит когда есть что-то действительно…
Выделил этот пост в отдельную статью в блоге, теперь со всеми можно делиться ссылкой:
https://optozorax.github.io/5-point-ratings-are-wrong
https://optozorax.github.io/5-point-ratings-are-wrong
optozorax.github.io
5-бальная шкала оценки неверна — Блог optozorax'а
Весь мир снова ошибается, и у меня снова есть великолепное решение.
Как известно, я очень упорот по клавиатурам.
И в этой области я развиваюсь уже много лет, поэтому мне есть что сказать. И вот думал что неплохо было бы написать статью о своей раскладке (а она довольно уникальна). Получилась, конечно, статья о раскладке, но случайно я параллельно рассказал про десятипальцевый метод, про неверность стандартных клавиатур и историю своего развития. Получилась огромная статья на 200к символов, которую читать, наверное, 2 часа.
Так что приятного чтения! 🍿
#клавиатуры
И в этой области я развиваюсь уже много лет, поэтому мне есть что сказать. И вот думал что неплохо было бы написать статью о своей раскладке (а она довольно уникальна). Получилась, конечно, статья о раскладке, но случайно я параллельно рассказал про десятипальцевый метод, про неверность стандартных клавиатур и историю своего развития. Получилась огромная статья на 200к символов, которую читать, наверное, 2 часа.
Так что приятного чтения! 🍿
#клавиатуры
optozorax.github.io
Раскладка Ильи Шепрута — Блог optozorax'а
Моя раскладка, история прихода к ней и объяснение каждого дизайнерского решения.
👍6❤2🔥1
В моей статье, в секции про Кладенец, было упоминание концепта клавиатуры, которую я однажды придумал. И называется она - Нумкорд.
Данная клавиатура состоит из 5 клавиш, и на ней всё нажимается через аккорды. Пользоваться ей можно используя всего три пальца. Данная клавиатура реализует расширенный нумпад, то есть с помощью неё можно писать цифры, стрелки, арифметические знаки, скобочки, и ещё на ней поместились клавиши для передвижения по ячейкам экселя через Tab, Shift+Tab, Enter, Shift+Enter. И это всё на 5 клавишах!
Конечно, пользоваться такой клавиатурой сложнее, чем обычным нумпадом, не так быстро, но зато как красиво! Как красиво на неё всё помещается, и как симметрично на схеме там размещаются клавиши передвижения.
А ещё в реальности она была бы очень маленькой. Выглядит как игрушка, но при этом полноценный нумпад.
Данная клавиатура состоит из 5 клавиш, и на ней всё нажимается через аккорды. Пользоваться ей можно используя всего три пальца. Данная клавиатура реализует расширенный нумпад, то есть с помощью неё можно писать цифры, стрелки, арифметические знаки, скобочки, и ещё на ней поместились клавиши для передвижения по ячейкам экселя через Tab, Shift+Tab, Enter, Shift+Enter. И это всё на 5 клавишах!
Конечно, пользоваться такой клавиатурой сложнее, чем обычным нумпадом, не так быстро, но зато как красиво! Как красиво на неё всё помещается, и как симметрично на схеме там размещаются клавиши передвижения.
А ещё в реальности она была бы очень маленькой. Выглядит как игрушка, но при этом полноценный нумпад.
ДР Канала! Вчера, 24 января, данному каналу исполнился год. И как раз аккурат к этому событию количество подписчиков перевалило за 4 сотни. За этот год сюда было написано почти 300 сообщений.
Я не в настроении рефлексировать, рассказывать историю или говорить планы на будущее, так что просто скажу спасибо всем кто читает и делится с друзьями!
Я не в настроении рефлексировать, рассказывать историю или говорить планы на будущее, так что просто скажу спасибо всем кто читает и делится с друзьями!
Forwarded from Кладенец, обучение (илья шепрут)
Я тут вдохновился статьёй про однорукую раскладку OPRI, и решил придумать что-то аккордовое, чтобы можно было одной рукой нажимать любой хоткей.
И получилось такая клавиатура - Hotkeypad. Тут вся основная инфа написана на картинке. Главное отличие от Кладенца - это то, что любой хоткей нажимается одним аккордом, когда как на Кладенце хоткеи одной рукой нажимаются при помощи залипающих модификаторов.
И получилось такая клавиатура - Hotkeypad. Тут вся основная инфа написана на картинке. Главное отличие от Кладенца - это то, что любой хоткей нажимается одним аккордом, когда как на Кладенце хоткеи одной рукой нажимаются при помощи залипающих модификаторов.