caesar cipher object doesn't support assignment python - python

Write a method that takes in an integer offset and a string.
Produce a new string, where each letter is shifted by offset. You
may assume that the string contains only lowercase letters and
spaces.
def caesar_cipher(offset, string):
words = string.split(" ")
word_i = 0
while word_i < len(words):
word = words[word_i]
letter_i = 0
while letter_i < len(word):
char_i = ord(word[letter_i]) - ord("a")
new_char_i = (char_i + offset) % 26
word[letter_i] = chr(ord("a") + new_char_i) #----error is at this line ----
letter_i += 1
word_i += 1
return words.join(" ")
print caesar_cipher(3, "abc")
print should return def.
would like to know how to fix this str assignment error please and thank you!

Strings are immutable.
a = "hello"
a[1] = 'q'
..results in this error:
TypeError: 'str' object does not support item assignment
A better approach is to build up new a list of 1-character strings out of the substituted letters. In idiomatic Pythonic, that would be a list comprehension, but a for-loop would also work fine.
Lastly, join them into a new string like this:
''.join(cipher_chars)

Related

Use a condition within a loop

A simple substitution cipher may be created by shifting or rotating the alphabet by a certain number of places. Using this system with a rotation of 5 gives us the following alphabets:
Plaintext alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZ
Ciphertext alphabet: FGHIJKLMNOPQRSTUVWXYZABCDE
Any plain text message can be translated into the ciphertext by replacing each letter of the plain text alphabet with the letter in the ciphertext alphabet in the equivalent position. Spaces are left unchanged. For example, using the cipher above, the word DOG is enciphered as OBK.
Given a String and a rotation value, return the String translated into the ciphertext using the simple substitution method described above. You may assume that the text contains only spaces or capital letters and that the rotation value is always non-negative
function name: rotate_text
arguments:
text - input text to be encoded
n - an integer value specifying how many characters to rotate the text by
returns: a string containing the text rotated as described above
Testing
I am able to pass the test, but the result said I am u therenable to pass hidden or more test, Could someone help me?
def rotate_text(string1, int1):
loL = ['A','B','C','D','E','F','G','H','I','J','K',
'L','M','N','O','P','Q','R','S','T','U','V',
'W','X','Y','Z']
strtoList = list(string1)
list1 = []
newStr = ""
if int1 == len(loL):
int1 = int1 % 26
for i in range(len(strtoList)):
if strtoList[i] in loL:
loLindex = loL.index(strtoList[i])
list1 += [loL[loLindex + int1]]
elif strtoList[i] == " ":
list1 += [" "]
for i in range(len(list1)):
newStr += list1[i]
return newStr
You need:
list1 += [loL[(loLindex + int1) % len(loL)]]
for whenever the cypher "loops back to the first letters".
And then
if int1 == len(loL):
int1 = int1 % 26
becomes irrelevant as well.
And BTW, you don't need to build a list and then make it a string. You can grow your string directly too...

Python 3 - TypeError: string indices must be integers / conditional statement

I thought that so long that the if statement is True, then run the line of code. Why is it wanting an integer in the conditional?
#function that accepts a string and calculates the number of upper case and lower case
def case_count(str):
total_cap_cases = 0
total_low_cases = 0
for words in str:
if str[words].isupper():
total_cap_cases += 1
elif words.islower():
total_low_cases += 1
else:
pass
print(total_cap_cases)
print(total_low_cases)
str = "How Many upper and LOWER case lettters are in THIS senTence?"
case_count(str)
When I run this code:
s = "abc"
for words in s:
print(words)
I get this output:
$ python test.py
a
b
c
This is because for variable in string: does not create an integer index. Rather, it assigns the individual characters of the string to variable, one at a time.
When you do for words in str:, you are actually processing the str one character at a time. You would do better to write:
for character in str:
if character.isupper():
tot_cap_cases += 1
elif character.islower():
tot_low_cases += 1
else:
tot_non_cases += 1
(Also, it's worth pointing out that in the world of unicode, you cannot simply assume that any character that is not upper case must be lower case. According to this Unicode FAQ page most scripts do not have case at all.)
There is an error in your code. You should just use words.isupper(): instead of str[words].isupper()
def case_count(str):
total_cap_cases = 0
total_low_cases = 0
for words in str:
if words.isupper():
total_cap_cases += 1
else:
total_low_cases += 1
print(total_cap_cases)
print(total_low_cases)
You're attempting to use a str to index, but it should be of type int.
To fix it, you can simply change:
if str[words].isupper():
to:
if words.isupper():
I also recommend using replace(' ', '') on your str, as the spaces might count when computing the values.
You can iterate string in python, but string isn't list.
it indices must be integers, not str
def case_count(string):
total_cap_cases = 0
total_low_cases = 0
for words in string:
if words.isupper():
total_cap_cases += 1
else:
total_low_cases += 1
print(total_cap_cases)
print(total_low_cases)
OR
def case_count(string):
total_cap_cases = 0
total_low_cases = 0
for idx in range(0, len(string)):
if string[idx].isupper():
total_cap_cases += 1
else:
total_low_cases += 1
print(total_cap_cases)
print(total_low_cases)
plus, do not use str as variable. it's python keyword.
str = "How Many upper and LOWER case lettters are in THIS senTence?"
def case_Counts(String):
print("Capital Letters: ", sum(1 for String in str if String.isupper()))
print("LowerCase Letters: ", sum(1 for String in str if String.islower()))
case_Counts(str)

Testing string against a set of vowels - Python

This is a module in my program:
def runVowels():
# explains what this program does
print "This program will count how many vowels and consonants are"
print "in a string."
# get the string to be analyzed from user
stringToCount = input("Please enter a string: ")
# convert string to all lowercase letters
stringToCount.lower()
# sets the index count to it's first number
index = 0
# a set of lowercase vowels each element will be tested against
vowelSet = set(['a','e','i','o','u'])
# sets the vowel count to 0
vowels = 0
# sets the consonant count to 0
consonants = 0
# sets the loop to run as many times as there are characters
# in the string
while index < len(stringToCount):
# if an element in the string is in the vowels
if stringToCount[index] in vowels:
# then add 1 to the vowel count
vowels += 1
index += 1
# otherwise, add 1 to the consonant count
elif stringToCount[index] != vowels:
consonants += 1
index += 1
# any other entry is invalid
else:
print "Your entry should only include letters."
getSelection()
# prints results
print "In your string, there are:"
print " " + str(vowels) + " vowels"
print " " + str(consonants) + " consonants"
# runs the main menu again
getSelection()
However, when I test this program, I get this error:
line 28, in runVowels
stringToCount = input("Please enter a string: ")
File "<string>", line 1
PupEman dABest
^
SyntaxError: unexpected EOF while parsing
I tried adding a + 1 to the "while index < len(stringToCount)" but that didn't help either. I'm pretty new to python and I don't really understand what's wrong with my code. Any help would be appreciated.
I researched this error, all I found out was that EOF stands for end of file. This didn't help at all with resolving my problem. Also, I understand that sometimes the error isn't necessarily where python says the error is, so I double-checked my code and nothing seemed wrong in my eyes. Am I doing this the round-about way by creating a set to test the string elements against? Is there a simpler way to test if string elements are in a set?
Question resolved. Thank you to all!
Looks like you're using Python 2. Use raw_input(...) instead of input(...). The input() function will evaluate what you have typed as a Python expression, which is the reason you've got a SyntaxError.
As suggested use raw_input. Also you don't need to do this:
while index < len(stringToCount):
# if an element in the string is in the vowels
if stringToCount[index] in vowels:
# then add 1 to the vowel count
vowels += 1
index += 1
# otherwise, add 1 to the consonant count
elif stringToCount[index] != vowels:
consonants += 1
index += 1
# any other entry is invalid
else:
print "Your entry should only include letters."
getSelection()
Strings in Python are iterable, so you can just do something like this:
for character in stringToCount:
if character in vowelSet : # Careful with variable names, one is a list and one an integer, same for consonants.
vowels += 1
elif character in consonantsSet: # Need this, if something is not in vowels it could be a number.
consonants += 1
else:
print "Your entry should only include letters."
This should do just fine. Using a while is not necessary here, and very non-Pythonic imho. Use the advantage of using a nice language like Python when you can to make your life easier ;)
You can count the vowels like so:
>>> st='Testing string against a set of vowels - Python'
>>> sum(1 for c in st if c.lower() in 'aeiou')
12
You can do something similar for consonants:
>>> sum(1 for c in st if c.lower() in 'bcdfghjklmnpqrstvwxyz')
26
Also,
if stringToCount[index] in vowels:
should read
if stringToCount[index] in vowelSet:
Here's another way you could solve the same thing:
def count_vowels_consonants(s):
return (sum(1 for c in s if c.lower() in "aeiou"),
sum(1 for c in s if c.lower() in "bcdfghjklmnpqrstvwxyz"))
To wit:
>>> count_vowels_consonants("aeiou aeiou yyy")
(10, 3)
>>> count_vowels_consonants("hello there")
(4, 6)
Python truly is grand.
The errors in your file run as follows (plus some suggestions):
stringToCount = input("Please enter a string: ")
This should be raw_input if you want what the user typed in as a string.
stringToCount.lower()
The .lower() method returns a new string with its letters lowered. It doesn't modify the original:
>>> a = "HELLO"
>>> a.lower()
"hello"
>>> a
"HELLO"
vowelSet = set(['a','e','i','o','u'])
Here you could just as easily do:
vowelSet = set("aeiou")
Note you also don't strictly need a set but it is indeed more efficient in general.
# sets the vowel count to 0
vowels = 0
# sets the consonant count to 0
consonants = 0
Please, you don't need comments for such simple statements.
index = 0
while index < len(stringToCount):
You usually don't need to use a while loop like this in python. Note that all you use index for is to get the corresponding character in stringToCount. Should instead be:
for c in stringToCount:
Now instead of:
if stringToCount[index] in vowels:
vowels += 1
index += 1
You just do:
if c in vowels:
vowels += 1
elif stringToCount[index] != vowels:
consonants += 1
index += 1
# any other entry is invalid
Not quite right. You're checking that a character doesn't equal a set. Maybe you meant:
elif c not in vowels:
consonants += 1
But then there'd be no else case... Got to fix your logic here.
print "In your string, there are:"
print " " + str(vowels) + " vowels"
print " " + str(consonants) + " consonants"
The above is more pythonically written as:
print "In your string, there are: %s vowels %s consonants" % (
vowels, consonants)
# runs the main menu again
getSelection()
Not sure why you're calling that there - why not call getSelection() from whatever calls runVowel()?
Hope that helped! Enjoy learning this great language.
Bah, all that code is so slow ;). Clearly the fastest solution is:
slen = len(StringToCount)
vowels = slen - len(StringToCount.translate(None, 'aeiou'))
consonants = slen - vowels
...note that I don't claim it's the clearest... just the fastest :)

How do I set characters in a Python string?

I have a function that decrements a whole number parameter represented by a string. For instance, if I pass in the string "100", it should return "99."
def dec(s):
i = len(s) - 1
myString = ""
while (i >= 0):
if s[i] == '0':
s[i] = '9'
i -= 1
else:
s[i] = chr(int(s[i]) - 1)
break
return s
However, Python issues this error.
s[i] = '9'
TypeError: 'str' object does not support item assignment
I am assuming that s[i] cannot be treated as an lvalue. What is a solution around this?
You can do:
s = s[:i] + "9" + s[i+1:]
This takes the part of the string before character index i, appends a 9, then appends the part of the string after character index i. However, doing a lot of string appends like this is not terribly efficient.
The other answer is that if you're dealing with numbers, why not actually use numbers instead of strings?
def dec(s):
return str(int(s) - 1)
Strings aren't mutable, but lists are. You can easily convert the string to a list of individual characters:
l = list(s)
Then convert it back:
s = ''.join(l)
Since you're working with a numeric string there are more direct approaches, but this answer works for the general case.
You can't. In Python, strings are immutable -- once created, they can't be changed.
You have two options without changing your function entirely.
Convert the string to a list and back:
def dec(s):
s = list(s)
i = len(s) - 1
myString = ""
while (i >= 0):
if s[i] == '0':
s[i] = '9'
i -= 1
else:
s[i] = chr(int(s[i]) - 1)
break
return ''.join(s)
Create a new string each time you want to make a change:
def dec(s):
i = len(s) - 1
myString = ""
while (i >= 0):
if s[i] == '0':
s = s[:i] + "9" + s[i+1:]
i -= 1
else:
s = s[:i] + chr(int(s[i]) - 1) + s[i+1:]
break
return s
I'm not sure why you are playing with the string character by character. Isn't this simpler?
def decrement_string(s):
try:
i = int(s)
i = i - 1
return str(i)
except:
# do something else
return "that's no number!"
while True:
s = raw_input("give me a number and I'll decrement it for you: ")
print decrement_string(s)
The solution to your specific problem of "decrementing" strings is to convert s to an int with int(s), decrease that, and convert back to a str: str(int(s)-1).
In [175]: str(int('100')-1)
Out[175]: '99'
The general solution is to not attempt to alter the elements of a string; use some other type to represent your work, and convert to a string as the last step.
Python strings are immutable so you cannot modify them. You have to create a new string that contains the value that you need. You are better off converting the string to an integer, decrementing it, and then converting it back to an integer again.
The reason for immutable strings is primarily efficiency.

noob python question, extract letter from list

not sure why this isn't working.
error I'm getting: ord() expected a character, but string of length 0 found
code:
phrase = 'test'
number = 0
text = 0
random1 = ''
while (number <= len(phrase)):
letter = phrase[number:number+1]
text = ord(letter) - ord('a')
....
number = number + 1
if a print letter, i get the t for the first iteration
thanks,
You are failing on your last iteration. Because you let number take the value len(phrase), you are trying to slice your string beyond the end.
For example:
>>> "abc"[3:4]
''
String indices range from 0 to len(s)-1.
BTW: Python gives you much nicer ways to iterate over strings:
phrase = 'test'
for letter in phrase:
text = ord(letter) - ord('a')
....
You are iterating past the end of phrase, try this:
phrase = 'test'
number = 0
text = 0
random1 = ''
while (number < len(phrase)):
letter = phrase[number:number+1]
text = ord(letter) - ord('a')
Note the:
while (number < len(phrase)):
You do indeed have to show more code. What is i? Are you incrementing it each loop?
Typically, if you ARE incrementing i to act just like a for loop, you want to loop such that number < len(phrase), not <=.
Also, you can replace
letter = phrase[number:number+1]
with
letter = phrase[number]
Use for..in instead to process each letter in your string:
Code:
phrase = 'test'
for letter in phrase:
print letter
Output:
t
e
s
t
This would be the more "pythonic" way of doing character iteration. This way you're guaranteed to hit every letter without having to consider hitting the end, as what's happening in your code.
You want a char and not a string, right? Try to replace your
letter = phrase[number:number+1]
with
letter = phrase[number]

Categories