Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .DS_Store
Binary file not shown.
17 changes: 17 additions & 0 deletions sl4964/.project
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>sl4964</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.python.pydev.PyDevBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.python.pydev.pythonNature</nature>
</natures>
</projectDescription>
8 changes: 8 additions & 0 deletions sl4964/.pydevproject
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?eclipse-pydev version="1.0"?><pydev_project>
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
<path>/${PROJECT_DIR_NAME}</path>
</pydev_pathproperty>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 3.0</pydev_property>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
</pydev_project>
16 changes: 16 additions & 0 deletions sl4964/Errors.py
Original file line number Diff line number Diff line change
@@ -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.'

37 changes: 37 additions & 0 deletions sl4964/assignment7.py
Original file line number Diff line number Diff line change
@@ -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.')



213 changes: 213 additions & 0 deletions sl4964/funcs.py
Original file line number Diff line number Diff line change
@@ -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
36 changes: 36 additions & 0 deletions sl4964/tests.py
Original file line number Diff line number Diff line change
@@ -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()