|
|
@ -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") |