So I am outputting a triangle made of characters inputted by the user, and the user also inputs the height of the triangle (height equals base as well).
The program also wants me to have spaces in between each character printed. I have two methods that will correctly output what I want. I just want to understand what the space = space + value... line does.
I only figured out how to do it because I knew I had to use a "for" loop and pretty much just messed around with which variables I placed in the loop.
sorry there are so many questions, loops confuse me so much
triangle_char = input('Enter a character:\n')
triangle_height = int(input('Enter triangle height:\n'))
space = ''
for i in range(0, triangle_height, 1):
for value in triangle_char: #if this loop is not here, and I do print(i * triangle_char), it will only output a triangle with height of 2. why?
space = space + value + ' ' #what does this do?
print(space)
#beneath is the 2nd version of the code
counter = 1
space = ''
for value in range(triangle_height):
while counter <= triangle_height:
for value in triangle_char: #how can there be a value in just a character?
space = space + value + ' '
print(space)
TLDR:
read this
Line 5
range(a, b) returns integers from the range [a, b). So in line 4 your code will loop i starting from 0 up to triangle_height-1. Therefore, on its first iteration when you print 0 * triangle_char it would print an empty string (nothing).
Also note that the for loop on this line is redundant. When looping through a string of what is expected to be length 1, it would only assign value to triangle_char.
Line 6
space = space + value + ' ' concats the value of value + ' ' to space. This effectively adds the value triangle_char and a space to the end of space.
Line 15
Unlike many lower-level languages, there are no chars in python. Rather, python treats all characters as strings. Therefore this line would be looping through the characters of a length 1 string.
What does space = space + value + ' ' do?
space = space + value + ' ' will add value and a space ( ) to the value of the variable space and then overwrite the old value of space with this new one.
Perhaps naming the variable differently would help, e.g.
# create a blank message to start off with
message = ""
# add the user-entered value and a space to the message
message = message + value + ' '
# print out the message
print(message)
Why does print(i * triangle_char) only output a triangle of height 2?
I suspect that you entered a value of 3 for the triangle height when you saw this. If you entered a height of 5 you will see 5 lines, but the first will be blank because on the first iteration of the loop i is 0 and 0 * triangle_char will be a blank string. So the apparent height of the triangle will always be one less than triangle_height. Here is an example with height of 5.
>>> triangle_char = "+"
>>> triangle_height = 5
>>> for i in range(0, triangle_height, 1):
... print(i * triangle_char)
<=== this is the first blank line
+
++
+++
++++
How can there be a value in just a character?
A character in Python is really a string of length one. Python allows you to iterate/loop through strings and when you do you go through all the characters in the string one at a time. Therefore a "character" has one value when you loop over it.
Related
I am programming a Caeser Cipher encoder/decoder for my computer science class in Python 3 and I'm struggling to find out how to exclude spaces when each character is shifted.
message = input("type in a message")
messageInt = float(input("type in an integer"))
newStrs = []
for letter in message:
x = ord(letter)
x = int(x + messageInt)
newStrs.append(chr(x))
print("".join(newStrs))
This happends when I try to use an example sentance with spaces, I've tried looking online for answers but I wasn't able to find anything that seemed to work in Python 3 or would output what my teacher expects.
type in a message hello there
type in an integer 3
#khoor#wkhuh
Process finished with exit code 0
Use a simple list comprehension with a ternary to check for the spaces:
message = input("type in a message")
messageInt = int(input("type in an integer"))
print("".join([c if c == ' ' else chr((ord(c)-ord('a')+messageInt)%26+ord('a')) for c in message]))
You can easily generalize to a whitelist of characters using a set:
keep = set(' .,?!')
print("".join([c if c in keep else chr((ord(c)-ord('a')+messageInt)%26+ord('a')) for c in message]))
Output:
khoor wkhuh
To exclude spaces when shifting the characters in your message, you can simply add an if statement to your loop that checks if the current letter is a space. If it is, you can skip the shifting step and just append the space to the newStrs list.
I modified your code as an example (code updated):
# Get the message and shift amount from the user
message = input("type in a message: ")
shift = int(input("type in an integer: "))
# Create a list to store the shifted characters
new_str = []
# Iterate through each character in the message
for letter in message:
# Check if the character is a space
if letter == " ":
# If it is, append a space to the new string and skip the rest of the loop
new_str.append(" ")
continue
# Shift the character by the specified amount
# First, get the ASCII value of the character
x = ord(letter)
# Shift the character and wrap around the alphabet if necessary
x = (x + shift - 97) % 26 + 97
# Convert the shifted ASCII value back to a character and append it to the new string
new_str.append(chr(x))
# Join the shifted characters into a single string and print it
print("".join(new_str))
If you are wondering whats going on with
x = (x + shift - 97) % 26 + 97
This will shift all characters except spaces, so the output will preserve the spaces in the original message.
x = (x + shift - 97) % 26 + 97
This line of code is used to shift the ASCII value of a character by a specified amount and wrap around the alphabet if necessary.
First, the value of x is added to the value of shift:
x + shift
Then, 97 is subtracted from the result:
x + shift - 97
The result is then passed to the % operator, which returns the remainder of the division of the left operand by the right operand. In this case, the remainder of the division of x + shift - 97 by 26 is calculated:
(x + shift - 97) % 26
Finally, 97 is added back to the result:
(x + shift - 97) % 26 + 97
This has the effect of shifting the character by the specified amount, wrapping around the alphabet if necessary, and ensuring that the resulting ASCII value is in the range 97 to 122 (inclusive).
For example, if the value of x is 120 (the ASCII value of 'x'), the value of shift is 3, and the line of code is executed, the following steps will be taken:
120 + 3 = 123
123 - 97 = 26
26 % 26 = 0
0 + 97 = 97
The final result, 97, is the ASCII value of 'a', so the resulting character will be 'a'.
This program will output a right triangle based on user specified height triangle_height and symbol triangle_char.
(1) The given program outputs a fixed-height triangle using a * character. Modify the given program to output a right triangle that instead uses the user-specified triangle_char character.
(2) Modify the program to use a loop to output a right triangle of height triangle_height. The first line will have one user-specified character, such as % or *. Each subsequent line will have one additional user-specified character until the number in the triangle's base reaches triangle_height. Output a space after each user-specified character, including a line's last user-specified character.
I'm having trouble figuring out how to create a space between my characters. Example input is % and 5. My code is:
triangle_char = input('Enter a character:\n')
triangle_height = int(input('Enter triangle height:\n'))
print('')
for i in range (triangle_height):
print((triangle_char) * (i + 1))
my output is:
%
%%
%%%
%%%%
%%%%%
while expected output is:
%
% %
% % %
% % % %
% % % % %
You need to use join(). This would work:
for i in range(triangle_height):
print(' '.join(triangle_char * (i + 1)))
It is adding spaces between every character because strings are iterable.
This may be optimized a bit by having a list of the characters and appending 1 character in each iteration, rather than constructing triangle_char * (i+1) every time.
This should fix the white space errors:
for i in range(triangle_height):
print(' '.join(triangle_char * (i + 1)) + ' ')
for i in range(triangle_height+1):
print(f'{triangle_char} '*i)
I see the popular way so far is using join, but another way while trying to stay true to the original idea is you simply can add a white space after each character. See below:
triangle_char = input('Enter a character:\n')
triangle_height = int(input('Enter triangle height:\n'))
print('')
for i in range(triangle_height):
print((triangle_char + ' ') * (i + 1))
There are some really good suggestions on here. Another approach is to use an incremented variable in a while loop as shown below:
triangle_char = input("Enter a character:\n")[0]
triangle_height = int(input("Enter triangle height:\n"))
i = 0
while (i <= triangle_height):
print((triangle_char + ' ') * i)
i += 1
With the example above, i iterates until it is equal to triangle_height and uses polymorphism to generate a quantity of (triangle_height + ' ') based on the value of i. This will generate the right triangle this lab requires. The space is used to format the triangle per lab requirements.
Another method is using the .join() feature, and it certainly would work well here, but is not taught until CH7 of this book where you learn about input and CSV files. I am unsure if your professor would approve of using this, and I am only saying this because my professor was strict about using material not covered.
An additional method mentioned already is to use a for loop with the use of the range() feature containing an expression:
triangle_char = input("Enter a character:\n")[0]
triangle_height = int(input("Enter triangle height:\n"))
for i in range((triangle_height + 1)):
print((triangle_char + ' ') * i)
The end point of range() being just triangle_height would not suffice because the value specified as the end point is not included in the sequence. This would make a right triangle with a height of 4 even if triangle_height was 5 Therefore, you must use the expression (triangle_height + 1). From there, the output is set up similarly to my first solution.
Try adding a whitespace in the print statement.
height = int(input())
symbol = (input())
print()
for i in range(height): #Loop for every index in the range 0-height
print((symbol + ' ') * (i + 1)) #Add whitespace to symbol
My requirements
Use Python to create a function cleanstring(S) to "clean up" the spaces in a sentence S.
The sentence may have extra spaces at the front and/or at the end and/or between words.
The subroutine returns a new version of the sentence without the extra spaces.
That is, in the new string, the words should be the same but there should be no spaces at the start, only one space between each word and no spaces at the end.
This program is about you writing code to search through a string to find words and so you are not allowed to use the split function in Python.
You can solve this problem with the basic capabilities of the if and while statements and string operations of len and concatentation.
For example: if the input is: " Hello to the world !" then the output should be: "Hello to the world!"
Question
My program deletes more characters in the program than needed.
Input: " Hello World ! "
Output: "HellWorl"
How do I fix the error in my program?
def cleanupstring (S):
newstring = ["", 0]
j = 1
for i in range(len(S) - 1):
if S[i] != " " and S[i+1] != " ":
newstring[0] = newstring[0] + S[i]
else:
newstring[1] = newstring [1] + 1
return newstring
# main program
sentence = input("Enter a string: ")
outputList = cleanupstring(sentence)
print("A total of", outputList[1], "characters have been removed from your
string.")
print("The new string is:", outputList[0])
Welcome to Stackoverflow. When I started reading I though this was going to be a "please answer my homework" question, but you've actually made a pretty fair effort at solving the problem, so I'm happy to try and help (only you can say whether I actually do).
It's sometimes difficult when you are learning a new language to drop techniques that are much more appropriate in other languages. Doing it character by character you normally just use for c in s rather than incrementing index values like you would in C (though either approach works, index incrementation where not necessary is sometimes regarded as "unpythonic"). Your basic idea seems to be to detect a space followed by another space, otherwise copying characters from the input to the output.
The logic can be simplified by retaining the last character you sent to the output. If it's a space, don't send any more spaces. A loop at the front gets rid of any leading spaces, and since there can be at most one space at the end it can be eliminated easily if present.
I'm not sure why you use a list to keep your results in, as it makes the code much more difficult to understand. If you need to return multiple pieces of information it's much easier to compute them in individual variables and then construct the result in the return statement.
So one desirable modification would be to replace newstring[0] with, say, out_s and newstring[1] with, say count. That will make it a bit clearer what's going on. Then at the end return [out_s, count] if you really need a list. A tuple using return out_s, count would be more usual.
def cleanupstring (s):
out_s = ''
count = 0
last_out = ' '
for c in s:
if c != ' ' or last_out != ' ':
last_out = c
out_s += c
else:
count += 1
if last_out == ' ':
count -= 1
out_s = out_s[:-1]
return out_s, count
# main program
sentence = input("Enter a string: ")
outputList = cleanupstring(sentence)
print("A total of", outputList[1], "characters have been removed from your string.")
print("The new string is:", outputList[0])
Sometimes you just don't have certain pieces of information that would help you to answer the question extremely succinctly. You most likely haven't yet been taught about the strip and replace methods, and so I imagine the following (untested) code
def cleanupstring(s):
out_s = s
while ' ' in out_s:
out_s = out_s.strip().replace(' ', ' ')
return out_s, len(s)-len(out_s)
would be right out.
Also, you can use an "unpacking assignment" to bind the different elements of the function's output directly to names by writing
s, c = cleanupstring(...)
I'm sure you will agree that
print("A total of", c, "characters have been removed from your string.")
print("The new string is:", s)
is rather easier to read. Python values readability so highly because with readable code it's easier to understand the intent of the author. If your code is hard to understand there's a good chance you still have some refactoring to do!
If the "space" it's literally spaces rather than whitespace then the following would work:
import re
def clean_string(value):
return re.sub('[ ]{2,}', ' ', value.strip())
If the stripped values contains consecutive spaces then replace with one space.
My approach would be to keep the last character available and make the decision whether it is a space or not:
def cleanupstring (S):
newstring = ["", 0]
last_character = ' ' # catch initial spaces
for i in range(len(S)-1):
char = S[i]
if char is ' ' and last_character is ' ':
continue # ignore
else:
last_character = char
newstring [0] = newstring[0] + char
return newstring
#get string and shift from user
string = input('Please enter a string to be ciphered: ')
shift = input('Please enter a shift amount between 0 and 25: ')
#strings are immutable so it must be converted to a list
s=list(string)
#now this will convert each character based on the shift
for i in range(0,len(s)):
s[i]=chr(ord(s[i]) + int(shift))
print ("".join(s))
You should call the method str.alpha to ensure that the chosen element is an alphabet before shifting
for i in range(0,len(s)):
if elem.isaplha():
s[i]=chr(ord(s[i]) + int(shift))
On a second though, you are doing to much work here. Why not use a comprehension expression?
s = ''.join(chr(ord(elem) + shift) if elem.isalpha() else elem for elem in s)
or if you are adventurous enough
s = ''.join([elem, chr(ord(elem) + shift)][elem.isalpha()] for elem in s)
and finally have you checked the string.makestrans along with str.translate to do the conversion?
from string import maketrans, ascii_alpha
s = s.translate(maketrans(ascii_alpha[shift:] + string.ascii_alpha[:shift])
All you have to do is check if the current character is not one you want to skip.
for i in range(0,len(s)):
#If not a space, cipher this character.
if s[i] != ' ':
s[i]=chr(ord(s[i]) + int(shift))
There is however, a possibility that one of your characters will be ciphered to a space, in which case that character would be skipped when reversing the cipher.
Also, a simple cipher like this should not be considered secure in the least.
I'm using Grok Learning and the task it give you is 'to select every third letter out of a sentence (starting from the first letter), and print out those letters with spaces in between them.'
This is my code:
text = input("Message? ")
length = len(text)
for i in range (0, length, 3):
decoded = text[i]
print(decoded, end=" ")
Although I it says it isn't correct, it say this is the desired out-put:
Message? cxohawalkldflghemwnsegfaeap
c h a l l e n g e
And my output is the same expect, in my output, I have a space after the last 'e' in challenge. Can anyone think of a way to fix this?
To have spaces only between the characters, you could use a slice to create the string "challenge" then use str.join to add the spaces:
" ".join(text[::3])
Here's Grok's explanation to your question: "So, this question is asking you to loop over a string, and print out every third letter. The easiest way to do this is to use for and range, letting range do all the heavy lifting and hard work! We know that range creates a list of numbers, - we can use these numbers as indexes for the message!"
So if you are going to include functions like print, len, end, range, input, for and in functions, your code should look somewhat similar to this:
line = input('Message? ')
result = line[0]
for i in range(3, len(line), 3):
result += ' ' + line[i]
print(result)
Or this:
line = input('Message? ')
print(line[0], end='')
for i in range(3, len(line), 3):
print(' ' + line[i], end='')
print()
Or maybe this:
code = input ('Message? ') [0::3]
msg = ""
for i in code: msg += " " + i
print (msg [1:])
All of these should work, and I hope this answers your question.
I think Grok is just really picky about the details. (It's also case sensitive)
Maybe try this for an alternative because this one worked for me:
message = input('Message? ')
last_index = len(message) -1
decoded = ''
for i in range(0, last_index, 3):
decoded += message[i] + ' '
print(decoded.rstrip())
You should take another look at the notes on this page about building up a string, and then printing it out all at once, in this case perhaps using rstrip() or output[:-1] to leave off the space on the far right.
Here's an example printing out the numbers 0 to 9 in the same fashion, using both rstrip and slicing.
output = ""
for i in range(10):
output = output + str(i) + ' '
print(output[:-1])
print(output.rstrip())
If you look through the Grok course, there is one page called ‘Step by step, side by side’ (link here at https://groklearning.com/learn/intro-python-1/repeating-things/8/) where it introduces the rstrip function. If you write print(output.rstrip()) it will get rid of whitespace to the right of the string.