import math """ Jeffery Russell 11-13-18 """ def extraSpace(S, M, i, j): """ Computes the number of extra characters at the end of the line. Between each word there is only once space. :param S: List of words :param M: Max length of line :param i: start word index :param j: end word index """ extraSpaces = M - j + i for x in range(i, j + 1): extraSpaces -= len(S[x]) return extraSpaces def badnessLine(S, M, i, j): """ Computes Line badness. This is the number of extra spaces or infinity if the length exceeds M :param S: List of words :param M: Max length of line :param i: start word index :param j: end word index """ es = extraSpace(S, M, i, j) if es < 0: return math.inf return es def minBad(S, M, i): """ Computes the badness of a paragraph as the badness of the worst line in the paragraph not including the last line. *this is recursive :param S: List of words :param M: Max length of line :param i: start word index """ if badnessLine(S, M, i, len(S) -1) != math.inf: return 0 min = math.inf for k in range(i + 1, len(S)): end = minBad(S, M, k) front = badnessLine(S, M, i, k - 1) max = end if end > front else front min = min if min < max else max return min def minBadDynamic(S, M): """ Write a procedure minBadDynamic that implements the function mb' using dynamic program- ming. It should take only two parameters: S and M :param S: List of words :param M: Max length of line """ cost = [math.inf for i in range(len(S))] for i in range(0, len(S)): if badnessLine(S, M, 0, i) != math.inf: cost[i] = badnessLine(S, M, 0, i) if i == len(S) -1: return 0 #Everything fit on one line else: min = math.inf for k in range(0, i): before = cost[k] after = badnessLine(S, M, k + 1, i) if i == len(S) -1 and badnessLine(S, M, k+1, i) != math.inf: after = 0 # Last Line max = before if before > after else after min = min if min < max else max cost[i] = min return cost[len(S) -1] def minBadDynamicChoice(S, M): """ Write a procedure minBadDynamicChoice that implements the function mb' using dynamic programming. In addition to returning mb(S, M ), it should also return the choices made :param S: List of words :param M: Max length of line """ cost = [math.inf for i in range(len(S))] # List of tuples indicating start/end indices of line choice = [[] for i in range(len(S))] for i in range(0, len(S)): if badnessLine(S, M, 0, i) != math.inf: cost[i] = badnessLine(S, M, 0, i) choice[i] = [(0, i)] if i == len(S) - 1: return 0, [(0,i)] # One line else: min = math.inf choiceCanidate = [] for k in range(0, i): # Finds the optimal solution before = cost[k] # Previously computed minimum after = badnessLine(S, M, k + 1, i) # Badness of new slice if i == len(S) - 1 and badnessLine(S, M, k+1, i) != math.inf: after = 0 # Last line max = before if before > after else after if min > max: # Captures where slice is being taken choiceCanidate = choice[k] + [(k+1, i)] min = max choice[i] = choiceCanidate cost[i] = min return cost[len(S) -1], choice[len(S) -1] def printParagraph(S, M): """ which takes two parameters: S and M that displays the words in S on the screen using the choices of minBadDynamicChoice. What is the asymptotic running time of your algorithm? This program will run asymptotically in O(n^2) due to the characteristic of calculating the minBad for each sub sequence and then looping through a maximum of |S| to find the optimal solution. :param S: List of words :param M: Max length of line """ cost, choice = minBadDynamicChoice(S, M) print() for i in range(0, len(choice)): for x in range(choice[i][0], choice[i][1] + 1): print(str(S[x]), end=" ") print() print(minBadDynamicChoice(["aaa", "aaa"], 6)) printParagraph(["jjjjjj","aaa", "bb", "cc", "ff", "mm", "ddddd", "ddddd"], 6) printParagraph(["jjjjjj"], 6)