Reputation: 768
I am extremely new to Python and programming in general, and have been thinking about this supposedly simple exercise from a book called 'Think Python'and would like some help in understanding and solving this better. I apologize in advance if this is considered too 'simple' or off-topic, but I wasn't sure how to go about researching further about this specific example.
Write a function named right_justify that takes a string named s as a parameter and prints the string with enough leading spaces so that the last letter of the string is in column 70 of the display.
right_justify('monty')
Hint: Use string concatenation and repetition. Also, Python provides a built-in function called len that returns the length of a string, so the value of len('monty') is 5.
I have found an answer to this specific exercise here, but before I found that solution, I tried a solution of my own and would like to learn from solving it differently, even though it is much more long-winded.
At first, I thought it seemed simple; I just had to take the length of the parameter using the len function hinted, then divide 70 with that length and simply use string repetition with that division result to print. However, I quickly realized that this wouldn't work for arguments with a length where the division is not an integer but a floating number. So I came up with an idea:
def right_justify(s):
length = len(s)
HP = int(70/length)
#HP = Highest possible integer you can multiply with len(s) before exceeding total length of 70 , since int() will truncate a floating point result
remainder = 70 - HP*length
x = ' ', 'x', 'xx', 'xxx', 'x'*4, 'x'*5, 'x'*6, 'x'*7, 'x'*8, 'x'*9
remainder = len(x)
print(s*(HP-1)+x+s)
What I tried to do here was, first I filled up the entire row via repetition while leaving space for 1 last iteration of the input along with the remainder length if any. To make sure that the last letter is the last letter of the argument, I concatenate the remainder first to s*(HP-1), then join the last reiteration of s.
I already see problems with my code but I'm at a lost as to how to solve it. The first thing is the remainder: How can I write the program such that x can have variable length, and I ensure that the x with the length equal to that of the remainder is always in the final print statement?
Also, when I try to run the program, I get an error message:
Traceback (most recent call last):
File "<pyshell#25>", line 1, in <module>
right_justify('test')
File "<pyshell#24>", line 8, in right_justify
print(s*(HP-1)+x+s)
TypeError: can only concatenate str (not "tuple") to str
I tried to Google the TypeError but the answers were too specific or advanced solutions such that I could not gain any understanding from them. I hope someone can help me understand the concepts involved in solving this problem and how to execute them. Thanks!
EDIT: Thank you for all the informative answers everyone! I appreciate all the different solutions given, there is a lot to learn from them. I decided to select Pepi's answer as he guided the way to solve this problem using tuples in my original train of thought.
Here is what I wrote using my newfound knowledge of tuples and index to solve this problem:
def right_justify(s):
length = len(s)
HP = int(70/length)
#HP = Highest possible integer you can multiply with len(s) before exceeding total length of 70 , since int() will truncate a floating point result
remainder = 70 - HP*length
x = '', 'x', 'xx', 'xxx', 'x'*4, 'x'*5, 'x'*6, 'x'*7, 'x'*8, 'x'*9
y = x[remainder]
print(s*(HP-1)+y+s)
Thank you to Jack Taylor and Alain T. for the other very elegant solutions as well.
Upvotes: 0
Views: 440
Reputation: 42143
using concatenation, repetition and the len function:
" "*(70-len(s)) + s
Upvotes: 1
Reputation: 6217
If you're feeling lazy, you can use a right-align format string:
def right_justify(s):
return "{:>70}".format(s)
Upvotes: 3
Reputation: 171
First - the answer to your question:
The line
x = ' ', 'x', 'xx', 'xxx', 'x'*4, 'x'*5, 'x'*6, 'x'*7, 'x'*8, 'x'*9
creates a tuple, with is a kind of list, in this case contain the strings ' ', 'x', 'xx', 'xxx', ..., 'xxxxxxxxx'.
In order to concatenate one of these strings, get the one that you want using an index: x[i], where i is an integer from 0 to 9. (More generally, list types will be indexed from 0 to len(list)-1.)
x[2] #returns 'xx'
The result of this reference will be str, and will concatenate to the rest of your string.
Lastly: I think you'll find shorter & clearer ways to solve the given problem, but there's nothing wrong with playing around for while. Hint: avoid floating point math here.
Upvotes: 2