| @ -0,0 +1,186 @@ | |||
| import math | |||
| """ | |||
| Python script to print the message blurb above | |||
| the asci actor for quotes | |||
| 11-3-18 | |||
| Jeffery Russell | |||
| """ | |||
| MAX_MESSAGE_WIDTH = 35 | |||
| 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 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 getMaxLineWidth(S, choice): | |||
| """ | |||
| Computes the max width of a solution given | |||
| :param S: List of words | |||
| :param choice: tuples of the start/end indecies of the words to print | |||
| :return: max width | |||
| """ | |||
| max = -1 | |||
| for i in range(0, len(choice)): | |||
| print_size = 0 | |||
| for x in range(choice[i][0], choice[i][1] + 1): | |||
| print_size += len(str(S[x])) | |||
| if not x == choice[i][1]: | |||
| print_size += 1 | |||
| if max < print_size: | |||
| max = print_size | |||
| return max | |||
| def getBestSolution(S): | |||
| """ | |||
| Computes the best way to print the message by varying the | |||
| max width at most 10 spaces. | |||
| :param S: List of words | |||
| :return: choices to print optimal solution | |||
| """ | |||
| bestCost = math.inf | |||
| bestSolution = None | |||
| for i in range(MAX_MESSAGE_WIDTH -5, MAX_MESSAGE_WIDTH + 5): | |||
| cost, choice = minBadDynamicChoice(S, i) | |||
| if cost < bestCost: | |||
| bestSolution = choice | |||
| bestCost = cost | |||
| return bestSolution | |||
| def printParagraph(S): | |||
| """ | |||
| This will print the message in the optimal way | |||
| which reduces the maximum number of blank spaces | |||
| at the end of a line (excluding last line). | |||
| The message will be printed in the form of a | |||
| message bubble. | |||
| ------------------------------------- | |||
| / One day I will find the right words \ | |||
| \ and they will be simple. / | |||
| ------------------------------------- | |||
| ------------------------ | |||
| < No rest for the wicked > | |||
| ------------------------ | |||
| ---------------------------------- | |||
| / A bug is never just a mistake. \ | |||
| | It represents something bigger. | | |||
| | An error of thinking. That makes | | |||
| \ you who you are. / | |||
| ---------------------------------- | |||
| :param S: List of words | |||
| """ | |||
| choice = getBestSolution(S) | |||
| max_line_width = getMaxLineWidth(S, choice) | |||
| "Print top" | |||
| print(" " + "-" * (2 + max_line_width)) | |||
| for i in range(0, len(choice)): | |||
| if len(choice) == 1: print("< ", end="") | |||
| elif i == 0: print("/ ", end="") | |||
| elif i == len(choice) - 1: print("\\ ", end="") | |||
| else: print("| ", end="") | |||
| print_size = 0 | |||
| for x in range(choice[i][0], choice[i][1] + 1): | |||
| print_size += len(str(S[x])) | |||
| print(str(S[x]), end="") | |||
| if not x == choice[i][1]: | |||
| print_size += 1 | |||
| print(" ", end="") | |||
| "print ending padding" | |||
| print(" " * (max_line_width - print_size), end="") | |||
| if len(choice) == 1: print(" >", end="") | |||
| elif i == 0: print(" \\", end="") | |||
| elif i == len(choice) -1: print(" /", end="") | |||
| else: print(" |", end="") | |||
| print() | |||
| "print bottom" | |||
| print(" " + "-" * (2 + max_line_width)) | |||
| def print_message(message): | |||
| if len(message) > 0: | |||
| printParagraph(message.split(" ")) | |||
| else: | |||
| print("Please pass in a message parameter") | |||