Going Back to a Previous Command in Python - python

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.

Related

How do I create a random letter generator that loops

So I´m very new to python and just trying to create a letter generator.
The output should be like this: aaa aab abb bbb aac acc ccc ...
No uppercase letters, no digits, no double outputs, just a 3 letter long random letter loop.
Hope Someone can help me, Greetings
Edit: I´ve now created a working code that generates a 3 letter long word but now I have the problem that they are getting generated several times. I know the loop function looks weird but I mean it works.
import string, random
count = 0
while count < 1:
randomLetter1 = random.choice(
string.ascii_lowercase
)
randomLetter2 = random.choice(
string.ascii_lowercase
)
randomLetter3 = random.choice(
string.ascii_lowercase
)
print(randomLetter1 + randomLetter2 + randomLetter3)
The example you posted (aaa, aab, abb, etc.) does not seem like a random letter generator to me, but here's the method I would use to randomly generate 3-letter strings:
# choice allows us to randomly choose an element from a list
from random import choice
letters = ['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']
randomString = ''
for i in range(3):
randomString += choice(letters)
If you want to create a list of these strings, then just loop the last 3 lines several times and add the results to a list like this:
charList = []
for i in range(x):
randomString = ''
for i in range(3):
randomString += choice(letters)
charList.append(randomString)
where x is the number of strings you want to generate. There are definitely many other ways to do something like this, but as you mentioned you're a beginner this would probably be the easiest method.
EDIT: As for the new problem you posted, you've simply forgotten to increment the count variable, which leads to the while loop running infinitely. In general, should you see a loop continue infinitely you should immediate check to see if the exit condition ever becomes true.

'Builtin_function_or_method' object is not subscriptable. Error while using NumPy

I am new fo NumPy and was creating a script to count the number of each vovels in a word. By far I have comeup with this solution for counting all the vovels:
import numpy as np
num = 0
name = np.array['B','A', 'N', 'A', 'N', 'A']
print(name)
vovel = np.array['A', 'E', 'I', 'O', 'U']
for i in (0,4):
a = name[i:i+1]
if a in vovel:
num = num+1
print(num)
But this code give Type error again and again. Can you please explain what is wrong and also how can I change it to make it show number of times each vovel occurs.
I would try something a little more like this:
For each vowel (vovel), check the vowel against each letter in name, and print the count at the end of the loop.
import numpy as np
name = np.array(['B', 'A', 'N', 'A', 'N', 'A'])
vowels = np.array(['A', 'E', 'I', 'O', 'U'])
print(name)
for vowel in vowels:
count = 0
for letter in name:
if letter == vowel:
count += 1
print(f'{vowel}: {count}')
It's also worth mentioning, in Python strings are iterable, meaning you can iterate over them. This means instead of passing a numpy array of
['B', 'A', 'N', 'A', 'N', 'A']
you could actually just pass the string
'BANANA'
and you will achieve the same results

Pig_Latin Translator & for loop

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

How can I pop this letter if it exists based on this algorithm?

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.

My python method isn't working correctly, skipping items in a list (playfair cipher)

I'm trying to write a method that takes a key and an alphabet and creates a playfair cipher box. For those of you that don't know what that is, It takes the key and puts it in a 5 x 5 grid of letters, spilling onto the next line if neccessary, and then adds the rest of the letters of the alphabet. Each letter is only supposed to appear in the box once. I'm trying to do this with a list with 5 internal lists, each with 5 items. the only problem is that where the method is supposed to skip letters, it isn't. Here is the method and the output, can anyone help me?
def makePlayFair(key, alpha):
box = []
#join the key and alphabet string so that you only have to itterate over one string
keyAlpha = ""
keyAlpha = keyAlpha.join([key, alpha])
ind = 0
for lines in range(5):
line = []
while len(line) < 5:
if isIn(keyAlpha[ind], box) or isIn(keyAlpha[ind], line):
print(isIn(keyAlpha[ind],box))
ind += 1
continue
else:
line.append(keyAlpha[ind])
ind += 1
box.append(line)
return box
def isIn(item, block):
there = None
for each_item in block:
if type(each_item) == type([]):
for nested_item in each_item:
if item == nested_item:
there = True
break
else:
there = False
else:
if item == each_item:
there = True
break
else:
there = False
return there
>>> makePlayFair("hello", alphabet) #alphabet is a string with all the letters in it
> `[['h', 'e', 'l', 'o', 'a'], ['b', 'c', 'd', 'f', 'g'], ['h', 'i', 'j', 'k', 'l'], ['m', 'n', 'o', 'p', 'q'], ['r', 's', 't', 'u', 'v']]`
Thanks for your help in advance!
cheers, brad
Your problem is in isIn:
Your break statement only breaks out of the inner for loop. The code then continues to iterate over the second for loop. This means that only the last one is considered. You have to make sure that you exit out of both loops for this to work correctly.
The entire process can be made simpler by doing something like:
def makePlayFair(key, alpha):
letters = []
for letter in key + alpha:
if letter not in letters:
letters.append(letter)
box = []
for line_number in range(5):
box.append( letters[line_number * 5: (line_number+1) * 5])
Make the list of letters first, then break them up into the 5x5 grid:
def takeNatATime(n, seq):
its = [iter(seq)]*n
return zip(*its)
def makePlayfair(s):
keystr = []
for c in s + "abcdefghijklmnopqrstuvwxyz":
if c not in keystr:
keystr.append(c)
return list(takeNatATime(5, keystr))
print makePlayfair("hello")
Prints:
[('h', 'e', 'l', 'o', 'a'), ('b', 'c', 'd', 'f', 'g'), ('i', 'j', 'k', 'm', 'n'), ('p', 'q', 'r', 's', 't'), ('u', 'v', 'w', 'x', 'y')]
Here's my attempt:
#!/usr/bin/env python
from string import ascii_uppercase
import re
def boxify(key):
cipher = []
key = re.sub('[^A-Z]', '', key.upper())[:25]
for i in range(max(25 - len(key), 0)):
for letter in ascii_uppercase:
if letter not in key:
key += letter
break
for i in range(0, 25, 5):
cipher.append(list(key[i:i+5]))
return cipher
if __name__ == "__main__":
print boxify("This is more than twenty-five letters, i'm afraid.")
print boxify("But this isn't!")

Categories