Четвърта задача
Публикувано на 20.03.2007 23:18 от Стефан
Последна промяна на 03.04.2007 1:11
Тази публикация е от предишно издание на курса, моля не разчитайте на актуалността на информацията.
Краен срок: 4 Април 2007, 19:00 часа
Тема на форумите с въпроси
Формуляр за изпращане
Да се напише клас представящ интервал от числа (с име Interval
), който да отговаря на следните изисквания.
Концептуални изисквания:
- Да работи с числа с плаваща запетая (
float
), но да е толерантен и към цели числа (т.е., да може да приема иint
иlong
, преобразувайки ги доfloat
). - Интервалите да са затворени.
- Да поддържа отворени интервали към безкрайност, т.е. (-∞, 3], [4, +∞) и (-∞, +∞).
- Да поддържа ред операции, които са изброени по-долу.
Изисквания към кода:
- Класът да се казва
Interval
. - Да има двуаргументен конструктор, в който първият аргумент да е лявата граница, а втория - дясната. Ако вместо число се подаде
None
, тогава това да се третира като безкрайност. - Да дефинира
repr
по смислен начин - така чеeval(repr(Interval))
да работи, ако иметоInterval
съответства на вашия клас (т.е. да връща неща от рода наInterval(0, 10
).
Да дефинира следните методи:
leftOpen()
- да връщаTrue
илиFalse
в зависимост от това дали интервала е отворен отлявоrightOpen()
- да връщаTrue
илиFalse
в зависимост от това дали интервала е отворен отдясноopen()
- връщаTrue
ако интервала е отворен или от ляво, или от дясно, или от двете страни. ИначеFalse
left()
- да връща границата на интервала отляво. В случай чеleftOpen()
връщаTrue
, този метод няма да се вика от клиентски код.*right()
- да връща границата на интервала отляво. В случай чеrightOpen()
връщаTrue
, този метод няма да се вика от клиентски код.*expand(left=0, right=0)
- разширява интервала от ляво или от дясно със съответната стойност. Аргументите са незадължителни.Interval(0, 10).expand(-1, 1)
връща нов интервалInterval(1, 11)
. Ако от ляво или отдясно имате безкрайност, разширяването не се отразява по никакъв начин на тази страна. Ако интервал е невалиден (left() > right()
), можете да върнетеNone
или да хвърлите грешка (напр.ValueError
).intersect(interval)
- взема интервал и връща сечението на двата интервала. Ако то е празно, връщаNone
.intersects(intarval)
- взема интервал и връща дали той се пресича с този, на който метода е извикан.True
илиFalse
.contains(interval)
- връщаTrue
илиFalse
в зависимост от това дали подадения като аргумент интервал се съдържа в този, върху който е извикан метода. Всеки интервал съдържа себе си.Interval(0, 10).contains(2, 5) == true
.
Операции, които Interval
трябва да дефинира.
==
и!=
- Два интервала са равни, ако граничните им стойности са равниin
(n in interval
) - Ако n е число, оператора връща дали то се съдържа в интервала; ако n е интервал, то оператора връща дали interval съдържа изцяло n.hash
- да има валидна хеш функция (дори тя да не е много ефективна)len(interval)
- връща дължината на интервала като цяло число, загръглено нагоре. При безкрайни интервали дължината е 0. Т.е.,len(Interval(0, 3.5)) == 4), len(Interval(1, 2)) == 1, len(Interval(0, None)) == 0
.събиране (+)
- Ако два интервала се пресичат, сбора им е най-малкия интервал който обхваща и двата. Например,Interval(0, 10) + Interval(5, 15) == Interval(0, 15)
. Ако не се пресичат, хвърляйтеValueError
изваждане (-)
(interval1 - interval2
) - връща интервал, който съдържа всички стойности на interval1, които не се съдържат в interval2 (без граничните стойности). Ако това изваждане би довело до два интервала, хвърляйтеValueError
. Ако ще доведе до празен интервал, връщайтеNone
. НапримерInterval(0, 10) - Interval(0, 5) == Interval(5, 10)
;Interval(1, 2) - Interval(0, 10) == None
;Interval(0, 10) - Interval(3, 4)
хвърляValueError
.сравняване (<, >, <=, >=)
- Дефинирайтеa < b
като „b съдържа a“ (аналогичноa > b
като „a съдържа b„). Т.е., един интервал е по-голям от друг, ако го съдържа изцяло. Два интервала са равни, ако съвпадат.a <= b
акоa < b
илиa == b
. Обърнете внимане, че има интервали които са несравними -Interval(0, 10)
иInterval(5, 20)
.<, <=, >, >=
и==
връщатFalse
за тези два интервала.
ВАЖНО: Нито един от методите не е мутатор, т.е., навсякъде връщайте нов интервал.
Забележки:
* Това значи, че ако един интервал е отворен отляво, не е легално да се вика метода му left()
. Можете спокойно да връщате None
, да хвърляте изключение или каквото си искате. Нещо като leftOpen() == false
е precondition за извикване на left()