Четвърта задача
Публикувано на 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ако интервала е отворен или от ляво, или от дясно, или от двете страни. ИначеFalseleft()- да връща границата на интервала отляво. В случай че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()