Разбор исходников программы snips-nlu. Часть 1

Недавно в школе проходила РПГ на тему сдачи экзаменов. То есть ОГЭшники и ЕГЭшники на полном серьёзе заполняли бланки, решали задачи полного экзаменационного варианта, а я изображала сначала технического специалиста, а потом проверяющего эксперта.
Ещё один такой отыгрыш ждёт нас 17 мая.
В ЕГЭ, как ни забавно, играть гораздо проще: вся работа проходит за компьютером, и система сама проверяет верность введённого ответа. А вот ОГЭ приходится проверять вручную. И готовить для сдачи индивидуальные бланки.
На каждом ОГЭшном бланке стоит 13-значный номер. Причём на бланках № 1 и № 2 эти номера обычно разные. По номеру ваши результаты сопоставляются вашей записи в базе — как раз это гарантирует объективность, ведь ваше имя нигде не «светится».
Ну и этот номер вы задаёте в качестве имени файлов с решениями второй части экзамена.
В нашем отыгрыше эти номера мне надо было раскидать на всех сдающих. Единственное условие: все номера должны быть разными, чтобы я потом по имени файла поняла, кому балл за этот файл рисовать.
Варианты решения могут быть разными. Я, естественно, набросала свой на Питоне, не зря же он отличный язык прототипирования.
1) Составила строку из цифр, повторённых пять раз. Это позволило цифрам в номере повторяться.
num = '' for i in range(5): for j in range(10): num += str(j)
2) Строку я преобразовала в список. Теперь каждый символ строки стал отдельным элементом списка.
num = list(num)
3) Теперь этот список я «замешала» при помощи метода .shuffle() модуля random.
random.shuffle(num)
Теперь у нас уже случайный набор цифр, только слишком длинный — из 50 цифр.
4) Осталось вывести первые 13 символов нашего списка. Проще всего это сделать, собрав элементы снова в строку при помощи среза.
print(''.join(num)[:13])
Вот весь код программки, которая за один запуск выдаёт десять случайных 13-значных чисел.
import random num = '' for i in range(5): for j in range(10): num += str(j) num = list(num) for i in range(10): random.shuffle(num) print(''.join(num)[:13])
Обратите внимание: составляем 50-значную строку мы один раз, а дальше просто замешиваем её, сколько нужно.
Вывод может быть, например, таким:
1545020904967 4735326057005 2079875308964 3482096197552 3335818279040 5864215649929 4832200521656 5758123696278 2829394392713 1088239197451
Ещё можно проверить на ведущие нули и удалить их при необходимости. Хотя в бланках у нас не числа, а именно коды, так что ведущие нули имеют право на существование.
Если вам где-нибудь понадобятся случайные наборы символов — пользуйтесь!
Интерфейс МЭШ заточен под управление тыками мыши, причём все элементы управления в разных местах (и эти места ещё отличаются для разных режимов / размеров списка учащихся / количества уроков / темы урока и пр.). Каждое действие требует множества тыков в разные точки окна браузера.
Гораздо проще набирать команды текстом, например:
«дз» — вставить текст ДЗ из буфера обмена в поле ввода уже открытого урока;
«иванов 5» — поставить указанную оценку выбранному ученику в уже открытом журнале;
«вт 3 у» — открыть журнал на вкладке «Урок» для третьего урока во вторник — из открытого расписания.
Мой скрипт предоставляет такую возможность. В силу особенностей интерфейса системы, он не универсален и требует некоторой настройки для каждого действия. Зато даёт как увеличение скорости работы, так и уменьшение урона здоровью, которое мы — преподаватели — получаем из-за значительного напряжения глаз и общей нервозности от множества кликов, когда каждый нужный элемент необходимо «поймать» мышью.
Скрипт никак не взаимодействует с базами данных или содержимым страницы — это простое управление мышью.
Скрипт я делала для себя. Но буду рада, если он пригодится и вам, коллеги.
Тестировалось в Яндекс-браузере на группах до 22 человек и максимальном количестве уроков в день — 6 (не считая «окон», которые в расписании не отображаются).
Запускаем МЭШ в Яндекс-браузере.
Страница журнала должна быть открыта в масштабе 90%. Изменение масштаба отображения: [Ctrl]+[+] и [Ctrl]+[-].
Начинаем работу со страницы расписания.
Команда:
день номер у/ж <строк>
где день = пн / вт / ср / чт / пт
номер = 1.6
<строк> (необязательный) = количество строк в теме урока (положение кнопки открытия зависит от длины строки темы)
Например:
вт 3 у пт 6 ж 4
Тонкости:
• Я не знаю, как ведёт себя журнал, если уроков в вашем расписании больше шести в день без учёта «окон». У меня уроков по семь, но с окном — клеточек в расписании шесть. И они как раз занимают все пространство окна сверху донизу.
При более шести плашек уроков, наверное, либо требуется прокрутка, либо элементы разъезжаются (плашки уменьшаются). В обоих случаях скрипт использовать не получится или требуется подгонка координат.
Команда:
бдз
Команда:
дз
Текст домашнего задания должен быть заранее скопирован в буфер обмена (например, через [Ctrl]+[C] или меню Правка → Копировать)
Команда:
оценки положение группа
где положение = п / л — к какому краю сетки прижата колонка, куда будут выставляться оценки;
группа = название группы как в файле students.dat
Например:
оценки п 9а1 оценки л 10б
Предварительно:
• МЭШ должен быть открыт в режиме журнала на выбранном уроке
• Колонка оценок должна быть прижата к левому или правому краю сетки (см. скриншот)
Я не знаю, как это будет работать в начале года для нескольких уроков. Первый очевидно будет автоматически прижат к левому краю, а вот можно ли подвинуть влево второй-третий и т. д., пока не накопится целая страница колонок — надо будет проверять в следующем году.
• В журнале должен быть выбран «Расширенный режим», чтобы окошко выставления оценки распахивалось сверху донизу окна браузера (см. скриншот), иначе это окошко всегда оказывается в разных (непредсказуемых) местах, и скрипт не сможет «поймать» кнопку оценки
• Файл students.dat должен быть заполнен (см. ниже формат файла)
• Для колонки должен быть заранее выбран тип работы (кроме «Домашнего задания», см. дальше).
• Темой урока не может быть «Повторение», т. к. в этом случае требуется выбирать тему для каждой оценки.
Команда:
иванов 5 <2>
где иванов = фамилия учащегося в любом регистре
5 = оценка 2.5
<2> (необязательный) — вторая оценка в той же клетке.
На каждой строке — сведения об одном ученике.
группа|номер|фамилия
Например
9а1|1|Иванов 9а1|2|Петров 10б|1|Сидоров и т.д.
Необязательно вся группа подряд.
Номер должен соответствовать номеру учащегося в списке группы — точно как в МЭШ на странице выставления оценок.
Тонкости:
• Для типа работы «Домашнее задание» добавили дополнительные элементы интерфейса, и теперь кнопки оценок находятся не там, где для других типов.
Я решаю эту проблему так:
— выбираю другой тип работы;
— выставляю оценки;
— меняю тип работы на «домашнее задание»
• Для урока повторения приходится выбирать тему для каждой оценки. Скрипт поставит оценку, но без темы сохранить её не сможет.
► txtgui4mash.exe — скомпилированная автономная программа, ничего не требует, кроме Windows. Запакована в zip-архив, т. к. 12 Mb размером (потому что Python).
► txtgui4mash.py — исходный код программы (если вы боитесь exe-шников или хотите изменить скрипт под свои нужды). Для работы нужно установить библиотеку pyautogui.
► students.dat — пример файла с данными учеников. Должен находиться в той же папке, что и txtgui4mash.exe (или в папке Python-проекта). Кодировка: ANSI (Windows-1251).
Разработка прикладного программного обеспечения на языке Python с применением библиотеки Qt (PySide6), СУБД PostgreSQL и других технологий
Разработка прикладного программного обеспечения на языке Python с применением библиотеки Qt (PySide6), СУБД PostgreSQL и других технологий.
Разработка прикладного программного обеспечения на языке Python с применением библиотеки Qt (PySide6), СУБД PostgreSQL и других технологий.
Разработка прикладного программного обеспечения на языке Python с применением библиотеки Qt (PySide6), СУБД PostgreSQL и других технологий
Разработка прикладного программного обеспечения на языке Python с применением библиотеки Qt (PySide6), СУБД PostgreSQL и других технологий.
Разработка прикладного программного обеспечения на языке Python с применением библиотеки Qt (PySide6), СУБД PostgreSQL и других технологий
Разработка прикладного программного обеспечения на языке Python с применением библиотеки Qt (PySide6), СУБД PostgreSQL и других технологий
Разработка прикладного программного обеспечения на языке Python с применением библиотеки Qt (PySide6), СУБД PostgreSQL и других технологий.
1. Решаем задачу на количество чисел по условиям тремя способами: аналитически, простым перебором на Python и при помощи библиотеки Python itertools.
2. Решаем задачу на алфавитные последовательности двумя способами: при помощи аналитического трюка и при помощи Python: библиотеки itertools и функции enumerate
3. Ещё один вид задач № 8 ЕГЭ по информатике (комбинаторика): составление слов перестановками букв. Рассмотрим простой аналитический подход и разберёмся, как решать задачу с подковырками при помощи библиотеки Python itertools и функции enumerate
Итак, в задаче на комбинаторику два основных типа:
При этом у нас три основных типа решения:
А теперь — за тренировку!
💾 Методы .index() и .find() делают одно и то же — ищут первое вхождение чего-либо в свою коллекцию. Только .index() применяется к списку и ищет элемент, а .find() работает со строкой и ищет в ней подстроку.
список.index(элемент) строка.find(подстрока)
Вот пример:
s = '12345' x = [1, 2, 3, 4, 5] print(s.find('3'), x.index(3))
Получим 2 и 2, потому что нумерация элементов и в строках, и в списках идёт с нуля.
Но что будет при использовании методов .index() и .find(), если такого элемента или такой подстроки нет?
Например, для строки и списка из примера выше:
s = '12345' x = [1, 2, 3, 4, 5] print(s.find('7')) print(x.index(7))
Метод .find() для отсутствующей строки вернёт -1. Почему не ноль? Потому что нулевая позиция существует.
А вот .index() для отсутствующего элемента сгенерирует ошибку. Проще говоря, программа обругает вас и упадёт, вот так:
ValueError: 7 is not in list
Как же бороться с падением программы при использовании .index()? Запросто! Мы должны сначала проверить, есть ли вообще такое значение в списке. И только убедившись, что есть — определяем его позицию:
x = [1, 2, 3, 4, 5] if 7 in x: print(x.index(7))
Теперь вы точно знаете, как искать элемент в коллекции 👍
Словами будем считать последовательности букв, разделённых пробелами. Знаки препинания не являются частью слова.
ПРИМЕР: если мы ввели строку
Моя головная боль: математика, физика, информатика.
программа должна вывести:
Моя боль физика головная математика информатика
1. Вводим строку:
s = input()
2. Чтобы разбить строку на элементы, используем метод .split(), причём без аргумента, потому что разбивать будем по пробелу.
wrds = s.split()
Переменная wrds теперь — это список строк. Каждая строка — слово, причём со знаком препинания в конце, если он там был. Например, «физика, „.
3. Давайте удалим последний символ каждой подстроки, если это знак препинания. Конечно, мы могли бы сделать это «в лоб»:
# для всех подстрок списка for i in range(len(wrds)): # если последний символ — знак препинания if wrds[i][-1] in '.,: ; -?! ': # заменяем строку на неё без последнего символа # (фактически ДО последнего символа) wrds[i] = wrds[i][: -1]
Но во-первых, а вдруг там будет случайно затесавшаяся цифра или мы не все знаки препинания вспомнили (вот скобки, например, ещё могут быть).
А во-вторых, знак может быть и в начале слова — та же скобка.
Используем метод .isalpha(), который возвращает True, если аргумент состоит только из букв. И будем проверять с обоих концов слова:
for i in range(len(wrds)): if not(wrds[i][0].isalpha()): wrds[i] = wrds[i][1:] if not(wrds[i][-1].isalpha()): wrds[i] = wrds[i][: -1]
4. Теперь бы надо отсортировать список строк. Но если мы будем делать это запросто:
wrds.sort()
получим (естественно!) сортировку по алфавиту, а это не то, что нам нужно.
Вспомним, что у метода .sort() есть параметр key, позволяющий сортировать элементы списка как угодно: хоть по второму символу строк, хоть по остатку от деления чисел на 11.
Причём мы можем функцию-ключ сортировки сделать отдельной функцией, вот так:
def key_func(x): return len(x)
А можем использовать лямбда-функцию прямо в вызове метода.
Лямбда-функции (напомню) — это крохотные функции без имени, которые реализуются прямо там, где используются.
Наша сортировка по длинам строк будет выглядеть так:
wrds.sort(key=lambda x: len(x))
Параметр лямбда-функции х — это элемент списка, для которого вызывается .sort(). То есть в нашем случае — строка.
Что возвращает функция-ключ сортировки — по тому и сортируем. Здесь — по длине строк.
5. Осталось вывести наши строки. Можно, конечно, сделать это попросту:
for x in wrds: print(x)
А можно использовать чуть более мудрёный, но краткий функциональный подход и записать так:
[print(x) for x in wrds]
Результат получим один и тот же!
Осталось переписать программу полностью и можно 💥 сдавать лабу 😉
Код программы:
s = input() # разбиваем строку на слова wrds = s.split() # для всех подстрок списка for i in range(len(wrds)): # если последний символ - знак препинания if wrds[i][-1] in '.,:;-?!': # заменяем строку на неё без последнего символа # (фактически ДО последнего символа) wrds[i] = wrds[i][:-1] # удаляем начальные и конечные знаки # препинания из каждого слова for i in range(len(wrds)): if not(wrds[i][0].isalpha()): wrds[i] = wrds[i][1:] if not(wrds[i][-1].isalpha()): wrds[i] = wrds[i][:-1] # сортируем список по длинам строк wrds.sort(key=lambda x: len(x)) # выводим по одному слову на строке [print(x) for x in wrds]
Или можете скачать готовым файликом 🔽🔽🔽
Разработка прикладного программного обеспечения на языке Python с применением библиотеки Qt (PySide6), СУБД PostgreSQL и других технологий
Разработка прикладного программного обеспечения на языке Python с применением библиотеки Qt (PySide6), СУБД PostgreSQL и других технологий.
Разработка прикладного программного обеспечения на языке Python с применением библиотеки Qt (PySide6), СУБД PostgreSQL и других технологий.
Разработка прикладного программного обеспечения на языке Python с применением библиотеки Qt (PySide6), СУБД PostgreSQL и других технологий.
Эпизод 6. Объектные модели и специальные методы.
Часть 2. Модель "Генератор и итератор".
Разработка прикладного программного обеспечения на языке Python с применением библиотеки Qt (PySide6), СУБД PostgreSQL и других технологий