Python Scrambler Program - python

This program takes words in a sentence and scrambles them.
The rules are:
- first and last letter remain the same
- punctuation at the end of a word stays the same
- punctuation with a word is scrambled like the middle letters
My problem is that if I have multiple punctuation at the end of a word it does not scramble it.
Ex) testing!!! should be something like t!ste!nig! or t!est!nig!
but not tstenig!!!
How can I fix that?
import random
import string
original_text = input("Enter your text: ").split(' ')
seed = int(input("Enter a seed (0 for random): "))
punctuation = []
for c in string.punctuation:
punctuation.append(c)
if seed is not 0:
random.seed(seed)
randomized_list = []
def scramble_word(word):
alpha = word[0]
end_punctuation = ''
if word[-1] in punctuation:
x = -1
while word[x] in punctuation:
end_punctuation += word[x]
x -= 1
omega = word[x]
middle = word[1: x]
else:
omega = word[-1]
middle = word[1:-1]
end_punctuation = ""
middle_list = list(middle)
random.shuffle(middle_list)
shuffled_text = "".join(middle_list)
new_words = alpha + shuffled_text + omega + end_punctuation
return new_words
for item in original_text:
if len(item) <= 3:
randomized_list.append(item)
else:
randomized_list.append(scramble_word(item))
new_words = " ".join(randomized_list)
print(new_words)

The problem is that you don't add in the punctuation to the shuffle; see the two amended lines below:
if word[-1] in punctuation:
x = -1
while word[x] in punctuation:
end_punctuation += word[x]
x -= 1
omega = word[x]
middle = word[1: x] + end_punctuation[1:] # Include all except the final character
end_punctuation = end_punctuation[0] # Just use the final character
else:
omega = word[-1]
middle = word[1:-1]
end_punctuation = ""
That does the trick for me:
In [63]: scramble_word('hello!?$')
Out[63]: 'hle?l!o$'
In [64]: scramble_word('hello!?$')
Out[64]: 'h?!ello$'
In [65]: scramble_word('hello!?$')
Out[65]: 'hlel!?o$'
In [66]: scramble_word('hello!')
Out[66]: 'hlleo!'
In [67]: scramble_word('hello!')
Out[67]: 'hello!'
In [68]: scramble_word('hello!')
Out[68]: 'hlleo!'
In [69]: scramble_word('hello')
Out[69]: 'hlelo'
By the way, you don't need the punctuation variable; word[x] in string.punctuation will work the same.

My take on it, can shorten the code a bit. (In Python 3.5.1)
import random
words = input("Enter your text: ")
def scramble(words):
for x in words.split():
middle = x[1:-1]
middle_list = list(middle)
random.shuffle(middle_list)
shuffled = "".join(middle_list)
print ("".join(x[0]+shuffled+x[-1]),"", end="")
scramble(words)
My output was for example from:
Masterson!!%& makes baking%$ potatoes great!
to
Ment!osrs!a%& mkeas bigkna%$ patooets gerat!
I'm sure someone could shorten it even more dramatically.

Related

.pop is cutting off after prematurely

I'm trying to make a Pig Latin translator but if you type in more then two words for an input the .pop function starts to go nuts and I cant figure out why. Information and a fix would be helpful. Thanks.
x = input("Type phrase or word you would like to be translated to pig latin:")
x = x.strip()
y = x.split()
z = []
n = len(y) -1
a = 0
for i in range(0, n):
first_word = y.pop(a)
pig_latin = first_word[1:len(first_word)] + first_word[0] + "ay"
a += 1
z.append(pig_latin)
print(pig_latin)
You have several problems. First, you keep reducing the size of the list with pop(a) but also increment a. a eventually exceeds the size of the now-diminished list and you get the error. As a first cut, we can fix the bugs in the original
x = input("Type phrase or word you would like to be translated to pig latin:")
x = x.strip()
y = x.split()
z = []
#n = len(y) -1
n = len(y)
#a = 0
for i in range(0, n):
first_word = y.pop(0)
pig_latin = first_word[1:len(first_word)] + first_word[0] + "ay"
#a += 1
z.append(pig_latin)
#print(pig_latin)
print(" ".join(z))
But there is no advantage to doing the error prone indexing. We could shorten the program to
x = input("Type phrase or word you would like to be translated to pig latin:")
y = x.strip().split()
z = []
for word in y:
pig_latin = word[1:] + word[0] + "ay"
z.append(pig_latin)
print(" ".join(z))
Or use list comprehensions to reduce it further still
x = input("Type phrase or word you would like to be translated to pig latin:")
z = [word[1:] + word[0] + "ay" for word in x.strip().split()]
print(" ".join(z))

Contract words in python with set length

I'm currently trying to make a sort of "word mixer": for two given words and the desired length specified, the program should return the "mix" of the two words. However, it can be any sort of mix: it can be the first half of the first word combined with the second half of the second word, it can be a random mix, anything really.
Examples:
fish + cake, length 5: fiske
dog + cat, length 4: doga
late + cross, length 6: losste
I've written a very sloppy code (as seen below), and I'd appreciate some tips on what am I doing wrong (since my outputs aren't really good) and if there's anything that can be improved.
from random import randint
name1 = "domingues"
name2 = "signorelli"
names = [name1,name2]
# a list of the desired lengths
lengths = [5,6,7]
mixes = []
def sizes(size):
if size == 5:
letters1 = randint(2,3)
else:
letters1 = randint(2,size-2)
letters2 = size-letters1
return letters1, letters2
def mix(letters1, letters2):
n = randint(0,1)
if n == 1:
a = 0
else:
a = 1
n1 = names[n]
n2 = names[a]
result = n1[0:letters2]+n2[-letters1::]
return result
file = open("results.txt","w+")
for leng in lengths:
file.write("RESULTS WITH "+str(leng)+" LETTERS \n")
file.write("\n")
for i in range(10):
let1, let2 = sizes(leng)
result = mix(let1,let2)
while result == name1 or result == name2:
result = mix(let2)
if result not in mixes:
mixes.append(result)
for m in mixes:
if m not in file:
file.write(m+" \n")
file.write("\n")
file.close()
(Thanks for taking your time to help me btw, I appreciate it!)
In general, this is AI-related problem, because we are implicitly want to get readable mixed words.
I just wrote simple (and dirty) code that tries to catch sequences of vowels and consonants from training data and builds mixed words according to catched rules.
import random
consonants_pat = 'BCDFGHJKLMNPQRSTVXZ'.lower()
vowels_pat = 'aeiouy'
train_data = '''
This our sentence to be used as a training dataset
It should be longer
'''
def build_mixer(train_data, num=3, mixed_len=(2, 4)):
def _get_random_pattern(td, wlen):
td_splitted = td.lower().split()
while True:
w = random.choice(list(filter(lambda x: len(x)>=wlen, td_splitted)))
for j in range(len(w)-wlen):
yield tuple(map(lambda x: 0 if x in vowels_pat else 1, w[j:j + wlen]))
def _select_vowels(w):
return
def _mixer(w1, w2, num=num, mixed_len=mixed_len):
allowed_letters = w1.lower().strip() + w2.lower().strip()
ind = 1
for j in range(num):
wlen = random.choice(range(*mixed_len))
pattern = _get_random_pattern(train_data, wlen)
_aux = allowed_letters
word = ''
try:
for pat in pattern:
for k in pat:
if k == 0:
choiced = random.choice(list(filter(lambda x: x in vowels_pat, _aux)))
word += choiced
else:
choiced = random.choice(list(filter(lambda x: x in consonants_pat, _aux)))
word += choiced
l = list(_aux)
l.remove(choiced)
_aux = ''.join(l)
ind += 1
yield word
if ind>num:
raise StopIteration
except IndexError:
continue
return _mixer
mixer = build_mixer(train_data, num=6, mixed_len=(3,6))
for mixed in mixer('this', 'horse'):
print(mixed)
I got the following words:
het hetihs hetihssro sheo hsio tohir
I recommend taking a random slice of the word string and combining it with another random slice from the second word. Get the len(word) and take a slice of the word randomly using random.randrange().
import random
def word_mixer(word1, word2):
slice1 = word1[:random.randrange(2, len(word1))]
slice2 = word2[:random.randrange(2, len(word2))]
return slice1 + slice2
mixed = word_mixer('weasel', 'snake')
print(mixed)
Output:
wesnak
weasesna
weassnak
Here's one way to do it.
import random
w1 = 'dog'
w2 = 'cat'
w3 = 'fish'
w4 = 'wolf'
def word_mixer(w1, w2, length):
new_word = w1 + w2
x = random.sample(range(len(new_word)), length)
result = []
for i in x:
result.append(new_word[i])
return "".join(result)
print(word_mixer(w3,w4,4))
print(word_mixer(w2,w4,5))
Output:
lfwi
falwc
A bit more smaller version of #AkshayNevrekar's post:
import random
w1 = 'dog'
w2 = 'cat'
w3 = 'fish'
w4 = 'wolf'
def word_mixer(w1, w2, length):
return ''.join(random.sample(w1 + w2, length))
print(word_mixer(w3, w4, 4))
print(word_mixer(w2, w4, 5))
We can also use random.sample and pass mixed string to it like this:
import random
w1=input("Enter first word")
w2=input("Enter second word")
len=int(input("Enter length"))
mixed=w1+w2
def wordmixer(mixed,len):
return ''.join(random.sample(mixed,len))
print(wordmixer(mixed,len))

Function, that turns a word in a string to stars

Im doing an exercise, where im defining a function that takes two inputs - a sentence and a word, that will be replaced by stars in the sentence input.
Problem is, I cant get the final output to put spaces in between words, ie it prints all the words crammed together. Any help please ?
def censor(text, word):
lis = text.split()
output =""
p = []
for w in lis:
if w != word:
p.append(w)
else:
l = len(w)
y = "*" * l
p.append(y)
output = output.join(p)
print output
censor("Hello world televison", "world")
You don't need to initialize output to an empty string first. You can just do
output = " ".join(p)
Notice the " ".join(), that is what determines how you are joining your strings. In this case, it's a single space. Also, you need to return something from your function, so instead of using print you should do
return output
Here's another solution, even though it's a little tricky, it should handle all the different cases that can occur:
def censor(text, word):
text = '.' + text + '.'
for i in range(len(text)):
if text[i].lower() == word[0].lower():
toCensor = True
for j in range(len(word)):
if text[i + j].lower() != word[j].lower():
toCensor = False
break
if toCensor:
if (ord(text[i - 1]) < ord('A') or ord(text[i - 1]) > ord('z'))\
and (ord(text[i + len(word)]) < ord('A') or ord(text[i + len(word)]) > ord('z')):
lst = list(text)
for j in range(len(word)):
lst[i + j] = '*'
text = "".join(lst)
lst = list(text)
lst = lst[1 : -1]
return "".join(lst)
censor("World worlds world television", "world")
>>> ***** worlds ***** television
It handles capital letters and all the punctuation.

Python: Letters to numbers not working correctly

So I have this project for school and I am so close to finishing it but there is one that I just cant seem to get to work properly. One of the functions I have is:
vowels = "aeiou"
consonants = "bcdfghjklmnpqrstvwyz"
def alphapinDecode(tone):
s = tone.lower()
pin = ''
for ch in s:
if ch in consonants:
idx = consonants.find(ch)
elif ch in vowels:
idx2 = vowels.find(ch)
pin = str(pin) + str(idx*5 + idx2)
print(pin)
return None
For the most part the function runs exactly how I want it to. I take a string and it returns numbers as a string.
For example:
>>> alphapinDecode('bomelela')
3464140
But when I do this one:
>>>> alphapinDecode('bomeluco')
it returns 346448 instead of the 3464408 like it is supposed to do (according to my assignment). Now I know the function is giving me the correct answer based on the code, but what am I missing to have it include the 0 before the 8?
EDIT:
Function is supposed to take the string that you pass(tone) and break it up into 2 letter chunks(vowel/consonant pair). With the pair, it is supposed to use the pair and index them with vowels/consonants and return a number. >>>alphapinDecode('hi') returns 27 because consonants[h] gives idx = 5 while vowels[i] gives idx2 = 2
I think your lecture trying to test students coding adaptability.
If really want achieve some output like that please try like below
vowels = "aeiou"
consonants = "bcdfghjklmnpqrstvwyz"
def alphapinDecode(tone):
s = tone.lower()
pin = ''
for ch in s:
if ch in consonants:
idx = consonants.find(ch)
elif ch in vowels:
idx2 = vowels.find(ch)
num = '%02d' % int((idx*5) + idx2) #python 2
num = "{0:0=2d}".format((idx*5) + idx2) #python 3 more verbose
pin = pin + str(num)
print(int(pin))
return None
alphapinDecode('bomeluco') # 3464408
alphapinDecode('bomelela') # 3464140
Your approach is perhaps awkward - I would iterate two characters at a time:
def alphapinDecode(tone):
s = tone.lower()
pin = ''
# Step over the string two characters at a time
for i in range(0, len(s), 2):
ch1 = s[i]
ch2 = s[i+1]
if ch1 in consonants and ch2 in vowels:
idx1 = consonants.find(ch1)
idx2 = vowels.find(ch2)
this_pair = idx1*5 + idx2
# For debugging
print(this_pair)
pin = pin + str(this_pair)
# We need to print without leading zeroes
print(int(pin))
# Returning the pin as an integer is better, IMO
return int(pin)
OK, now we have the code looking a bit better, we can see, I hope, that for the co pair in your second text, the value is 1*5 + 3, which equals 8, of course, but you really want 08. There's a number of ways to do this, but since you're a beginner I'll illustrate the easiest way.
this_pair = idx1*5 + idx2
if this_pair < 10:
# If the pair is less than ten, prepend a leading zero
this_pair_pin = '0' + str(this_pair)
else
this_pair_pin = str(this_pair)
pin = pin + this_pair_pin
EDIT: Let's forget about accumulating the answer in a string as we can simplify the code:
pin = 0
#...
this_pair = idx1*5 + idx2
pin = pin * 100 + this_pair
print(pin)

Python: Converting word to list of letters, then returning indexes of the letters against lower case alphabet

I have already completed the task but in its most basic form looking for help shortening it and so it can apply to any word not just one with eight letters, here's what I've got so far (bit long for what it does):
alpha = map(chr, range(97, 123))
word = "computer"
word_list = list(word)
one = word[0]
two = word[1]
three = word[2]
four = word[3]
five = word[4]
six = word[5]
seven = word[6]
eight = word[7]
one_index = str(alpha.index(one))
two_index = str(alpha.index(two))
three_index = str(alpha.index(three))
four_index = str(alpha.index(four))
five_index = str(alpha.index(five))
six_index = str(alpha.index(six))
seven_index = str(alpha.index(seven))
eight_index = str(alpha.index(eight))
print (one + "=" + one_index)
print (two + "=" + two_index)
print (three + "=" + three_index)
print (four + "=" + four_index)
print (five + "=" + five_index)
print (six + "=" + six_index)
print (seven + "=" + seven_index)
print (eight + "=" + eight_index)
What you are probably looking for is a for-loop.
Using a for-loop your code could look like this:
word = "computer"
for letter in word:
index = ord(letter)-97
if (index<0) or (index>25):
print ("'{}' is not in the lowercase alphabet.".format(letter))
else:
print ("{}={}".format(letter, str(index+1))) # +1 to make a=1
If you use
for letter in word:
#code
the following code will be executed for every letter in the word (or element in word if word is a list for example).
A good start to learn more about loops is here: https://en.wikibooks.org/wiki/Python_Programming/Loops
You can find tons of ressources in the internet covering this topic.
Use for loop for loop,
alpha = map(chr, range(97, 123))
word = "computer"
for l in word:
print '{} = {}'.format(l,alpha.index(l.lower()))
Result
c = 2
o = 14
m = 12
p = 15
u = 20
t = 19
e = 4
r = 17
Start with a dict that maps each letter to its number.
import string
d = dict((c, ord(c)-ord('a')) for c in string.lowercase)
Then pair each letter of your string to the appropriate index.
result = [(c, d[c]) for c in word]
thanks for the help managed to solve it myself in a different way using a function and a while loop, not as short but will work for all lower case words:
alpha = map(chr, range (97,123))
word = "computer"
count = 0
y = 0
def indexfinder (number):
o = word[number]
i = str(alpha.index(o))
print (o + "=" + i)
while count < len(word):
count = count + 1
indexfinder (y)
y = y+1

Categories

Resources