Домашняя работа по курсу
- Домашняя работа нужна в первую очередь для того, чтобы доказать себе и экзаменатору, что ты освоил тему.
- Задача считается сданной в срок, если в ejudge (см. ниже) зафиксирована посылка решения, успешно принятого системой (результат OK) до наступления срока сдачи.
- Количество (точнее, процент от общего числа) домашних задач, сданных в срок, будет учитываться при допуске к экзамену.
Если решение не проходит проверку, придумайте побольше своих тестов. Напишите генератор входных данных (модуль random вам в помощь).
Домашняя работа — не олимпиада. Если что-то не получается, всегда можно спросить (FrBrGeorge, PavelSutyrin, знакомого питониста).
- Текст задач домашней работы — повод для разговора на экзамене.
Как сдавать домашнюю работу
Зарегистрироваться на факультетском Ejudge
- Выбрать 5-й «турнир» (UNИX Python 2014)
- Возможно, придётся пойти по ссылке «Confirm registration» («Подтвердить регистрацию»)
- Возможно, придётся пойти по ссылке «Participate» («Участвовать»)
- Выбрать соответствующую задачку
Задачу под названием «1» решать не надо
- Загрузить решение
- Прежде, чем загружать решение, убедитесь, что оно правильное. Не надо вместо этого делать много различных вариантов решения в надежде, что какой-то один всё-таки пройдёт тесты.
Если возникают вопросы — спрашивайте, для этого есть и интерфейс eJudge, и почта (FrBrGeorge, PavelSutyrin)
- Дождаться конца проверки (как правило, несколько секунд) и обновить страницу браузера
Как оформлять решение
По умолчанию, т. е. если иное не указано отдельно:
- программа читает со стандартного ввода и выводит на стандартный вывод
- вводимые данные корректны
⇒ Для ввода можно пользоваться input() (без строки-подсказки), а для вывода — print.
Сводный список домашних заданий
- Установить Python и поработать в командной строке
Прочитать и отщёлкать вторую главу учебника (имеется перевод)
Прочитать про настройку командной строки в учебнике
- Настроить что-нибудь
Настроить что-нибудь на Windows
Разобраться с rlcompleter и настроить что-нибудь с его помощью
См. ../HomeworkRules
Установить и настроить подходящий текстовый редактор или IDE (пример: настройка Geany)
Ввести два объекта Python и вывести первый ненулевой из них. Если оба нулевые, вывести NO.
[] 123
123
(Methods) Вывести в столбик поля объекта
Ввести объект Python и вывести в столбик имена тех его полей (независимо от типа ⇒ в т. ч. методов), которые не начинаются на «_»
1
bit_length conjugate denominator imag numerator real
(SecondMax) Найти второй максимум
Ввести список и вывести второй максимум этого списка, т. е. элемент a∈S : ∃ b∈S : b>a и a⩾c ∀c∈S, c≠b. Если второго максимума нет, вывести NO.
3,4,5,6,7
6
В первой строке ввести координаты центра круга и его радиус (числа x, y, r через запятую). Во второй строке ввести координаты точек (чётное количество чисел через запятую: x1, y1, x2, y2, ... xk, yk). Вывести YES, если все точки принадлежат кругу и NO, если не все.
x, y, r
YES
- Прочитать:
Неформальное введение в Python (introduction.html) в учебнике
Числовые типы Python в справочнике
Структуры данных (datastructures.html) в учебнике
Последовательности в справочнике
Передать input() что-нибудь действительно нехорошее
(ParallelSegments) Параллельные отрезки
Ввести восемь чисел через запятую — целочисленные координаты 4-х попарно несовпадающих точек A1, A2, A3 и A4: X1, Y1, X2, Y2, X3, Y3, X4, Y4. Вывести YES, если прямая A1A2 параллельна прямой A3A4 (или совпадает с ней), и NO — если не параллельна.
1,2,7,14,8,8,18,28
YES
(SectionShuffle) Перетасовать кортеж
Ввести последовательность A объектов Python через запятую и вывести кортеж, состоящий из элементов последовательности, стоящих на чётных местах — в обратном порядке (включая A[0]), после которых идут элементы последовательности, стоящие на нечётных местах.
'0', 1, 2, '3', 4, 5, '6', 7, 8, '9', 10, 11
(10, 8, '6', 4, 2, '0', 1, '3', 5, 7, '9', 11)
(RepeatedString) Строка — повторение подстроки
Ввести непустую строку s. Найти такое наибольшее число k и такую строку t, что s совпадает со строкой t, выписанной k раз подряд. Вывести k.
abcabcabcabc
4
Ввести заданный построчно лабиринт размером N×N. Каждая из N строк ввода содержит N символов: «.» — проходимый участок и «#» — непроходимый. Левый верхний и правый нижний участки лабиринта проходимы. С одного проходимого участка можно попасть на соседний либо по вертикали, либо по горизонтали. Проверить, можно ли попасть из левого верхнего участка в правый нижний, и вывести YES, если можно, и NO, если нельзя.
........... .#.###.###. .#...#...#. .#.#####.#. .#.....#.#. ##.###.###. .....#.#.#. .#.###.#.## .#...#.#... ##.#.###.## ...#.......
YES
ввести W, H — размеры лабиринта и вывести представление достаточно случайного проходимого лабиринта для предыдущей задачи (обратите внимание на нескучные обои красивые неслучайные стены )
- Прочитать в учебнике
про множества и словари (datastructures.html), и про них же в документации
про форматирование строк (inputoutput.html) и про это же в документации
Прочитать в документации про строковые методы
(ReqSum) Сумма подпоследовательности
Ввести число N, а на следующей строке — последовательность натуральных чисел через запятую. Проверить, является ли N суммой не более, чем 10 каких-либо элементов последовательности, и вывести YES или NO в зависимости от результата.
21 1,2,3,4,5,6,7
YES
(DiffLet) Количество разных символов
Ввести строку (слова, разделённые пробелами), и вывести через пробел вначале слова, состоящие из повторения единственного символа (если таковые имеются), затем — слова, образованные всего из двух символов в любом количестве и сочетании, затем — из трёх и т. д. Слова с одинаковым количеством символов выводить в порядке их появления в строке.
sorted(iterable, cmp=None, key=None, reverse=False) --> new sorted list
--> new list sorted key=None, cmp=None, reverse=False) sorted(iterable,
(PopularWord) Самое популярное слово
Ввести построчно текст, состоящий из пробелов, переводов строки и латинских букв, и заканчивающийся пустой строкой. Вывести слово, которое чаще других встречается в тексте, если оно такое одно, и ---, если таких слов несколько.
Sed tempus ipsum quis eros tempus lacinia Cras finibus lorem ut lacinia egestas nunc nibh iaculis est convallis tincidunt mi mi sed nisl Sed porttitor aliquam elit ullamcorper tincidunt arcu euismod quis Mauris congue elit suscipit leo varius facilisis Cras et arcu sodales laoreet est vitae pharetra orci Integer eget nulla dictum aliquet justo semper molestie neque Maecenas bibendum lacus tincidunt auctor varius purus felis ullamcorper dui et laoreet ligula ex et risus Donec eget fringilla nibh Cras congue tincidunt accumsan Maecenas euismod eleifend elit ut rhoncus tortor sodales a Cras egestas finibus lorem non tempor tincidunt aera
tincidunt
(MultTable) Таблица умножения на N
Ввести через запятую M и N и вывести таблицу умножения от M×1 до M×N в столбик, где K-я строчка имеет вид __P_=__K_*_M. Между элементами стоят символы подчёркивания, причём перед P может быть ноль или больше подчёркиваний, а перед K — одно или больше, в остальных случаях подчёркивание одно. В результате символы = и * должны стоять друг под другом.
7,11
_7_=__1_*_7 14_=__2_*_7 21_=__3_*_7 28_=__4_*_7 35_=__5_*_7 42_=__6_*_7 49_=__7_*_7 56_=__8_*_7 63_=__9_*_7 70_=_10_*_7 77_=_11_*_7
- Прочитать:
Про random в документации
Про исключения в учебнике (errors.html) и в документации
Про генераторы в учебнике, pep-0255, pep-0342
(GenMinMax) Найти минимум и максимум произвольной функции на целочисленном отрезке
Ввести строку — произвольное выражение Python, в котором могут дополнительно встречаться функции из модуля math и переменная x. На следующей строке ввести через запятую целые числа A и B (выражение должно быть определено как минимум на A или на B). Вывести через пробел минимальное и максимальное значение выражения на всех допустимых целых x, принадлежащих отрезку [A,B]. Точностью вычислений не управлять.
(x**5+1)/(factorial(x)-720) -10,10
-6 3
(RandomGen) Найти число в псевдослучайной последовательности
Ввести через запятую натуральные числа X0, a, c и m (c также может быть равно 0); на следующей строке ввести натуральное число Y. Использовать генератор последовательности псевдослучайных чисел линейным конгруэнтным методом и проверить, встречается ли Y в последовательности Xn+1 = (aXn + c) mod m (это и есть упомянутый метод ). Вывести YES, если встречается и NO, если нет.
7,7,7,10 6
YES
(DoPolIZ) Вычислить выражение в польской инверсной записи
Ввести целочисленное выражение в польской инверсной записи, в котором могут содержаться разделённые пробелом целые числа и 4 знака арифметики: "+", "-", "*" и "/". Если выражение можно вычислить, вывести результат. В противном случае (синтаксическая ошибка, в стеке остался не один элемент, и т. п.) вывести ERROR.
234 345 456 + + 5 /
207
(PaidStairs) Классическая задача динамического программирования «Платная лестница»
Наступить на k-ю ступень лестницы A стоит Ak монет. Ввести через запятую «цены» ступеней A, и на следующей строке — ширину шага S (все числа натуральные) и вывести минимальную стоимость пути с земли до последней ступени (на которую наступать обязательно), при условии, что идти можно только вверх и перешагивать можно не более, чем через S-1 ступень.
5, 3, 6, 1, 1, 2, 3, 4, 7, 5, 5, 7, 1, 1, 4, 6, 3, 4, 7, 4, 2 4
14
- Прочитать:
Про файловые объекты в учебнике (inputoutput.html) и в документации
Про сериализацию в документации по pickle
- Опционально почитать документацию по всем упомянутым пакетам
Применить pylama (или pylint + falkes) к своему коду и помедитировать над выдачей
Задачи для EJudge не могут включать в себя работу с ОС или модулями, так что просто упражнения:
(MaxSubst) Подстрока максимальной длины из разных букв
Ввести строку и вывести ближайшую к началу подстроку максимальной длины, содержащую только различные символы.
qweqweASDFGHASDFGASasdfghas123
DFGASasdfgh
(GuessSigns) Вставить знаки в целочисленное выражение
Ввести последовательность натуральных чисел через пробел (не более 12), и вывести YES, если можно ли между этими числами вставить произвольные знаки сложения или вычитания и один знак "=", чтобы получилось равенство. Вывести NO, если нельзя. Унарные операции и пропуск знака не допускаются.
123 234 345 12
YES
(ConstructIt) Проверить, можно ли собрать агрегат согласно инструкции
Первая строка ввода — правило сборки агрегата вида «название_агрегата деталь1 деталь2 …», в ней сказано, из каких деталей можно собрать агрегат. Последующие строки ввода — либо аналогичные правила сборки деталей вида «деталь1 деталь2 …», либо состоят из одного слова «деталь» — в знак того, что такие детали есть на складе. Каждая деталь собирается не более, чем единственным способом. Последняя строка пустая. Вывести YES, если из деталей на складе можно собрать агрегат, и NO, если нельзя.
Choo qw er ty ui qw er ty er ty ui ty ui
YES
(SubModules) Ввести имя модуля и посчитать, сколько подмодулей в нём содержится
Ввести имя модуля и посчитать, столько подмодуелй он содержит (солько объектов модуля сами являются модулями). Если имя не соответствует никакому модулю, вывести -1.
os
5
- Прочитать:
(одним глазом) functions.html — список стандартных функций
Про функциональное программирование в учебнике
Мнение Гвидо по ссылкам выше
Документацию по functools.html и itertools.html
Документацию по collections.html и heapq.html
Про модули и пакеты в учебнике (modules.html)
(KdigNbase) K-значные N-ричные
Ввести через запятую K и N (1<N<17), вывести в столбик все K-значные N-ричные числа в порядке возрастания (латинские буквы для цифр — большие, незначащие нули или пробелы не считаются).
2,4
10 11 12 13 20 21 22 23 30 31 32 33
(ParamForm) Параметрическая формула
Первая строка содержит Python-совместимую формулу, в которой могут присутствовать названия переменных и элементы модуля math. В следующей строке через пробел в виде переменная=значение или переменная=начало_диапазона,конец_диапазона указаны допустимые целочисленные значения переменных (целочисленный диапазон включает и начальное, и конечное значения). Вывести наибольшее значение формулы на всех допустимых целочисленных значениях переменных.
Param**2+Fun/6-Result+1 Param=3 Fun=-21,45 Result=5,15
12
Ввести строку (слова через пробел), вывести её таким образом, что все вхождения слов, кроме первого, опущены. В случае, если слово встречалось в исходной строке более одного раза, после слова в скобках без пробела следует номер — позиция последнего вхождения.
qwe sdf tyu qwe sdf try sdf qwe sdf rty sdf wer sdf wer
qwe(7) sdf(12) tyu try rty wer(13)
(ByteReverse) Байты задом наперёд
Ввести через запятую строку чисел типа «4-байтовое знаковое целое», переставить байты в занимаемой ими совместно памяти в обратном порядке, вывести в виде списка объектов типа «4-байтовое знаковое целое». Обратите внимание на то, что и «int», и «long int» на разных архитектурах имеют разную длину.
-12,4,-345345345,12345
[959447040, -1083020565, 67108864, -184549377]
- Прочитать:
Про модули в учебнике (modules.html
Про классы в учебнике (classes.html)
Про спецметоды в справочнике ( или пока не читайте про метаклассы, или берегите мозг! вас предупредили!)
(CompareFields) Сравнение полей
Реализовать класс Comparator, содержащий только поле value и метод compare, возвращающий результат сравнения value с полем value любого другого объекта (аналогичный работе стандартной функции cmp()). Если такого поля нет, метод возвращает 1.
-1
(SimpleVector) Вектора на плоскости
Реализовать класс Vector, позволяющий
- задавать двумерный вектор (из двух чисел)
- вычислять вектор — сумму двух векторов
- вычислять вектор — результат умножения вектора на число (или числа на вектор)
- скалярно умножать вектор на вектор
преобразовывать вектор в строку вида |x,y|
|1,2| |4,6| 11 |7,14|
(PrimitiveDot) Точки в N-мерном пространстве
Реализовать клаcc Dot, позволяющий:
Задавать точку в N-мерном пространстве (с помощью N чисел, где N>0)
Преобразовывать точку в строку вида «X1,X2,…,XN»
Вычислять расстояние (distance()) между двумя точками пространства одинаковой размерности
Вычислять точку (middle()) — середину отрезка между двумя точками пространства одинаковой размерности
При попытке работы с такими же точками пространства, но разной размерности порождать исключение ValueError
1,2,3 3.464 2.0,3.0,4.0 1,2 ERROR
Реализовать класс Vovel, у объекта которого можно получить значение любого поля, если имя этого поля состоит только из маленьких гласных латинских букв. Значение это — строка, совпадающая с именем поля, только состоящая из больших латинских букв. В противном случае поведение объекта должно быть естественным (вызывть исключение AttributeError, как минимум с тем же сообщением, что и «естественный» AttributeError в случае несуществующего поля). Реализовывать что-то, кроме получения значения поля, не надо.
A = mod.Vovel() print A.aoao try: print A.field except AttributeError, msg: print "ERROR",msg
AOAO ERROR Vovel instance has no attribute 'field'
- Прочитать:
Раздел Data model (весь, можно несколько раз)
- Всё по ссылкам выше
(SelfishTuple) Выворачиваемый кортеж
Определить класс MTuple, проксирующий тип tuple, с добавлением в него единственной операции — унарного минуса (операция возвращает MTuple с элементами в обратном порядке). Прочие операции также должны возвращать MTuple вместо tuple.
c=mod.MTuple(range(10)) print -(-c[2:6]+c[-1:2:-2]) print -c[7:9]+("Bdyshch","Bdyshch") print {-c[3:5]:"QQ"}
(3, 5, 7, 9, 2, 3, 4, 5) (8, 7, 'Bdyshch', 'Bdyshch') {(4, 3): 'QQ'}
Создать три класса:
Trigon, обозначающий треугольник:
- заводится по трём сторонам
имеет методы square() (площадь) и perimeter() (периметр)
Pea, обозначающий грушу круг
заводится (NB!) по трём сторонам вписанного треугольника
имеет методы square() и perimeter()
TrigonPea (унаследованный от Trigon и Pea), обозначающий треугольную грушу
- заводится по трём сторонам
- периметр и площадь равны периметру и площади треугольника
имеет метод volume(), равный произведению периметра треугольника на площадь описанного круга
Неравенство треугольника проверять не надо.
t=mod.Trigon(3,4,5) p=mod.Pea(3,4,5) z=mod.TrigonPea(3,4,5) print "{:.6f}".format(t.square()) print "{:.6f}".format(t.perimeter()) print "{:.6f}".format(p.square()) print "{:.6f}".format(z.volume()) print "{:.6f}".format(z.square())
6.000000 12.000000 19.634954 235.619449 6.000000
Очередная алгоритмическая задачка, поупражнять мозг:
(QuadChain) Прямоугольник из цепи
Цепь состоит из прямых отрезков различной целой ненулевой длины, соединённых попарно в замкнутую ломаную. Ввести строку целых чисел через запятую — длины отрезков цепи. Вывести YES, если цепь можно превратить в прямоугольник с вершинами в четырёх различных вершинах ломаной. Если нельзя, вывести NO.
1, 3, 2, 2, 4, 4
YES
(необязательное)
FunctionCachier. Написать декоратор function_cachier, который возвращает функцию, значения которой не вычисляются заново при повторных обращениях.
def f1(n): print 'f1 called' return n*n @mod.function_cachier def f2(n): print 'f2 called' return n*n*n print len([ f1(n) for n in range(3)]) print len([ f1(n) for n in range(3)]) print len([ f2(n) for n in range(4)]) print len([ f2(n) for n in range(4)])
f1 called f1 called f1 called 3 f1 called f1 called f1 called 3 f2 called f2 called f2 called f2 called 4 4
- Усложнение: научить его работать с рекурсивными функциями.
WithFunctionCachier. Из декоратора FunctionCachier сделать полноценный ContextManager:
def f1(n): print 'f1 called' return n*n def f2(n): print 'f2 called' return n*n*n print len([ f1(n) for n in range(3)]) with mod.with_function_cachier(f2) as f: print len([ f(n) for n in range(5)])
f1 called f1 called f1 called 3 5
- Усложнение: Сделать его повторно используемым между вызовами with, чтобы сохранялся однажды накопленный кэш функций.
Усложнение: Сделать его повторно используемым между вызовами программы
Include: Ничего не найдено по регулярному выражению «== Д/З ==$».
Что дальше?
Мелочи и подчистка
eval() и exec(), полная версия (simple_stmts.html, functions.html, functions.html)
«TypeError: media_is_eligible() takes at least 2 arguments (2 given)»
- …
Вопросы быстродействия
- 1 ms vs. 1 µs
- Быстродействие и ЗБЧ
- Быстродействие и вычислительная сложность
- Быстродействие и дзен Python (см. далее)
- Действительные случаи потери быстродействия
Python Patterns - An Optimization Anecdote (довольно старое эссе Гвидо, здесь он ещё любил reduce() ):
Rule number one: only optimize when there is a proven speed bottleneck. Only optimize the innermost loop. (This rule is independent of Python, but it doesn't hurt repeating it, since it can save a lot of work. )
- Small is beautiful. Given Python's hefty charges for bytecode instructions and variable look-up, it rarely pays off to add extra tests to save a little bit of work.
Use intrinsic operations. An implied loop in map() is faster than an explicit for loop; a while loop with an explicit loop counter is even slower.
- Avoid calling functions written in Python in your inner loop. This includes lambdas. In-lining the inner loop can save a lot of time.
- Local variables are faster than globals; if you use a global constant in a loop, copy it to a local variable before the loop. And in Python, function names (global or built-in) are also global constants!
Try to use map(), filter() or reduce() to replace an explicit for loop, but only if you can use a built-in function: map with a built-in function beats for loop, but a for loop with in-line code beats map with a lambda function!
- Check your algorithms for quadratic behavior. But notice that a more complex algorithm only pays off for large N - for small N, the complexity doesn't pay off. In our case, 256 turned out to be small enough that the simpler version was still a tad faster. Your mileage may vary - this is worth investigating.
And last but not least: collect data. Python's excellent profile module can quickly show the bottleneck in your code. if you're considering different versions of an algorithm, test it in a tight loop using the time.clock() function.
Разбор каких-то задач?
Дзен Python
import this:
The Zen of Python, by Tim Peters (structured by FrBrGeorge CO)
- Beautiful is better than ugly.
- Explicit is better than implicit.
- Simple is better than complex.
- Complex is better than complicated.
- Flat is better than nested.
- Sparse is better than dense.
- Readability counts.
- Special cases aren't special enough to break the rules.
- Although practicality beats purity.
- Errors should never pass silently.
- Unless explicitly silenced.
- In the face of ambiguity, refuse the temptation to guess.
- There should be one — and preferably only one — obvious way to do it.
- Although that way may not be obvious at first unless you're Dutch.
- Now is better than never.
Although never is often better than right now.
- If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
- Namespaces are one honking great idea -- let's do more of those!
Дальнейшее движение
- Изучение алгоритмического программирования на Python:
Проект «Interactivepython»: Problem Solving with Algorithms and Data Structures и перевод (!): http://aliev.me/runestone/ (via Иван Морозов)
- Инструментальная разработка и промышленное программирование
- «Академическое» программирование
- Сам Python и его реализации
EE: import antigravity