Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rajatdiptabiswas/c051d60f24c4b203d7bda6ce0c71da52 to your computer and use it in GitHub Desktop.
Save rajatdiptabiswas/c051d60f24c4b203d7bda6ce0c71da52 to your computer and use it in GitHub Desktop.
Find the position of line breaks in a given string such that the lines are printed neatly. The string and the number of characters that can be put in one line are given as inputs. (https://www.geeksforgeeks.org/dynamic-programming-set-18-word-wrap/) (https://www.youtube.com/watch?v=RORuwHiblPc)
#!/usr/bin/env python3
import math
def main():
# take inputs
string = input("Enter the text to be justified:\n").split()
width = int(input("Enter the width of the line: "))
# create an array with the lengths of the words
string_length = [len(x) for x in string]
# create a dp table and initialise all values to 0
dp = [[0 for i in range(len(string))] for j in range(len(string))]
# fill the dp table with the square of the space remaining from the width after the words have been placed
# when more than one word is placed, the space between them should also be accounted for
# if the word(s) cannot be placed in the position fill the table with infinity
# dp[i][j] -> words placed from index i to index j (i and j inclusive)
for i in range(len(string)):
for j in range(i,len(string)):
if (sum(string_length[i:j+1]) + len(string_length[i:j+1]) - 1) <= width:
dp[i][j] = (width - (sum(string_length[i:j+1]) + len(string_length[i:j+1]) - 1))**2
else:
dp[i][j] = math.inf
# create two more lists to store the minimum cost and the final result
min_cost = [dp[x][len(string)-1] for x in range(len(string))]
result = [len(string) for x in range(len(string))]
# both i and j moves backwards
for i in range(len(string)-1,-1,-1): # last index -> 0
for j in range(len(string)-1,i,-1): # last index -> i
# min_cost[i] -> minimum cost needed to place words from index i to result[i]-1
# result[i] -> gives the range of the words to be placed in one line
# result[3] = 6 -> can place words from string[3] to string[5] (index to result[index]-1) in one line
# for the last words of the string given
if dp[i][len(string)-1] != math.inf:
min_cost[i] = dp[i][j]
result[i] = j + 1
else:
if dp[i][j-1] + min_cost[j] < min_cost[i]:
min_cost[i] = dp[i][j-1] + min_cost[j]
result[i] = j
# prints out the justified text
print()
index = 0
while (index != len(string)):
print(' '.join(string[index:result[index]]))
index = result[index]
print()
if __name__ == '__main__':
main()
'''
example
string = 'The quick brown fox jumps over the lazy dog'
width = 10
dp table
0 1 2 3 4 5 6 7 8
0 49 1 inf inf inf inf inf inf inf
1 0 25 inf inf inf inf inf inf inf
2 0 0 25 1 inf inf inf inf inf
3 0 0 0 49 1 inf inf inf inf
4 0 0 0 0 25 0 inf inf inf
5 0 0 0 0 0 36 4 inf inf
6 0 0 0 0 0 0 49 4 inf
7 0 0 0 0 0 0 0 36 4
8 0 0 0 0 0 0 0 0 49
min_cost = 35 59 34 9 33 8 53 4 49
result = 2 2 4 5 5 7 8 9 9
index 0 1 2 3 4 5 6 7 8
output
0 1 2 3 4 5 6 7 8 9
T h e q u i c k
b r o w n f o x
j u m p s
o v e r t h e
l a z y d o g
'''
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment