def test_truncate(self): ''' Tests the truncate method from the tower class. Tests typical cases that the truncate method would be used for. The cases can be found in the Juypter Notebook section discussing the truncate method. Tests the result against the truncated tower it should generate if working properly. ''' grey_box = tower((2, 2), 4, 4) slash_box = tower((1, 1), 2, 6) dash_box = slash_box.truncate([grey_box]) self.assertEqual(dash_box.coord_ll, (1, 1)) self.assertEqual(dash_box.width, 1) self.assertEqual(dash_box.height, 6) grey_box = tower((2, 2), 4, 4) slash_box = tower((1, 5), 6, 2) star_box = tower((1, 1), 6, 2) truncate_1 = slash_box.truncate([grey_box]) truncate_2 = star_box.truncate([grey_box]) self.assertEqual(truncate_1.coord_ll, (1, 6)) self.assertEqual(truncate_1.width, 6) self.assertEqual(truncate_1.height, 1) self.assertEqual(truncate_2.coord_ll, (1, 1)) self.assertEqual(truncate_2.width, 6) self.assertEqual(truncate_2.height, 1) slash_box = tower((2, 1), 4, 6) grey_box = tower((1, 2), 2, 4) blue_box = tower((5, 2), 2, 4) t = [grey_box, blue_box] dash_box = slash_box.truncate(t) self.assertEqual(dash_box.coord_ll, (3, 1)) self.assertEqual(dash_box.width, 2) self.assertEqual(dash_box.height, 6) grey_box = tower((1, 2), 2, 4) blue_box = tower((5, 2), 2, 4) dash_box = grey_box.truncate([blue_box]) self.assertEqual(dash_box.coord_ll, (1, 2)) self.assertEqual(dash_box.width, 2) self.assertEqual(dash_box.height, 4)
def setUp(self): ''' Sets up typical towers. t1 = tower((2,2),4,6) t2 = tower((7,2),2,6) other = [t1,t2] ''' self.t1 = tower((2, 2), 4, 6) self.t2 = tower((7, 2), 2, 6) self.other = [self.t1, self.t2]
def test_corner(self): ''' Tests the corner method from the tower class. Tests typical situations seen by the corner method. This test case can be found in the Juypter Notebook section discussing the corner method. Consists of: - Can identify specific corners. - Can recognize when one tower is contained in another. ''' grey_box = tower((1, 1), 1, 2) #gray box blue_box = tower((2, 1), 1, 2) #blue box result_1 = grey_box.corner(blue_box) self.assertEqual(result_1, [False, False, False, False]) grey_box = tower((2, 2), 5, 5) dashed_box = tower((1, 1), 2, 2) star_box = tower((6, 1), 2, 2) dot_box = tower((1, 6), 2, 2) slash_box = tower((6, 6), 2, 2) backslash_box = tower((4, 3), 1, 1) result_1 = dashed_box.corner(grey_box) result_2 = star_box.corner(grey_box) result_3 = dot_box.corner(grey_box) result_4 = slash_box.corner(grey_box) result_5 = backslash_box.corner(grey_box) self.assertEqual(result_1, [False, False, False, True]) self.assertEqual(result_2, [False, True, False, False]) self.assertEqual(result_3, [False, False, True, False]) self.assertEqual(result_4, [True, False, False, False]) self.assertEqual(result_5, [True, True, True, True])
def test___eq__(self): ''' Tests the __eq__ method from the tower class. Test is, given two identical towers, does it recognize that they are equivalent? ''' t_test = tower((2, 2), 4, 6) result = t_test == self.t1 self.assertEqual(result, True)
def test_overlap(self): ''' Tests the overlap method found in the tower class. Tests typical cases that overlap is used for. The various cases can be found in the Juypter Notebook dicsussing the overlap method. Consists of - Can it return the right tower object for the case in question. ''' grey_box = tower((2, 2), 4, 4) slash_box = tower((1, 1), 2, 6) result = slash_box.overlap(grey_box) self.assertEqual(result.area, 4) self.assertEqual(result.coord_ll, (2, 2)) self.assertEqual(result.width, 1) self.assertEqual(result.height, 4) slash_box = tower((1, 5), 6, 2) star_box = tower((1, 1), 6, 2) overlap_1 = slash_box.overlap(grey_box) overlap_2 = star_box.overlap(grey_box) self.assertEqual(overlap_1.coord_ll, (2, 5)) self.assertEqual(overlap_1.width, 4) self.assertEqual(overlap_1.height, 1) self.assertEqual(overlap_2.coord_ll, (2, 2)) self.assertEqual(overlap_2.width, 4) self.assertEqual(overlap_2.height, 1) grey_box = tower((4, 1), 2, 6) slash_box = tower((1, 1), 2, 6) dash_box = slash_box.overlap(grey_box) self.assertEqual(dash_box, None)
def test_subtowers(self): ''' Tests for the subtowers() method found in the tower class. Test a typical case used for subtower. We create a tower and check the resulting list against the list that it should generate. ''' t = tower((0, 0), 5, 5) test = [ tower((0, 0), 1, 1), tower((0, 0), 1, 2), tower((0, 0), 1, 3), tower((0, 0), 1, 4), tower((0, 0), 1, 5), tower((0, 0), 2, 1), tower((0, 0), 2, 2), tower((0, 0), 2, 3), tower((0, 0), 2, 4), tower((0, 0), 2, 5), tower((0, 0), 3, 1), tower((0, 0), 3, 2), tower((0, 0), 3, 3), tower((0, 0), 3, 4), tower((0, 0), 3, 5), tower((0, 0), 4, 1), tower((0, 0), 4, 2), tower((0, 0), 4, 3), tower((0, 0), 4, 4), tower((0, 0), 4, 5), tower((0, 0), 5, 1), tower((0, 0), 5, 2), tower((0, 0), 5, 3), tower((0, 0), 5, 4), tower((0, 0), 5, 5), tower((0, 1), 1, 1), tower((0, 1), 1, 2), tower((0, 1), 1, 3), tower((0, 1), 1, 4), tower((0, 1), 2, 1), tower((0, 1), 2, 2), tower((0, 1), 2, 3), tower((0, 1), 2, 4), tower((0, 1), 3, 1), tower((0, 1), 3, 2), tower((0, 1), 3, 3), tower((0, 1), 3, 4), tower((0, 1), 4, 1), tower((0, 1), 4, 2), tower((0, 1), 4, 3), tower((0, 1), 4, 4), tower((0, 1), 5, 1), tower((0, 1), 5, 2), tower((0, 1), 5, 3), tower((0, 1), 5, 4), tower((0, 2), 1, 1), tower((0, 2), 1, 2), tower((0, 2), 1, 3), tower((0, 2), 2, 1), tower((0, 2), 2, 2), tower((0, 2), 2, 3), tower((0, 2), 3, 1), tower((0, 2), 3, 2), tower((0, 2), 3, 3), tower((0, 2), 4, 1), tower((0, 2), 4, 2), tower((0, 2), 4, 3), tower((0, 2), 5, 1), tower((0, 2), 5, 2), tower((0, 2), 5, 3), tower((0, 3), 1, 1), tower((0, 3), 1, 2), tower((0, 3), 2, 1), tower((0, 3), 2, 2), tower((0, 3), 3, 1), tower((0, 3), 3, 2), tower((0, 3), 4, 1), tower((0, 3), 4, 2), tower((0, 3), 5, 1), tower((0, 3), 5, 2), tower((0, 4), 1, 1), tower((0, 4), 2, 1), tower((0, 4), 3, 1), tower((0, 4), 4, 1), tower((0, 4), 5, 1), tower((1, 0), 1, 1), tower((1, 0), 1, 2), tower((1, 0), 1, 3), tower((1, 0), 1, 4), tower((1, 0), 1, 5), tower((1, 0), 2, 1), tower((1, 0), 2, 2), tower((1, 0), 2, 3), tower((1, 0), 2, 4), tower((1, 0), 2, 5), tower((1, 0), 3, 1), tower((1, 0), 3, 2), tower((1, 0), 3, 3), tower((1, 0), 3, 4), tower((1, 0), 3, 5), tower((1, 0), 4, 1), tower((1, 0), 4, 2), tower((1, 0), 4, 3), tower((1, 0), 4, 4), tower((1, 0), 4, 5), tower((1, 1), 1, 1), tower((1, 1), 1, 2), tower((1, 1), 1, 3), tower((1, 1), 1, 4), tower((1, 1), 2, 1), tower((1, 1), 2, 2), tower((1, 1), 2, 3), tower((1, 1), 2, 4), tower((1, 1), 3, 1), tower((1, 1), 3, 2), tower((1, 1), 3, 3), tower((1, 1), 3, 4), tower((1, 1), 4, 1), tower((1, 1), 4, 2), tower((1, 1), 4, 3), tower((1, 1), 4, 4), tower((1, 2), 1, 1), tower((1, 2), 1, 2), tower((1, 2), 1, 3), tower((1, 2), 2, 1), tower((1, 2), 2, 2), tower((1, 2), 2, 3), tower((1, 2), 3, 1), tower((1, 2), 3, 2), tower((1, 2), 3, 3), tower((1, 2), 4, 1), tower((1, 2), 4, 2), tower((1, 2), 4, 3), tower((1, 3), 1, 1), tower((1, 3), 1, 2), tower((1, 3), 2, 1), tower((1, 3), 2, 2), tower((1, 3), 3, 1), tower((1, 3), 3, 2), tower((1, 3), 4, 1), tower((1, 3), 4, 2), tower((1, 4), 1, 1), tower((1, 4), 2, 1), tower((1, 4), 3, 1), tower((1, 4), 4, 1), tower((2, 0), 1, 1), tower((2, 0), 1, 2), tower((2, 0), 1, 3), tower((2, 0), 1, 4), tower((2, 0), 1, 5), tower((2, 0), 2, 1), tower((2, 0), 2, 2), tower((2, 0), 2, 3), tower((2, 0), 2, 4), tower((2, 0), 2, 5), tower((2, 0), 3, 1), tower((2, 0), 3, 2), tower((2, 0), 3, 3), tower((2, 0), 3, 4), tower((2, 0), 3, 5), tower((2, 1), 1, 1), tower((2, 1), 1, 2), tower((2, 1), 1, 3), tower((2, 1), 1, 4), tower((2, 1), 2, 1), tower((2, 1), 2, 2), tower((2, 1), 2, 3), tower((2, 1), 2, 4), tower((2, 1), 3, 1), tower((2, 1), 3, 2), tower((2, 1), 3, 3), tower((2, 1), 3, 4), tower((2, 2), 1, 1), tower((2, 2), 1, 2), tower((2, 2), 1, 3), tower((2, 2), 2, 1), tower((2, 2), 2, 2), tower((2, 2), 2, 3), tower((2, 2), 3, 1), tower((2, 2), 3, 2), tower((2, 2), 3, 3), tower((2, 3), 1, 1), tower((2, 3), 1, 2), tower((2, 3), 2, 1), tower((2, 3), 2, 2), tower((2, 3), 3, 1), tower((2, 3), 3, 2), tower((2, 4), 1, 1), tower((2, 4), 2, 1), tower((2, 4), 3, 1), tower((3, 0), 1, 1), tower((3, 0), 1, 2), tower((3, 0), 1, 3), tower((3, 0), 1, 4), tower((3, 0), 1, 5), tower((3, 0), 2, 1), tower((3, 0), 2, 2), tower((3, 0), 2, 3), tower((3, 0), 2, 4), tower((3, 0), 2, 5), tower((3, 1), 1, 1), tower((3, 1), 1, 2), tower((3, 1), 1, 3), tower((3, 1), 1, 4), tower((3, 1), 2, 1), tower((3, 1), 2, 2), tower((3, 1), 2, 3), tower((3, 1), 2, 4), tower((3, 2), 1, 1), tower((3, 2), 1, 2), tower((3, 2), 1, 3), tower((3, 2), 2, 1), tower((3, 2), 2, 2), tower((3, 2), 2, 3), tower((3, 3), 1, 1), tower((3, 3), 1, 2), tower((3, 3), 2, 1), tower((3, 3), 2, 2), tower((3, 4), 1, 1), tower((3, 4), 2, 1), tower((4, 0), 1, 1), tower((4, 0), 1, 2), tower((4, 0), 1, 3), tower((4, 0), 1, 4), tower((4, 0), 1, 5), tower((4, 1), 1, 1), tower((4, 1), 1, 2), tower((4, 1), 1, 3), tower((4, 1), 1, 4), tower((4, 2), 1, 1), tower((4, 2), 1, 2), tower((4, 2), 1, 3), tower((4, 3), 1, 1), tower((4, 3), 1, 2), tower((4, 4), 1, 1) ] subtowers = t.subtowers() generated = list(subtowers) self.assertEqual(len(test), len(generated)) for subtower in test: saw_it = 0 for t in generated: if t == subtower: saw_it = 1 self.assertEqual(saw_it, 1)
def test_borders(self): ''' Tests the border method from the tower class. Tests typical cases seen by the borders method. The cases this tests can be found in the Juypter Notebook section discussing the borders method. Consists of: - Can it tell which wall(s) is inside a region of another tower's coverage. ''' grey_box = tower((2, 2), 4, 4) t_test = [ tower((1, 3), 1, 2), tower((3, 1), 2, 1), tower((6, 3), 1, 2), tower((3, 6), 2, 1) ] for t in t_test: result = t.borders(grey_box) self.assertEqual(result, [False, False, False, False]) slash_box = tower((1, 1), 2, 6) star_box = tower((5, 1), 2, 6) result_1 = slash_box.borders(grey_box) result_2 = star_box.borders(grey_box) self.assertEqual(result_1, [False, True, False, False]) self.assertEqual(result_2, [True, False, False, False]) slash_box = tower((1, 5), 6, 2) star_box = tower((1, 1), 6, 2) result_3 = slash_box.borders(grey_box) result_4 = star_box.borders(grey_box) self.assertEqual(result_3, [False, False, False, True]) self.assertEqual(result_4, [False, False, True, False]) slash_box = tower((1, 3), 6, 2) star_box = tower((3, 1), 2, 6) result_3 = slash_box.borders(grey_box) result_4 = star_box.borders(grey_box) self.assertEqual(result_3, [False, False, True, True]) self.assertEqual(result_4, [True, True, False, False])
def coverage_up_to_n(n, width, height, plot=True, interval=3): ''' Takes in an amount of towers and a desired coverage area described by a height and width and returns a list of randomly generated towers to populate the desired coverage area. Parameter: n Type: int Parameter: width Type: int Parameter: height Type: int Parameter: plot Type: bool Parameter: interval Type: int Return: - list of towers that populate the coverage area. - list of towers that populate the coverage area in a format compatible with the function plot_towers(). - Returns a tuple containing the desired coverage versus the resulting coverage given n towers. (desired_area,actual_area) e.g. >>> valid_towers, plot_list = coverage(10,100,100) >>> valid_towers [tower((30, 0),15,59), tower((7, 1),23,21), tower((45, 34),33,44), tower((49, 22),2,12), tower((15, 32),15,64), tower((19, 26),11,6), tower((2, 27),13,13), tower((53, 78),24,16), tower((30, 79),23,12), tower((15, 22),2,10)] >>> plot_list [[tower((30, 0),15,59), '#56C8D0', None, True], [tower((7, 1),23,21), '#1968E5', None, True], [tower((45, 34),33,44), '#D23EEB', None, True], [tower((49, 22),2,12), '#DFA7A8', None, True], [tower((15, 32),15,64), '#A4011A', None, True], [tower((19, 26),11,6), '#D47484', None, True], [tower((2, 27),13,13), '#58D79F', None, True], [tower((53, 78),24,16), '#0E7345', None, True], [tower((30, 79),23,12), '#B8131C', None, True], [tower((15, 22),2,10), '#239036', None, True]] Assertions: - Number of towers (n) must be a positive number. - n must be an integer. - width must be a positive number - width must be an integer. - height must be a positive number - height must be an integer. - plot must be a boolean, True or False - interval must be a positive number - interval must be an integer. Takes an amount of towers and desired coverage region and randomly generates those towers to populate that region. You can opt to watch the attempts take place in real time by changing the plot value to True. It will then plot the values as time goes on. The variable interval designates the amount of time between plots. It starts by generating a random tower with random (x,y) coordinate of the lower left corner, a random height and random width. Once the tower is generated we check if it's a valid candidate for processing by making sure it is bound by the desired coverage region defined by the user. We do this by creating a tower that has the dimensions of the whole region. We can then run the contained method to see if the randomly generated tower is bound within the desired coverage area. If the current list of valid towers is empty, we add the randomly generated into the list. If it isn't, we makes sure that it isn't completely contained inside any of the already established towers, or that our new tower doesn't consume the entirety of the established towers. Once we have gone through those steps than the tower is valid and we can proceed. To speed up processing, we only truncate the new tower against towers that it overlaps with, which we check with the contained and borders method. If it doesn't overlap with any, then we can just add it to the valid tower list. If there is no valid truncated version of the tower than we toss it out and try again. If there is one, we can add it to the valid tower list. It does this over and over until the confirmed amount of towers is equal to the amount of towers asked by the user. Once we have found all the towers we are finished. In the plotting mode, it will show the attempted new tower as a slash-box. Then it will get replaced with a colored truncated version. Assertions: - n must be a positive integer greater than zero. - width must be a positive integer greater than zero. - height must be a positive integer greater than zero. - plot must be a boolean, True or False - interval must be a positive integer greater than zero. ''' assert n > 0, 'Warning! Number of towers must be greater than zero!' assert isinstance(n, int), 'Warning! Number of towers must be an integer!' assert width > 0, 'Warning! Width of coverage area must be greater than 0!' assert isinstance(width, int), 'Warning! Width must be an integer!' assert height > 0, 'Warning! Height of coverage area must be greater than 0!' assert isinstance(height, int), 'Warning! Height must be an integer!' assert isinstance(plot, bool), 'Warning! plot must be True or False!' assert interval > 0, 'Warning! Interval must be greater than zero!' assert isinstance(interval, int), 'Warning! Interval must be an integer!' print 'Computing...' confirmed_towers = 0 coverage_area = tower((0, 0), width, height) #Taking advantage of my tower class method. valid_towers = [] plot_list = [] desired_area = width * height while confirmed_towers < n: x_rand = np.random.randint(width, size=1) y_rand = np.random.randint(height, size=1) x = x_rand[0] y = y_rand[0] width_rand = np.random.randint( 1, width + 1, size=1) #Have to be careful about half-open interval height_rand = np.random.randint(1, height + 1, size=1) tower_width = width_rand[0] tower_height = height_rand[0] ### t = tower((x, y), tower_width, tower_height) #Check if newly generated tower is contained in main coverage area. test = t.contained(coverage_area) valid = 1 if all(test) != True: valid = 0 if len(valid_towers) != 0: #Checking to see if newly generated tower is inside any of the #already established towers. for t_i in valid_towers: checks = t.contained(t_i) if all(checks) == True: valid = 0 #Checking to see if any of my established towers are inside of mu #newly generated tower. for t_i in valid_towers: checks = t_i.contained(t) if all(checks) == True: valid = 0 #Now that we have validated the new tower, we can proceed. if valid == 1: #Plotting newly generated tower. if plot: plot_t = [t, None, '/', False] plot_list.append(plot_t) plot_towers(plot_list, width, height) plt.pause(interval) plt.close() #If the tower generated is equal to the coverage area, then we are done. if (len(valid_towers) == 0) and (t == coverage_area): valid_towers.append(t) return list_of_towers, plot_list elif len(valid_towers) == 0: valid_towers.append(t) if plot: plot_list.pop() color_rect = '#%02X%02X%02X' % (color(), color(), color()) plot_list.append([t, color_rect, None, True]) confirmed_towers += 1 else: truncate_list = [] for tow in valid_towers: if any(t.corner(tow)) or any(t.borders(tow)): truncate_list.append(tow) if len(truncate_list) != 0: truncated = t.truncate(truncate_list) #Was valid towers if truncated != None: if plot: plot_list.pop() color_rect = '#%02X%02X%02X' % (color(), color(), color()) plot_list.append( [truncated, color_rect, None, True]) confirmed_towers += 1 valid_towers.append(truncated) else: if plot: plot_list.pop() else: if plot: plot_list.pop() color_rect = '#%02X%02X%02X' % (color(), color(), color()) plot_list.append([t, color_rect, None, True]) confirmed_towers += 1 valid_towers.append(t) if plot: if confirmed_towers == n: plot_towers(plot_list, width, height) actual_area = 0 for coverage in valid_towers: actual_area = actual_area + coverage.area if (actual_area == desired_area): print "Coverage area has been filled!" break print 'Desired area: ', desired_area print 'Actual area: ', actual_area return valid_towers, (desired_area, actual_area), plot_list
def average_towers_for_coverage(iterations, width, height): ''' Takes in an amount of iterations and a desired coverage area described by a height and width and returns the average amount of towers needed to fully populate the desired coverage area. Parameter: iterations Type: int Parameter: width Type: int Parameter: height Type: int Return: - Returns the average for the number of iterations asked for by the user. e.g. Assertions: - iterations must be a positive number. - iterations must be an integer. - width must be a positive number - width must be an integer. - height must be a positive number - height must be an integer. Takes an amount of iterations and desired coverage region and randomly generates those towers to populate that region. It starts by generating a random tower with random (x,y) coordinate of the lower left corner, a random height and random width. Once the tower is generated we check if it's a valid candidate for processing by making sure it is bound by the desired coverage region defined by the user. We do this by creating a tower that has the dimensions of the whole region. We can then run the contained method to see if the randomly generated tower is bound within the desired coverage area. If the current list of valid towers is empty, we add the randomly generated into the list. If it isn't, we makes sure that it isn't completely contained inside any of the already established towers, or that our new tower doesn't consume the entirety of the established towers. Once we have gone through those steps than the tower is valid and we can proceed. To speed up processing, we only truncate the new tower against towers that it overlaps with, which we check with the contained and borders method. If it doesn't overlap with any, then we can just add it to the valid tower list. If there is no valid truncated version of the tower than we toss it out and try again. If there is one, we can add it to the valid tower list. It does this over and over until the confirmed amount of towers is equal to the amount of towers asked by the user. Once we have found all the towers we are finished and we go to the next iteration. It does this until all the iterations are done. Assertions: - iterations must be a positive integer greater than zero. - width must be a positive integer greater than zero. - height must be a positive integer greater than zero. ''' assert iterations > 0, 'Warning! Number of iterations must be greater than zero!' assert isinstance(iterations, int), 'Warning! Number of iterations must be an integer!' assert width > 0, 'Warning! Width of coverage area must be greater than 0!' assert isinstance(width, int), 'Warning! Width must be an integer!' assert height > 0, 'Warning! Height of coverage area must be greater than 0!' assert isinstance(height, int), 'Warning! Height must be an integer!' print 'Computing...' confirmed_towers = 0 coverage_area = tower((0, 0), width, height) #Taking advantage of my tower class method. desired_area = width * height counter = 0 number_of_towers = [] while counter < iterations: actual_area = 0 valid_towers = [] while actual_area != desired_area: x_rand = np.random.randint(width, size=1) y_rand = np.random.randint(height, size=1) x = x_rand[0] y = y_rand[0] width_rand = np.random.randint( 1, width + 1, size=1) #Have to be careful about half-open interval height_rand = np.random.randint(1, height + 1, size=1) tower_width = width_rand[0] tower_height = height_rand[0] ### t = tower((x, y), tower_width, tower_height) #Check if newly generated tower is contained in main coverage area. test = t.contained(coverage_area) valid = 1 if all(test) != True: valid = 0 if len(valid_towers) != 0: #Checking to see if newly generated tower is inside any of the #already established towers. for t_i in valid_towers: checks = t.contained(t_i) if all(checks) == True: valid = 0 #Checking to see if any of my established towers are inside of mu #newly generated tower. for t_i in valid_towers: checks = t_i.contained(t) if all(checks) == True: valid = 0 #Now that we have validated the new tower, we can proceed. if valid == 1: #If the tower generated is equal to the coverage area, then we are done. if (len(valid_towers) == 0) and (t == coverage_area): valid_towers.append(t) return list_of_towers, plot_list elif len(valid_towers) == 0: valid_towers.append(t) confirmed_towers += 1 else: truncate_list = [] for tow in valid_towers: if any(t.corner(tow)) or any(t.borders(tow)): truncate_list.append(tow) if len(truncate_list) != 0: truncated = t.truncate( truncate_list) #Was valid towers if truncated != None: confirmed_towers += 1 valid_towers.append(truncated) else: confirmed_towers += 1 valid_towers.append(t) actual_area = 0 for coverage in valid_towers: actual_area = actual_area + coverage.area if (actual_area == desired_area): print 'Iteration: %d. Desired coverage area has been filled!' % ( counter + 1) break number_of_towers.append(len(valid_towers)) counter += 1 summation = float(sum(number_of_towers)) average = summation / len(number_of_towers) print "Number of iterations: ", iterations print "Average: ", average return average