diff --git a/.DS_Store b/.DS_Store index 5008ddf..3a9c6e7 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/sl4964/.project b/sl4964/.project new file mode 100644 index 0000000..f7f2218 --- /dev/null +++ b/sl4964/.project @@ -0,0 +1,17 @@ + + + sl4964 + + + + + + org.python.pydev.PyDevBuilder + + + + + + org.python.pydev.pythonNature + + diff --git a/sl4964/.pydevproject b/sl4964/.pydevproject new file mode 100644 index 0000000..c3434da --- /dev/null +++ b/sl4964/.pydevproject @@ -0,0 +1,8 @@ + + + +/${PROJECT_DIR_NAME} + +python 3.0 +Default + diff --git a/sl4964/Errors.py b/sl4964/Errors.py new file mode 100644 index 0000000..8f71da4 --- /dev/null +++ b/sl4964/Errors.py @@ -0,0 +1,16 @@ +''' +This module defines errors +@author: ShashaLin +''' +class Errors(Exception): + pass + +class InputError(Errors): + def __init__(self, message): + self.message = message + + +class MergeError(Errors): + def __init__(self): + self.message = 'The intervals cannot be merged: they are neither overlapping nor adjacent.' + \ No newline at end of file diff --git a/sl4964/assignment7.py b/sl4964/assignment7.py new file mode 100644 index 0000000..f242a89 --- /dev/null +++ b/sl4964/assignment7.py @@ -0,0 +1,37 @@ +''' +This is the main program that interacts with the user. + +@author: ShashaLin +''' +from funcs import interval, mergeIntervals, mergeOverlapping, insert +from Errors import InputError, MergeError +i = 0 +while i < 1: + interv = input('List of intervals?') + + try: + intv = [] + inter2 = interv.split(', ') + for i in inter2: + intv.append(interval(i)) + i =+ 1 + except: + print('List of intervals does not follow the right format. Make sure every item is a correct interval, and each item is joined by a comma and space') + +inp = 0 + + + +while inp != 'quit': + inp = input('Interval?') + if inp != 'quit': + try: + interval(inp) + interv = insert(interv, inp) + print(interv) + + except InputError: + print('Interval of incorrect format. Input has to include two numbers, with a comma and no space in between.') + + + diff --git a/sl4964/funcs.py b/sl4964/funcs.py new file mode 100644 index 0000000..f1861ed --- /dev/null +++ b/sl4964/funcs.py @@ -0,0 +1,213 @@ +''' +This is where all the functions and classes are defined. +@author: ShashaLin +''' +from Errors import MergeError, InputError + +lowerbounds = ('(', '[') +upperbounds = (')', ']') + + +class interval(object): + + 'The interval class represents the range of integers between two bounds.' + + def __init__(self, readin): + '''the constructor ensures the argument for class interval is + of correct format''' + + try: + li = readin.split(',') + except: + InputError('input has to include two numbers, with a comma in between.') + if ' ' in list(readin): + raise InputError('space in interval is not allowed.') + + if li[0][0] not in lowerbounds or li[-1][-1] not in upperbounds: + + raise InputError ('Your input is not of the right format.\ + \n The input has to be a correct mathematical representation\ + of an interval with either closed or open bounds. \n \ + Example: [5, 7)') + + elif li[0][0] == lowerbounds[1] and li[-1][-1] == upperbounds[1] and int(li[0][1:]) > int(li[-1][: -1]): + raise InputError('The lower bound has to be smaller or equal to the upper bound for inclusive intervals.') + + elif li[0][0] == lowerbounds[0] and li[-1][-1] == upperbounds[0] and int(li[0][1:]) >= int(li[-1][: -1]) - 1: + raise InputError('The lower bound has to be smaller than upper bound - 1f or intervals with exclusive bounds on both sides') + + elif (li[0][0] == lowerbounds[0] and li[-1][-1] == upperbounds[1] and int(li[0][1:]) >= int(li[-1][: -1])) \ + or (li[0][0] == lowerbounds[1] and li[-1][-1] == upperbounds[0] and int(li[0][1:]) >= int(li[-1][: -1])): + raise InputError('The lower bound has to be smaller than upper bound if one bound is inclusive and the other inclusive.') + + else: + self.interva = readin + return None + + def __str__(self): + return "{}".format(self.interva) + +def mergeIntervals(inta, intb): + + int1 = inta.split(',') + int2 = intb.split(',') + + int1a = int(int1[0][1:]) #lower number for int1 + int1b = int(int1[-1][: -1]) #upper number for int1 + int2c = int(int2[0][1:]) #lower number for int2 + int2d = int(int2[-1][: -1]) #upper number for int2 + + int1b1 = int1[0][0] #lowerbound for int1 + int1b2 = int1[-1][-1] #upperbound for int1 + + int2b1 = int2[0][0] #lowerbound for int1 + int2b2 = int2[-1][-1] #upperbound for int1 + + if int1a != int1b: + if int1b == int2c: + if int1b2 ==upperbounds[0] and int2b1==lowerbounds[0]: + raise MergeError() + else: intNew = int1[0] + ',' + int2[-1] + + elif int1b - int2c ==-1: + if int1[-1][-1] == upperbounds[1] and int2[0][0]== lowerbounds[1]: #and\ + #int(int1[-1][: -1]) - int(int2[0][1:]) < -1: + intNew = int1[0] + ',' + int2[-1] + + elif int1[-1][-1] == upperbounds[1] and int2[0][0]== lowerbounds[1]: #and int(int1[-1][: -1]) - int(int2[0][1:])\ + #== -1 and int1[0][0] != lowerbounds[0] and int1[0][0] != upperbounds[0]: + intNew = int1[0] + ',' + int2[-1] + + else: raise MergeError() + + elif int1b - int2c < -1: + raise MergeError() + + else: + if int2c > int1a: + if int2d == int1b: + if int2b2 == int1b2 == upperbounds[0]: + intNew = inta + elif int2b2 == upperbounds[0] and int1b2 == upperbounds[1]: + intNew = inta + elif int2b2 == upperbounds[1] and int1b2 == upperbounds[0]: + intNew = int1[0] + ',' + int2[1] + else: + intNew = inta + + elif int2d < int1b: + intNew = inta + else: + intNew = int1[0] + ',' + int2[1] + + elif int2c < int1a or (int2c == int1a and int1b1 != lowerbounds[1]): + if int2d < int1a - 1: + raise MergeError() + + elif int2d == int1a - 1: + if int2b2 == upperbounds[1] and int1b1 == lowerbounds[1]: + intNew = int2[0] + ',' + int1[1] + else: + raise MergeError() + + elif int2d == int1a: + if int2b2 == upperbounds[0] and int1b1 == lowerbounds[0]: + raise MergeError() + else: + intNew = int2[0] + ',' + int1[1] + + elif int1a < int2d and int2d < int1b: + intNew = int2[0] + ',' + int1[1] + + + elif int2d == int1b: + if int2b2 == upperbounds[0]: + intNew = int2[0] + ',' + int1[1] + else: + intNew = int2[0] + ',' + int2[1] + + else: + intNew = intb + + else: + if int2d < int1a - 1: + raise MergeError() + + elif int2d == int1a - 1: + if int2b2 == upperbounds[1] and int1b1 == lowerbounds[1]: + intNew = int1[0] + ',' + int1[1] + else: + raise MergeError() + + elif int2d == int1a: + if int2b2 == upperbounds[0] and int1b1 == lowerbounds[0]: + raise MergeError() + else: + intNew = int1[0] + ',' + int1[1] + + elif int1a < int2d < int1b: + intNew = int1[0] + ',' + int1[1] + + + elif int2d == int1b: + if int2b2 == upperbounds[0]: + intNew = int1[0] + ',' + int1[1] + else: + intNew = int1[0] + ',' + int2[1] + else: + intNew = intb + + else: + if int2c == int2d: + if int1b == int2c: + intNew = inta + else: + raise MergeError() + else: + if int1b == int2c: + intNew = int1[0] + int2[-1] + elif int2d > int1b > int2c: + intNew = intb + elif int2d == int1b: + intNew = int2[0] + ',' + int1[1] + else: + if int2b2 == upperbounds[0]: + raise MergeError() + else: + if int1b == int2d + 1: + intNew = int2[0] + ',' + int1[1] + else: + raise MergeError() + + + return intNew + + +def mergeOverlapping (inter): + inter = inter.split(', ') + inter.sort(key = lambda x: int(x.split(',')[0][1:])) + + i = 0 #counter or the list of intervals + originalLength = len(inter) + while i < originalLength - 1: + #print(intervals) + try: + + inter.append(mergeIntervals(inter[i], inter[i+1])) + + del(inter[i]) + del(inter[i]) + + inter.sort(key = lambda x: int(x.split(",")[0][1:])) + + except: + i = i + 1 + inter = ', '.join(inter) + return inter + +def insert(inter1, newint): + inter1 = inter1 + ', ' + newint + + result = mergeOverlapping(inter1) + + return result \ No newline at end of file diff --git a/sl4964/tests.py b/sl4964/tests.py new file mode 100644 index 0000000..a8e1db3 --- /dev/null +++ b/sl4964/tests.py @@ -0,0 +1,36 @@ +''' +This is the module for tests. +@author: ShashaLin +''' +import unittest +from funcs import interval, mergeIntervals, mergeOverlapping, insert +from Errors import InputError, MergeError +class Test(unittest.TestCase): + + def testInterval(self): + self.assertIsInstance(interval('[-10,-7]'), interval) + self.assertIsInstance(interval('(-4,1]'), interval) + self.assertIsInstance(interval('[3,6)'), interval) + self.assertIsInstance(interval('(8,12)'), interval) + self.assertRaises(InputError, interval, '(8,-12)') + self.assertRaises(InputError, interval, '(-1,-1)') + + def test_mergeIntervals(self): + self.assertEqual(mergeIntervals('(-7,-6]', '[-5,1)'), '(-7,1)' ) + self.assertEqual(mergeIntervals('(-7,-6]', '(-6,2]'), '(-7,2]' ) + self.assertEqual(mergeIntervals('[110,720)', '(719,730]'), '[110,730]' ) + self.assertRaises(MergeError, mergeIntervals, '[0,3)', '[4,7]') + + def test_mergeOverlapping(self): + self.assertEqual(mergeOverlapping('[-10,-7], (-4,1], [3,6), (8,12), [15,23], [4,8]'), \ + '[-10,-7], (-4,1], [3,12), [15,23]') + self.assertEqual(mergeOverlapping('[-3,5), (5,10], [10,17), [17,23]'), \ + '[-3,5), (5,23]') + + def test_insert(self): + self.assertEqual(insert('[0,9), [11,27)', '(8,10]'), '[0,27)') + self.assertEqual(insert('[4,6), (7,12]', '(13,14]'), '[4,6), (7,12], (13,14]') + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file