Python Caesar cipher changes capitalization of the given input strings - python

In a ceasar cipher I need it to be that my upper characters remain upper and that non letter character remain non letters/the same. I have it that I can work with lower letters.
Upper letters however are converted to lower and a different letter. Non-letter characters are converted to a lower letter as well. Upper letters must shift but remain upper. Non-letter characters must remain as non-letter character.
p = raw_input(("enter a word"))
n = input(("how many must it shift"))
a = 0
b = 0
c = 0
d = 0
for i in p:
if i.isupper():
a += 1
elif i.islower():
b += 1
elif i.isdigit():
c += 1
else:
d += 1
e = ""
for i in p:
if i == "":
e += i
else:
integerValue = ord(i)
integerValue-= 97
integerValue += n
integerValue %= 26
integerValue += 97
e += chr(integerValue)
print e

You can use i.isalpha() to check if the current character is a letter or not and you can use i.isupper() to check if the current letter is uppercase or not. When you convert the letter you will need to make the letter lowercase and then convert it back to upper. On top of those changes you have too many parenthesis for your inputs. I used raw_input since I'm using python 2.7. Your formatting is so off your code that's posted won't run due to indentation errors and your line if i == "" checks for an empty string instead of a space which I am assuming you were going for. All that said here is what I did to your code to try and keep it similar to what you had while cutting out extraneous bits.
p = raw_input("enter a word")
n = int(raw_input("how many must it shift"))
e = ''
for i in p:
if not i.isalpha():
e+=i
else:
integerValue = ord(i.lower())
integerValue-= 97
integerValue += n
integerValue %= 26
integerValue += 97
if i.isupper():
e += chr(integerValue).upper()
else:
e += chr(integerValue)
print e

Related

How to compare two strings by character and print matching positions in python

I want to compare two strings by character and then print how many times they have the same character in the same position. If I were to input 'soon' and 'moon' as the two strings, it would print that they match in 3 positions.
I've run into another problem where if the 2nd string is shorter, it gives me an error "string index out of range".
I tried
a = input('Enter string')
b = input('Enter string')
i=0
count = 0
while i<len(a):
if b[i] == a[i]:
match = match + 1
i = i + 1
print(match, 'positions.')
You have some extraneous code in the form of the 2nd if statement and you don't have the match incrementor in the first if statement. You also don't need the found variable. This code should solve the problem
# get input from the user
A = input('Enter string')
B = input('Enter string')
# set the incrementors to 0
i=0
match = 0
# loop through every character in the string.
# Note, you may want to check to ensure that A and B are the same lengths.
while i<len(A):
# if the current characters of A and B are the same advance the match incrementor
if B[i] == A[I]:
# This is the important change. In your code this line
# is outside the if statement, so it advances for every
# character that is checked not every character that passes.
match = match + 1
# Move to the next character
i = i + 1
# Display the output to the user.
print(match, 'positions.')
num_matching = 0
a = "Hello"
b = "Yellow"
shortest_string = a if len(a) <= len(b) else b
longest_string = b if shortest_string == a else a
for idx, val in enumerate(shortest_string):
if val == b[idx]:
num_matching += 1
print(f"In {a} & {b} there are {num_matching} characters in the same position!")
Simplifying my answer in light of #gog's insight regarding zip versus zip_longest:
string1 = "soon"
string2 = "moon"
matching_positions = 0
for c1, c2 in zip(string1, string2):
if c1 == c2:
matching_positions += 1
print(matching_positions)
Output:
3

How can I resolve maximum recursion depth error

I'm generating a random password with a desired length. I want it to have at least 2 uppercase letters, 2 lowercase letters, 2 digits and 2 special characters. I've tried multiple things, but every time I get this recursion depth error.
Can anybody tell me what I've done wrong?
list_lower =['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']
list_upper = ['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']
list_digit = [1,2,3,4,5,6,7,8,9,0]
def generatePassword(desiredLength: int) -> str:
x = 0
password = ""
for x in range (desiredLength):
password = password + chr(random.randint(33,126))
list(password)
list_password = list(password)
times_lower = 0
times_upper = 0
times_digit = 0
times_special = 0
for character in list_password:
if character in list_lower:
times_lower += 1
elif character in list_upper:
times_upper += 1
elif character in list_digit:
times_digit += 1
else:
times_special +=1
if times_lower >= 2 and times_upper >= 2 and times_digit >= 2 and times_special >= 2:
return password
else:
return generatePassword(desiredLength)
generatePassword(7)
I get the error in line 30 which makes the function recursive.
Calling generatePassword(7) will never generate a password with 2 of each of 4 distinct categories.
You don't need recursion at all.
def generatePassword(desiredLength: int) -> str:
while True:
password = ""
for x in range (desiredLength):
password = password + chr(random.randint(33,126))
times_lower = 0
times_upper = 0
times_digit = 0
times_special = 0
for character in password:
if character in list_lower:
times_lower += 1
elif character in list_upper:
times_upper += 1
elif character in list_digit:
times_digit += 1
else:
times_special +=1
if times_lower >= 2 and times_upper >= 2 and times_digit >= 2 and times_special >= 2:
return password
else
print ("Rejecting ", password)
That will loop forever if asked to generate a password of length 7 or less. We can improve that by checking the desired length first
if desiredLength < 8:
raise ArgumentError("Cannot generate passwords shorter than 8 characters")
times_digit will never be >= 2 because it tests stings (e.g. "2" against the integers in your list, (e.g. 2) change your list_digit to
list_digit = ["1","2","3","4","5","6","7","8","9","0"]
and try again.
By the way this could be done much simpler and doensn't need a recursive function.
If you are generating passwords, it's important that you generate ones that actually have enough randomness to not be predictable.
Random string generation with upper case letters and digits in Python
Has a great breakdown of how to generate a password that's truly random:
''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(N))
(adding "special characters" and "lowercase characters" omitted to preserve the existing code)
I know that this is a somewhat oblique answer (i.e. it does not answer the question directly), so here's a potential solution if you still need the "it must contain these types of characters" (even though that would actually reduce security):
import random
import string
from collections import Counter
def gen(N):
return ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits + string.punctuation) for _ in range(N))
while True:
pw = gen(8)
counts = Counter(pw)
upper = lower = digit = special = 0
for (letter, count) in counts.items():
if (letter in string.ascii_lowercase):
lower += 1
elif (letter in string.ascii_uppercase):
upper += 1
elif (letter in string.digits):
digit += 1
else:
special += 1
pass
if (lower > 1 and upper > 1 and digit > 1 and special > 1):
print("password is {}".format(pw))
break
print("failed password: {}".format(pw))

Write a Python function that accepts a string and calculate the number of upper case letters and lower case letters

Question:
Write a Python function that accepts a string and calculate the number of upper case letters and lower case letters.
Sample String : 'Hello Mr. Rogers, how are you this fine Tuesday?'
Expected Output :
No. of Upper case characters : 4
No. of Lower case Characters : 33
function:
def up_low(s):
for a in s:
u = u.count(a.isupper())
l = l.count(a.islowwer())
print(u, l)
why this one doesn't work?
You can use List comprehensions and sum function to get the total number of upper and lower case letters.
def up_low(s):
u = sum(1 for i in s if i.isupper())
l = sum(1 for i in s if i.islower())
print( "No. of Upper case characters : %s,No. of Lower case characters : %s" % (u,l))
up_low("Hello Mr. Rogers, how are you this fine Tuesday?")
Output:
No. of Upper case characters : 4,No. of Lower case characters : 33
You are understanding wrong the count function, count, first of all, is a string functrion, and as parameter take a string, instead of doing this, you can simply do:
def up_low(string):
uppers = 0
lowers = 0
for char in string:
if char.islower():
lowers += 1
elif char.isupper():
uppers +=1
else: #I added an extra case for the rest of the chars that aren't lower non upper
pass
return(uppers, lowers)
print(up_low('Hello Mr. Rogers, how are you this fine Tuesday?'))
4 33
Problem
why this one doesn't work?
Along with having syntax errors and run-time errors, you code's logic is quite a ways off. You are actual not doing what the question asked. You seem to be trying to count the number of uppercase characters in a single character. That's incorrect.
Let's look back over the question to implement this correctly:
Write a Python function that accepts a string and calculate the number of upper case letters and lower case letters. Sample String : 'Hello Mr. Rogers, how are you this fine Tuesday?' Expected Output : No. of Upper case characters : 4 No. of Lower case Characters : 33.
Ok, so we have a clear definition of our problem. Given a single string, count the number of lower case characters the string contains, and uppercase characters the string contains. Let's start writing our function.
First we should define a function:
def count_upper_and_lower(string):
I know we'll need two variables; How? Because we need one to count the uppercase letters, and one to count the lowercase letters. So let's initialize those:
def count_upper_lower(string):
lowercase_letter_count = 0
uppercase_letter_count = 0
Now what do we need? Well the problem says to count each letter in the string. It sounds like we need to iterate over each character in the string. So we should use a for loop:
def count_upper_lower(string):
lowercase_letter_count = 0
uppercase_letter_count = 0
for letter in string:
OK, so what logic do we need in our for loop? Well we need to first check if a letter is upper case. If it is, we need to increment uppercase_letter_count. If not, we'll then test if the character is lowercase. If so, we'll increment lowercase_letter_count. Otherwise, we'll do nothing. Here is what that would look like in code:
if letter.isupper():
uppercase_letter_count += 1
elif letter.islower():
lowercase_letter_count += 1
Let's add that to our for loop:
def count_upper_lower(string):
lowercase_letter_count = 0
uppercase_letter_count = 0
for letter in string:
if letter.isupper():
uppercase_letter_count += 1
elif letter.islower():
lowercase_letter_count += 1
And were done. All that's left to do is to print the values at the end of the function:
def count_upper_lower(string):
lowercase_letter_count = 0
uppercase_letter_count = 0
for letter in string:
if letter.isupper():
uppercase_letter_count += 1
elif letter.islower():
lowercase_letter_count += 1
print uppercase_letter_count, lowercase_letter_count
Demo
def count_upper_lower(string):
lowercase_letter_count = 0
uppercase_letter_count = 0
for letter in string:
if letter.isupper():
uppercase_letter_count += 1
elif letter.islower():
lowercase_letter_count += 1
print uppercase_letter_count, lowercase_letter_count
count_upper_lower("Hello Mr. Rogers, how are you this fine Tuesday?")
# Output: 4 33
count_upper_lower("The FAT Cat Moaned AlL day!")
# Output: 8 13
If people are posting code...
def up_low(s):
up = filter(str.isupper, s)
low = filter(str.islower, s)
return len(up), len(low)
In Python 3, each filter will need to be converted into a list or thrown into a sum(1 for _ in ...) expression:
def up_low(s):
counter = lambda f: sum(1 for c in s if f(c))
return counter(str.upper), counter(str.lower)
A bit late to the party, but for the sake of completeness:
import string
def up_low(s):
return (sum(map(s.count, string.ascii_uppercase)),
sum(map(s.count, string.ascii_lowercase)))
And to test it:
u, l = up_low('Hello Mr. Rogers, how are you this fine Tuesday?')
print("No. of Upper case characters : {}\nNo. of Lower case Characters : {}".format(u, l))
Which gives:
No. of Upper case characters : 4
No. of Lower case Characters : 33
A manual loop & count is probably faster, tho.
I think this is the easiest approach for a beginner.
def up_low(s):
a=list(s)
u=[]
l=[]
for x in a:
if x.isupper():
u.append(x)
elif x.islower():
l.append(x)
else:
pass
return u, l
u, l = up_low(s)
print(f'No. of Upper case characters: {len(u)}')
print(f'No. of Lower case Characters: {len(l)}')
One simple
def up_low(s):
c_upper = 0
c_lower = 0
for letters in s:
if letters.isupper():
c_upper += 1
elif letters.islower():
c_lower += 1
else:
pass
print("Total characters :",len(s.replace(" ", "")),"\nNo. of Upper case characters :",c_upper, "\nNo. of Lower case Characters :",c_lower)
INPUT
mystring = 'Hello Mr. Rogers, how are you this fine Tuesday?'
up_low(mystring)
OUTPUT
Total characters : 40
No. of Upper case characters : 4
No. of Lower case Characters : 33
def up_low(s):
u, l = [], []
for a in s:
if a.isupper():
u.append(a)
else:
l.append(a)
print(len(u), len(l))

Trying to solve a beginner Python looping assignment

I have to make a program that asks the user for a String and then counts and prints the number of vowels in the String. The vowels that count are a, e, i, o, u, y, and the uppercase versions of these. For example, the input "ebony and ivory" would print 7. I also can't use any built-in string functions for this problem.
This is what I have so far:
userString = str(input("Please enter a string:"))
numVowels = 0
n=0
a=0
e=0
i=0
o=0
u=0
y=0
while (ord(userString[n]) != 0 or ord(userString[n+1])!=0):
if (userString[n] == 'a' or userString[n]=='A'):
a += 1
numVowels += 1
elif (userString[n] == 'e' or userString[n]=='E'):
e += 1
numVowels += 1
elif (userString[n] == 'i' or userString[n]=='I'):
i += 1
numVowels += 1
elif (userString[n] == 'o' or userString[n]=='O'):
o += 1
numVowels += 1
elif (userString[n] == 'u' or userString[n]=='U'):
u += 1
numVowels += 1
elif (userString[n] == 'y' or userString[n]=='Y'):
y += 1
numVowels += 1
n+=1
print("There are", numVowels, "vowels. There are", a, "A's", e, "E's", i, "I's", o, "O's", u, "U's, and", y, "Y's, including both uppercase and lowercase versions.")
However I keep getting the error:
IndexError: string index out of range
I am using Python 3.
First, you don't need to look at userString[n+1]. Trying to do so when n is already the last index is the first thing that triggers that error message.
Second, even if you remove that test, your loop will still not terminate when it should, because the nul character it's looking for at the end of the string is an implementation detail in the runtime of the C code that comprises the Python interpreter. From Python itself, that character is inaccessible, so ord(userString[n]) will never be 0 for any n unless you explicitly put a "\0" in the string at the Python level. Failing that, the loop will sail past the end of the string and trigger the same IndexError when you try to access userString[n] with n equal to the length of the string.
There are better ways to loop through a string in Python, but the simplest fix for your code is to change the while condition to this:
while n < len(userString):
If len counts as a "built-in string function", which is debatable, then you should just loop over the string in a more typical Pythonic way:
for ch in userString:
if (ch == 'a' or ch=='A'):
a += 1
numVowels += 1
...
There are improvements that can be made to the conditional code that checks for vowels as well (as in mbaytas's answer), but that wasn't your question.
In Python, you can iterate over a string, like you would over a list.
Exploiting this functionality, and using a list to store the vowels, you can use something along the lines of the following code to achieve the functionality you want:
inputString = "This is our input string."
vowels = ["A", "E", "I", "O", "U", "Y", "a", "e", "i", "o", "u", "y"]
vowelCount = 0
for character in inputString:
if (character in vowels):
vowelCount += 1
print vowelCount
I see that your code in the question makes use of conditionals and loops, but not lists. If you'd like to avoid using lists for some reason (e.g. not covered in class yet), you can do the following:
inputString = "This is our input string."
vowelCount = 0
for character in inputString:
if (character == 'A' or
character == 'E' or
character == 'I' or
character == 'O' or
character == 'U' or
character == 'Y' or
character == 'a' or
character == 'e' or
character == 'i' or
character == 'o' or
character == 'u' or
character == 'y'):
vowelCount += 1
print vowelCount
You can also modify the code above using elif statements instead of or logic to break down the occurrence of each vowel.
If you'd like to avoid using the for ... in ... functionality and stick to the while loop, consider the following:
vowelCount = 0
index = 0
while (index < len(inputString)):
if (inputString[index] in vowels):
vowelCount += 1
index += 1
Python offers many features that make solving problems like this a joy. Dictionary comprehensions, list comprehensions, etc.:
vowels = {v: 1 for v in 'aeiouyAEIOUY'}
def num_vowels(input_string):
return sum(vowels.get(character, 0) for character in input_string)
print(num_vowels(str(input("Please enter a string:")))
It's always a good approach to implement the general case first and derive your special case from that. I assumed that you can are "allowed" to use a dict. I avoided built-in methods of str for this.
def count_chars(s, chars):
cdict = {i:0 for i in chars}
for c in s:
try:
cdict[c] += 1
except KeyError:
pass
return cdict
def count_vowels(s):
chars = ['a','e','i','o','u', 'y', 'A', 'E', 'I', 'O', 'U', 'Y']
vowels = count_chars(s, chars=chars)
return vowels, sum(vowels.values())
# test it
tally, total = count_vowels(str(input()))
print(tally, total)
I will give it a try too :)
code below individual vowel and sum that up for total vowels count
input_string = str(input("Please enter a string: "))
vowel = [['a','A'], ['e','E'], ['i','I'], ['o','O'], ['u','U'], ['y','Y']]
vc = [0] * 6 # individual vowel count
for ch in input_string:
for i,v in enumerate(vowel):
if ch in v:
vc[i] += 1
total = sum(vc)
print("There are", total, "vowels.")
print("There are {0} A's {1} E's {2} I's {3} O's {4} U's, and {5} Y's, including both uppercase and lowercase versions.".format(*vc))

python password checker: numbers and symbols

I'm new to python and I'm having a problem. I need to check a password on its upper, lower, numbers and symbols. It needs 1 of each class and the whole password needs to be longer then 6 characters. I have upper and lower case so far. raw_input inputs as a string so how can I then check for numbers and symbols in that string?
My code so far:
p = raw_input(("plz enter a password to check it's strength"))
if len (p) <= 6:
if p.isupper() or p.islower() or int(p):
print"This is a weak password "
elif len(p) > 6 and len(p) <26:
if p.isupper() or p.islower() or isdigit():
print "wea2k"
else:
print "good"
So what I need to know is how to check the input for numbers and symbols.
Try taking the requirements one at a time.
has_upper = False
for char in p:
if char.isupper():
has_upper = True
break
Repeat this for lower case and digits.
For special characters, use the same type of loop, but change the if to something like this:
if not (char.isupper() or char.islower() or char.isdigit()):
At the end, if all four flags are true, then you have a strong password; otherwise, it's weak.
Can you finish the coding from there?
Just so you know, there are ways to code this that are far more "Pythonic" -- that use the language's style much better. For instance:
has_upper = reduce(lambda a, b: a or b.isupper(), [_ for _ in p], False)
... replaces the entire 5-line block that I gave you.
Try this:
p = raw_input(("plz enter a password to check it's strength"))
upper_case = 0
lower_case = 0
number = 0
symbol = 0
for i in p:
if i.isupper():
upper_case += 1
elif i.islower():
lower_case += 1
elif i.isdigit():
number += 1
else:
symbol += 1
if len (p) <= 6:
print"This is a weak password "
elif upper_case > 0 and lower_case > 0 and number > 0 and symbol > 0:
print "Good"
else:
print "Too Weak"

Categories