Python encryptor issues - python

I have been working on an encryption software and I got to the code given. But now I’m stuck. I need a way to get the encrypted letter out from the function.
num = input()
word = input()
num = int(num)
def encrypt(letter, var):
if letter == "a":
var = "m"
if letter == "b":
var = "n"
if letter == "c":
var = "b"
if letter == "d":
var = "v"
if letter == "e":
var = "c"
if letter == "f":
var = "x"
if letter == "g":
var = "z"
if letter == "h":
var = "p"
if letter == "i":
var = "o"
if letter == "j":
var = "i"
if letter == "k":
var = "u"
if letter == "l":
var = "y"
if letter == "m":
var = "t"
if letter == "n":
var = "r"
if letter == "o":
var = "e"
if letter == "p":
var = "w"
if letter == "q":
var = "q"
if letter == "r":
var = "a"
if letter == "s":
var = "s"
if letter == "t":
var = "d"
if letter == "u":
var = "f"
if letter == "v":
var = "g"
if letter == "w":
var = "h"
if letter == "x":
var = "j"
if letter == "y":
var = "k"
if letter == "z":
var = "l"
list = list(word)
if num == 1:
if num == 2:
var1, var2 = word
if num == 3:
if num == 4:
if num == 5:
if num == 6:
if num == 7:
if num == 8:
if num == 9:
if num == 10:
if num == 11:
if num == 12:
if num == 13:
if num == 14:
if num == 15:
Basically what happens is the first section (ends with the carriage return) just takes the word you want to encrypt and how long it is. Then the second section is the actual encryption which would recive the letter it is encrypting and the variable it would be. Such as the input would be encrypt(y, var1) and it would output the letter y would be encrypted then outputted as var1. Then the final section (which is unfinished) would be what takes the word turns it into a list then turns that list into a single letter then it outputs that to the encrypter.
Can someone give help on the final section and how to get an output from the mid section.
Note: this is an encryper not a decrypter. That’s part 2

Your code has a few problems.
You repeat the same code a lot, which isn't needed; what you're creating is what's called a substitution cipher and you're basically just replacing specific characters with another specific character.
You want to replace the letters one at a time and are looking to put the text in a string in a list to do so; you don't have to though, Python allows you to loop over a string just as easily as over a list.
You are trying to modify a variable you passed to a function (var), but that doesn't work for immutable types like a string; you can either return a value from the function, or pass it a mutable type (like a list) and modify that.
You picked a cipher that's very easy to guess; a substitution cipher is very easy to crack to begin with, but picking a cipher that's literally in front of everyone with a keyboard may be a bit much :)
This would do the same:
def encrypt(letter):
key = 'abcdefghijklmnopqrstuvwxyz'
cipher = 'mnbvcxzpoiuytrewqasdfghjkl'
return cipher[key.index(letter)]
word = input()
letters = list(word)
encrypted_letters = [encrypt(ch) for ch in word]
print('Encrypted:' + ''.join(encrypted_letters))
That still turns the word into a list, but since the number you were reading didn't really affect anything, I left it out.
It returns the encrypted letter and those are captured one at a time in what's known as a 'list comprehension': [encrypt(ch) for ch in word], resulting in a list of encrypted characters.
This still naively goes through 'encryption' one letter at a time, but it just looks up the position of the letter in the key, and then returns the letter at the same position in the cipher - a lot shorter.
It could be a lot simpler still though:
CIPHER = {chr(i + 97): replacement for i, replacement in enumerate('mnbvcxzpoiuytrewqasdfghjkl')}
def encrypt(s):
return ''.join(CIPHER[letter] if letter in CIPHER else letter for letter in s)
word = input()
print(f'Encrypted: {encrypt(word)}')
Here, the cipher is created as a dictionary, which is the ideal way to look up a value (that's what it's for). And it's created outside the function, so it only gets created once, since it doesn't change.
The cipher uses the fact that the characters of the alphabet (in lowercase) can be generated by a function chr() by giving it the ascii code for a character, 97 for 'a', 98 for 'b', etc. That way, you don't have to include the alphabet in the code again.
The function just loops over the letters in the word itself and returns the encrypted word - already joined back together.
And instead of just adding the strings together in the print line, that uses a so-called f-string to print the returned value inside the string, making it all a bit easier to read and avoiding some complications in many cases.

Related

How to make a function checking how many consonants or vowels are in a string?

I'm doing Georgia Tech's CS1301xII course, and I have been stumped by this question.
I am supposed to make a function called count_letters. If find_consonants is true, then it counts consonants, or vowels if it is false. It should only return vowels and consonants, no uppercase letters, spaces, numbers, or punctuation. The output I get is 0 consonants, then 1 vowel. I expected 14, then 7.
def count_letters(string, find_consonants):
if find_consonants == True:
count = 0
for i in string:
if i == ("q" or "w" or"r" or "t" or "y" or "p" or "s" or "d" or "f" or "g" or "h" or "j" or "k" or "l" or "z" or "x" or "c" or "v" or "b" or "n" or "m"):
count += 1
return count
else:
count = 0
for i in string:
if i == ("a" or "e" or "i" or "o" or "u"):
count += 1
return count
(The next section is just for me to test myself, the autograder changes the string)
a_string = "up with the white and gold"
print(count_letters(a_string, True))
print(count_letters(a_string, False))
The or operation in python is lazy evaluation, like:
>>> ('a' or 'c')
'a'
>>> ('c' or 'b' or 'a')
'c'
so i == ("a" or "e" or "i" or "o" or "u") equivalent to i == 'a', is not the result you want.
You can change it like
Option1
This is crazy...though
count = 0
for i in string:
if (i == "a") or (i == "e") or (i == "i") or (i == "o") or (i == "u"):
count += 1
Option2
This one is more elegant.
count = 0
for i in string:
if i in 'aeiou':
count += 1
Option3
And this is Python
len([x for x in string if x in 'aeiou'])
The test if find_consonants == True is a bit overengineered. if find_consonants suffices. You might also want to make use of list comprehensions, to avoid the explicit loops.
This should work for instance:
def count_letters(s, find_consonants):
if find_consonants:
return len([l for l in s if l in "bcdfghjklmnpqrstvwxyz"])
return len([l for l in s if l in "aeiou"])
Sadly, you can't use if var == "foo" or "bar"; you'd have to write if var == "foo" or var == "bar".
For your function, try something like:
def count(string, count_consonants):
vowelcount = 0
consonantcount = 0
for letter in string:
if letter in "aeiou": #Detect if letter is in vowel list
vowelcount += 1
elif letter in "bcdfghjklmnpqrstvwxyz":
consonantcount += 1
if count_consonants:
return consonantcount
else:
return vowelcount
#ObseleteAwareProduce's solution is correct and addresses the concept of checking if an item matches any item in a specific list. But as far as finding vowels and consonants, we can use re library as well
import re
regex = re.compile("a|e|i|o|u", flags=re.I)
vowels_count = len(regex.finditer(input_string))

Negating string comparison in `if` confusing

The output of this confuses me! when the output of == are N and M, Shouldn't the output of != be A and I?. Word entered is "Nima".
word = input("Enter a word:")
UpperWord= word.upper()
for letter in word:
if letter == "A":
continue
elif letter == "E":
continue
elif letter == "I":
continue
elif letter == "O":
continue
elif letter == "U":
continue
else:
print(letter)
word = input("Enter a word:")
UpperWord= word.upper()
for letter in word:
if letter != "A":
continue
elif letter != "E":
continue
elif letter != "I":
continue
elif letter != "O":
continue
elif letter != "U":
continue
else:
print(letter)
The condition if letter != "A" is true for all letters but 'A', and for all of them, you execute continue and skip to the next iteration of the loop. The elif letter != "E" statement is executed only when the letter is 'A'. Since the letter is already known to be 'A', the condition is always true and the second continue statement is always executed. The second code fragment never produces any output.
Here's what you want:
for letter in UpperWord:
if letter not in "AEUIO":
continue
print(letter)
As DYZ says, the second code fragment would never produce output, because it actually continues the loop for all letters.
Remember, thee code executes from top to bottom, so to avoid this issue, check all of the vowels at once.
You also initialize UpperWord, but never use it, so unless the character is uppercase, it will always fall through. Here is the combination of both fixes:
vowelString = "AEIOU"
word = input("Enter a word:")
upperWord= word.upper()
for letter in upperWord:
if letter not in vowelString:
print(letter)
If you're up for it, I would also recommend researching Regular Expressions, or RegEx. This is a pattern-matching system that would make it much easier to match things going forward.
The solution with regex would look like:
import re
vowelRegex = re.compile(r"[aeiouAEIOU]")
word = input("Enter a word:")
for letter in word:
if vowelRegex.match(letter)==None:
print(letter)
This would easily allow you to expand your searched characters, as well as expanding to searching for more complex patterns.
Python Regex Documentation
Regex Playground

Is there a program that will only return the constants in a word python

I would like to write a program that asks the user for a word and only returns the constants. But I am stuck with this program, I would expect this program to do what I have mentioned above, but all it does is returns the word row by row.
original = input('Enter a word:')
word = original.lower()
first = word[0]
second = word[1]
third = word[2]
fourth = word[3]
fifth=word[4]
if first == "a" or "e" or "i" or "u":
print (first)
else:
print ("")
if second == "a" or "e" or "i" or "u":
print (second)
else:
print ("")
if third == "a" or "e" or "i" or "u":
print (third)
else:
print ("")
if fourth == "a" or "e" or "i" or "u":
print (fourth)
else:
print ("")
if fifth == "a" or "e" or "i" or "u":
print (fifth)
else:
print ("")
Strip all the vowels from a word and print it:
original = input('Enter a word:')
print("".join(x for x in original if x.lower() not in "aeiou"))
The precedence is wrong. "or" has higher precedence then "==" - see https://docs.python.org/2/reference/expressions.html#operator-precedence
So the line:
if first == "a" or "e" or "i" or "u":
Is the same as:
if (first == "a") or ("e") or ("i") or ("u"):
Which I suspect isn't what you wanted. The following might work better:
if first in "aeiu":
However also note this is case sensitive...

Python String Help Hawaiian Word Pronunciation

I am having trouble figuring out why my code is not printing out anything after I input a value for word. I can input a word, but it does not output anything after evaluating through the while loop. What are your thoughts?
ai = "eye-"
ae = "eye-"
ao = "ow-"
au = "ow-"
ei = "ay-"
eu = "eh-oo-"
iu = "ew-"
oi = "oy-"
ou = "ow-"
ui = "ooey-"
a = "ah-"
e = "eh-"
i = "ee-"
o = "oh-"
u = "oo-"
p = "p"
k = "k"
h = "h"
l = "l"
m = "m"
n = "n"
word = input("Please enter a Hawaiian word you want pronounced")
character_count1 = int(0)
character_count2 = int(1)
pronunciation = ""
while character_count1 < len(word):
if word[character_count1:character_count2] == ai or word[character_count1:character_count2] == "ae"or word[character_count1:character_count2] == "ao"or word[character_count1:character_count2] == "ei"or word[character_count1:character_count2] == "eu"or word[character_count1:character_count2] == "iu"or word[character_count1:character_count2] == "oi"or word[character_count1:character_count2] == "ou":
print("your word",pronunciation + word[character_count1:character_count2])
character_count1 + 2 and character_count2 + 2
elif word[character_count1:character_count1] == a or word[character_count1:character_count1] == e or word[character_count1:character_count1] == i or word[character_count1:character_count1] == o or word[character_count1:character_count1] == p or word[character_count1:character_count1] == k or word[character_count1:character_count1] == h or word[character_count1:character_count1] == l or word[character_count1:character_count1] == m or word[character_count1:character_count1] == n:
print("your word",pronunciation + word[character_count1:character_count1] )
character_count1 + 1 and character_count2 + 1
What are you trying to achieve is pretty easy, if you use a data structure called dictionary, a very basic data structure in python. Change the data structure like that:
dic={"ai" :"eye-","ae" :"eye-","ao": "ow-","au" :"ow-"......}
Now you can access the values (Pronunciation) with the keys (words).
like this,
dic["ai"]
You will get:
eye-
So, now let's try to get the solution:
Define a dictionary.
dic={"ai" :"eye-","ae" :"eye-","ao": "ow-","au" :"ow-"......}
Take the input, better use raw_input if you are not using python3
word = raw_input("Please enter a Hawaiian word you want pronounced")
Split the input by white spaces and form a list.
lst=word.split()
Use the elements of lst as dictionary key to find the value. Iterate through the list and check if the input matches to any key of dic
for i in lst:
print dic.get(i)
None will be printed if the key doesn't exist.
As, your requirement isn't quite clear to me, i have included all the things needed to solve the problem.
So, use them where needed and solve the problem.
Happy coding.
The folks in the answers and comments who have said "use a dictionary" are right, but you can't just loop through the input a character at a time because you have overlapping matches. Without looking at the next character, you can't tell if "a" is part of "ai" or "an", and those cases are handled differently. Here is a complete solution with annotation that handles the subtlety and provides an informative error message when you encounter an illegal string.
hawaiian_pronunciation = {
"ai": "eye-",
"ae": "eye-",
"ao": "ow-",
"au": "ow-",
"ei": "ay-",
"iu": "ew-",
"oi": "oy-",
"ui": "ooey-",
"a": "ah-",
"e": "eh-",
"i": "ee-",
"o": "oh-",
"u": "oo-",
"p": "p",
"k": "k",
"h": "h",
"l": "l",
"m": "m",
"n": "n"
}
def segment(word, start):
# we have to consider the longest possible segment first
# so that hai gets tokenized h-ai instead of h-a-i
for length in (2,1):
# check if the length of the segment puts us past the end of the word
# the upper bound can be equal to the length of the word since the
# string[upper_bound] is not actually included in the range
if start+length > len(word):
continue
# the input segment we are considering
input = word[start:start+length]
# is it in our dictionary?
if input in hawaiian_pronunciation:
# if it is get the corresponding pronunciation
output = hawaiian_pronunciation[input]
# return the output and length for a successful match
return output, length
# if no candidate matches, raise an exception describing where you were
# when you failed to find a match
raise Exception("cannot match word {} at position {}, bad segment {}",
word, start, word[start:])
def pronounce(word):
"generate pronunciation from word"
# build a list of strings
out = []
# we have to use a while loop and an explicit index
# because we can jump by one or two spaces depending on the length of the match
start = 0
while start < len(word):
# when we get a match, append the new sound and
# advance the appropriate number of spaces
new_sound, length = segment(word, start)
out.append(new_sound)
start += length
return "".join(out)
def main():
print pronounce("hai")
main()

Shortening down this specific code

I have been studying Python for a couple of weeks now, and just after easter, will be having a controlled assesment that will count towards my GCSE grade, for which I will be also marked for the criteria of something like the lentgh of my code.
The question was: Write a Python program that asks the user for a word, then calculates the prints the vowel value of the word entered.
What I want to know:
Is there anyway of shortening down this code?
And also:
How can the program be executed without printing out the "word" variable?
Above I have been given a rubric that I used in the code (in the control flow part).
score = 0
word = str(input("Input a word: "))
c = 0
for letter in word:
print(word[c])
c = c + 1
if letter == "a":
score = score + 5
if letter == "e":
score = score + 4
if letter == "i":
score = score + 3
if letter == "o":
score = score + 2
if letter == "u":
score = score + 1
print("\nThe score for your word is: " + score)
You can use sum and a dict, storing vowels as keys and the associated value as the values:
word = input("Input a word: ")
values = {"a":5,"e":4,"i":3,"o":2,"u":1}
print(sum(values.get(ch,0) for ch in word))
values.get(ch,0) will return 0 as a default value if the ch which is each char in the word is not a vowel therefore not in our dict.
sum(values.get(ch,0) for ch in word) is a generator expression where the variables are evaluated lazily when the next() method is called for generator object
In relation to your own code you should use if/elif's. A character can only have one value, if's are always evaluated but elif's are only evaluated if the previous statement evaluates to False:
score = 0
# already a str in python3 use raw_input in python2
word = input("Input a word: ")
for letter in word:
if letter == "a":
score += 5 # augmented assignment same as score = score + 5
elif letter == "e":
score += 4
elif letter == "i":
score += 3
elif letter == "o":
score += 2
elif letter == "u":
score += 1
Here's the working code:
word = input("Input a word: ")
values = {"a":5,"e":4,"i":3,"o":2,"u":1}
score = sum(values[let] for let in word if let in values)
print("\nThe score for your word is: " + score)

Categories

Resources