Related
I want to write a function that encrypt text using caesar cipher. But I want to let non-letters characters to be the same.
I have list with alphabet and a "questions for user"
alphabet = ['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']
direction = input("Type 'encode' to encrypt, type 'decode' to decrypt:\n").lower()
text = input("Type your message:\n").lower()
shift = int(input("Type the shift number:\n"))
This is function which should let non-letters to be in code non changed
def encrypt(text, shift):
text_encrypted = [] # blank text
for letter in text: # check every letter
indeksik = alphabet.index(letter)
if indeksik == None:
text_encrypted.append(letter)
else:
text_encrypted.append(alphabet[indeksik + shift])
But then I'm getting this error:
Tracebac k (most recent call last):
File "C:\Users\mateu\PycharmProjects\Cipher\main.py", line 25, in <module>
encrypt(text, shift)
File "C:\Users\mateu\PycharmProjects\Cipher\main.py", line 16, in encrypt
indeksik = alphabet.index(letter)
ValueError: ' ' is not in list
I know that ' ' is not in list. That's the point - how I can still append to another list these spaces and other non-alphabetical characters?
(Yes, I know that in this moment it will crash when I will shift letter "beyond z" - but I will work with this later)
index() raises a ValueError exception if the value is not in the list. You can do something like:
if letter in alphabet:
# Found the letter
else:
# Not found
The other possible solution is to handle the exception itself, but I'd probably go with the first one.
For
indeksik = alphabet.index(letter)
If letter is not found in alphabet, a ValueError exception is raised.
for letter in text: # check every letter
if letter in alphabet:
indeksik = alphabet.index(letter)
text_encrypted.append(alphabet[indeksik + shift])
else:
text_encrypted.append(letter)
If you use a string, preferably not typing (and possibly mistyping) it yourself, then you can use find and you'll get -1 instead of an error:
>>> from string import ascii_lowercase as alphabet
>>> alphabet.find('c')
2
>>> alphabet.find(' ')
-1
Pig Latin translator is basically an introductory code for many projects, and it involves getting words that start with consonants to move the first letter to the end of the word and add 'ay', and adding only 'ay' to a word that starts with a vowel. I have basically finished the whole project except for some places, and one main thing is getting the program to complete a whole sentence with a for loop, especially in moving to the next list item
I have tried to do simple things such as n+1 at the end of the for loop, and researched online (majority on Stackoverflow)
latin = ""
n = 0
sentence = input ("Insert your sentence ")
word = sentence.split()
first_word = word [n]
first_letter = first_word [0]
rest = first_word [1:]
consonant = ['b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'z')
vowel = ['a', 'e', 'i', 'o', 'u')
for one in consonant :
latin = latin + " " + rest + one + "ay"
print (latin)
n + 1
for one in vowel :
latin = latin + " " + first_word +ay
print (latin)
n + 1
There was no error message, however, the computer ran the variable 'one' not as the first (zeroth) letter of the variable first_word, rather, just running it from a - z. Is there anyway to fix this? Thank you
#!/usr/bin/env python
sentence = input("Insert your sentence ")
# don't forget "y" :)
consonants = ['b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z']
# this empty list will hold our output
output_words = list()
# we'll take the user's input, strip any trailing / leading white space (eg.: new lines), and split it into words, using spaces as separators.
for word in sentence.strip().split():
first_letter = word[0]
# check if the first letter (converted to lower case) is in the consonants list
if first_letter.lower() in consonants:
# if yes, take the rest of the word, add the lower case first_letter, then add "ay"
pig_word = word[1:] + first_letter.lower() + "ay"
# if it's not a consonant, do nothing :(
else:
pig_word = word
# add our word to the output list
output_words.append(pig_word)
# print the list of output words, joining them together with a space
print(" ".join(output_words))
The loop loops over each word in the sentence - no need to count anything with n. There's also no need to loop over the consonants or the vowels, all we care about is "does this word start with a consonant" - if yes, modify it as per your rules.
We store our (possibly) modified words in an output list, and when we're done, we print all of them, joined by a space.
Note that this code is very buggy - what happens if your user's input contains punctuation?
I opehay hattay elpshay, eyuleochoujay
I'm trying to count punctuations that are: apostrophe (') and hyphen (-) using dictionaries. I want to see if I can pull this off using list/dictionary/for loops and boolean expressions. These punctuations MUST ONLY BE COUNTED if they are surrounded by any other letters! E.g. jack-in-a-box (that is 3 hyphens) and shouldn't (1 apostrophe). These letters can be anything from a to z. Also, since this is part of an assignment, no modules/libraries can be used. I'm out of ideas and don't know what to do.
Any help would be greatly appreciated.
This is what I tried: but I get an KeyError: 0
def countpunc2():
filename = input("Name of file? ")
text = open(filename, "r").read()
text = text.lower() #make all the words lowercase (for our convenience)
for ch in '!"#$%&()*+./:<=>?#[\\]^_`{|}~':
text = text.replace(ch, ' ')
for ch in '--':
text = text.replace(ch, ' ')
words = text.split('\n') #splitting the text for words
wordlist = str(words)
count = {} #create dictionary; the keys/values are added on
punctuations = ",;'-"
letters = "abcdefghijklmnopqrstuvwxyz"
for i, char in enumerate(wordlist):
if i < 1:
continue
if i > len(wordlist) - 2:
continue
if char in punctuations:
if char not in count:
count[char] = 0
if count[i-1] in letters and count[i+1] in letters:
count[char] += 1
print(count)
UPDATE:
I changed the code to:
def countpunc2():
filename = input("Name of file? ")
text = open(filename, "r").read()
text = text.lower() #make all the words lowercase (for our convenience)
for ch in '!"#$%&()*+./:<=>?#[\\]^_`{|}~':
text = text.replace(ch, ' ')
for ch in '--':
text = text.replace(ch, ' ')
words = text.split('\n') #splitting the text for words
wordlist = str(words)
count = {} #create dictionary; the keys/values are added on
punctuations = ",;'-"
letters = "abcdefghijklmnopqrstuvwxyz"
for i, char in enumerate(wordlist):
if i < 1:
continue
if i > len(wordlist) - 2:
continue
if char in punctuations:
if char not in count:
count[char] = 0
if wordlist[i-1] in letters and wordlist[i+1] in letters:
count[char] += 1
print(count)
While it is giving me an output it is not correct.
Sample file: https://www.dropbox.com/s/kqwvudflxnmldqr/sample1.txt?dl=0
The expected results must be: {',' : 27, '-' : 10, ';' : 5, "'" : 1}
I'd probably keep it simpler than that.
#!/usr/bin/env python3
sample = "I'd rather take a day off, it's hard work sitting down and writing a code. It's amazin' how some people find this so easy. Bunch of know-it-alls."
punc = "!\"#$%&\'()*+,-./:;<=>?#[\\]^_`{|}~"
letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
d = {}
for i, char in enumerate(sample):
if i < 1:
continue
if i > len(sample) - 2:
continue
if char in punc:
if char not in d:
d[char] = 0
if sample[i - 1] in letters and sample[i + 1] in letters:
d[char] += 1
print(d)
Output:
{"'": 3, ',': 0, '.': 0, '-': 2}
Dunno where you're getting the ";" from. Also your comma has a space next to it.. so it doesn't count here.. if that does count add a space to the letters variable.
Explanation of what's happening:
We initiate a dict and read in sample text as sample and iterate it character by character, using enumerate to play with the indexes. If it is too close to the end or start to qualify, we skip it.
I check the character before and after the one we're at using the i variable from enumerate. and add to it's count if it qualifies.
NOTE: despite the shebang, this code works in python2
You could map the characters of your input string into 3 categories: alphabetic(a), punctuation(p) and spaces(s). Then group them in triples (sequences of 3 characters). From those, isolate the a-p-a triples and count the number of distinct punctuation characters.
for example:
string="""jack-in-a-box (that is 3 hyphens) and shouldn't (1 apostrophe)."""
categ = [ "pa"[c.isalpha()] if c != " " else "s" for c in string ]
triples = [ triple for triple in zip(categ,categ[1:],categ[2:]) ]
pChars = [ p for p,triple in zip(s[1:],triples) if triple==("a","p","a") ]
result = { p:pChars.count(p) for p in set(pChars) }
print(result) # {"'": 1, '-': 3}
If you're not allowed to use isAlpha() or zip(), you can code the equivalent using the in operator and for loops.
Here is an example that does it in a very spelled out way:
end_cap_characters = ['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', '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']
special_characters = [";", ":", "'", "-", ","]
def count_special_characters(in_string):
result = {}
for i in range(1, len(in_string) - 1):
if in_string[i - 1] in end_cap_characters:
if in_string[i + 1] in end_cap_characters:
if in_string[i] in special_characters:
if in_string[i] not in result:
result[in_string[i]] = 1
else:
result[in_string[i]] +=1
return result
print(count_special_characters("jack-in-the-box"))
print(count_special_characters("shouldn't"))
print(count_special_characters("jack-in-the-box, shouldn't and a comma that works,is that one"))
Output:
{'-': 3}
{"'": 1}
{'-': 3, "'": 1, ',': 1}
Obviously this can be condensed, but I will leave that as an exercise for you ;).
Update
Based on your edited question and posted code, you need to update the line:
if count[i-1] in letters and count[i+1] in letters:
to:
if wordlist[i-1] in letters and wordlist[i+1] in letters:
I am working on a silly project where I try to print something with the most code possible. What I want it to do is to take an input, split it into a list, and go through every letter on that list. Then it picks a random number from 0 to 26, and sees if the letter it is on matches the letter in a separate list, and if it does, append it to yet another list. It's hard to explain, so here is my current code (not finished):
import random
alphabet = ['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']
inserted_words = []
target_word = input('what word do you want printed? (caps only): ')
target_word.split()
class Transform(object):
def __init__(self, letter, number):
self.letter = letter
self.number = number
def RandomChoose(self, insert):
let1 = random.randint(0, 26)
let2 = alphabet[let1]
if let2 == insert:
inserted_words.append(insert)
else:
RandomChoose()
for x in target_word:
y = alphabet.index(x)
x = Transform(x, y)
x.RandomChoose(x)
print(inserted_words)
But there is one problem. Here it is:
def RandomChoose(self, insert):
let1 = random.randint(0, 26)
let2 = alphabet[let1]
if let2 == insert:
inserted_words.append(insert)
else:
RandomChoose()
I want the code to choose a random letter from my 'alphabet' list, and see if it matches the input. If not, I want it to repeat the code from the beginning. so, if the input is A and the random letter is B, It will repeat, And if the random letter is Q, it repeats again. And so on until it picks A randomly, which will then be appended to 'inserted_words'. I tried recursion but to no avail. If you know what to do, please tell me!
Try this:
def RandomChoose(self, insert):
letter = None
while letter != insert:
letter = random.choice(alphabet)
inserted_words.append(insert)
Also you might as well declare alphabet and and inserted_words as elements of the class and access them from there, because otherwise RandomChoose has no use being a class function.
Furthermore, you're not assigning target_word.split() to anything. Try with:
target_word = target_word.split()
Also not directly relevant to the question, but you can capitalize the input with target_word.upper() - that way you won't have to limit input to already capitalized words.
I'm trying to pop any letters given by the user, for example if they give you a keyword "ROSES" then these letters should be popped out of the list.
Note: I have a lot more explanation after the SOURCE CODE
SOURCE CODE
alphabet = ["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"]
encrypted_message = []
key_word = str(input("Please enter a word:"))
key_word = list(key_word)
#print(key_word)
check_for_dup = 0
for letter in key_word:
for character in alphabet:
if letter in character:
check_for_dup +=1
alphabet.pop(check_for_dup)
print(alphabet)
print(encrypted_message)
SAMPLE INPUT
Let's say keyword is "Roses"
this what it gives me a list of the following ['A', 'C', 'E', 'G', 'I', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
But that's wrong It should of just removed the characters that existed in the keyword given by the user, like the word "Roses" each letter should of been removed and not in the list being popped. as you can see in the list the letters "B","D","F","H",etc were gone. What I'm trying to do is pop the index of the alphabet letters that the keyword exists.
this is what should of happened.
["A","B","C","D","F","G","H","I","J","K","L","M","N","P","Q","T","U","V","W","X","Y","Z"]
The letters of the keyword "ROSES" were deleted of the list
There is some shortcomings in your code here is an implementation that works:
alphabet = ["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"]
key_word = str(input("Please enter a word:"))
for letter in key_word.upper():
if letter in alphabet:
alphabet.remove(letter)
print(alphabet)
Explanations
You can iterate on a string, no need to cast it as a list
Use remove since you can use the str type directly
You need to .upper() the input because you want to remove A if the user input a
Note that I did not handle encrypted_message since it is unused at the moment.
Also, as some comments says you could use a set instead of a list since lookups are faster for sets.
alphabet = {"A","B","C","D",...}
EDIT
alphabet = ["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"]
key_word = str(input("Please enter a word:"))
encrypted_message = []
for letter in key_word.upper():
if letter in alphabet:
alphabet.remove(letter)
encrypted_message.append(letter)
encrypted_message.extend(alphabet)
This is a new implementation with the handling of your encrypted_message. This will keep the order of the alphabet after the input of the user. Also, if you're wondering why there's no duplicate, you will be appending only if letter is in alphabet which means the second time it won't be in alphabet and therefore not added to your encrypted_message.
you can directly check with input key
iterate all the letters in data, and check whether or not the letter in the input_key, if yes discard it
data = ['A', 'C', 'E', 'G', 'I', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
input_key = 'Roses'
output = [l for l in data if l not in input_key.upper()]
print output
['A', 'C', 'G', 'I', 'K', 'L', 'M', 'N', 'P', 'Q', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
You can do something like this....
import string
alphabet = list(string.ascii_lowercase)
user_word = 'Roses'
user_word = user_word.lower()
letters_to_remove = set(list(user_word)) # Create a unique set of characters to remove
for letter in letters_to_remove:
alphabet.remove(letter)
alphabet = ["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"]
# this can be accepted as a user input as well
userinput = "ROSES"
# creates a list with unique values in uppercase
l = set(list(userinput.upper()))
# iterates over items in l to remove
# the corresponding items in alphabet
for x in l:
alphabet.remove(x)
' '.join(alphabet).translate({ord(c): "" for c in keyword}).split()
Try this:
import string
key_word = set(input("Please enter a word:").lower())
print(sorted(set(string.ascii_lowercase) - key_word))
Explanation:
When checking for (in)existence, it's better to use set. https://docs.python.org/3/tutorial/datastructures.html#sets
Instead of iterating over it N times (N = number of input characters), you hash the character N times and check if there's already something at the result hash or not.
If you check the speed, try with "WXYZZZYW" and you'll see that it'll be a lot slower than if it were "ABCDDDCA" with the list way. With set, it will be always the same time.
The rest is pretty trivial. Casting to lowercase (or uppercase), to make sure it hits a match, case insensitive.
And then, we end by doing a set difference (-). It's all the items that are in the first set but not in the second one.