How to generate random characters within an existing string? - python

I'm making a text converter, and I'd like to select random characters in a string that already exists.
When I research it, all that comes up is someone that wants to generate random letters in the alphabet or someone that wants to generate a random string. That's not what I'm looking for.
new_string = ""
index = 0
for letter in input_text:
if letter not in "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM":
new_string = new_string + (letter)
continue
index += 1
if index % 2 == 0:
new_string = new_string + (letter.upper())
else:
new_string = new_string + (letter.lower())
My existing text converter capitalizes every other letter, but I'd like to have it randomly capitalize the letters. Is this possible?

You may want to look at the random.choice and random.choices functions in the random library (built-in), which allows you to randomly select an item from a list:
>>> import random
>>> a = random.choice("ABCDabcd")
'C'
>>> my_text = "".join(random.choices("ABCDabcd", k=10))
'baDdbAdDDb'
In order to randomly capitalize, you can choice from a list of the lower- and upper-case version of a letter:
import random
new_string = ""
for letter in input_text:
if letter not in "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM":
new_string = new_string + (letter)
else:
new_string += random.choice([letter.upper(), letter.lower()])
(Note that random.choices returns a list, not a str, so we need to join() the elements together.)
Finally, you may also want to use the isalpha function:
>>> "A".isalpha()
True
>>> "a".isalpha()
True
>>> "7".isalpha()
False
(Relevant question)
But upper() and lower() functions have no effect on non-alpha characters. So you can completely remove this check from your code:
new_string = ""
for letter in input_text:
new_string += random.choice([letter.upper(), letter.lower()])

Related

Python iterations mischaracterizes string value

For this problem, I am given strings ThatAreLikeThis where there are no spaces between words and the 1st letter of each word is capitalized. My task is to lowercase each capital letter and add spaces between words. The following is my code. What I'm doing there is using a while loop nested inside a for-loop. I've turned the string into a list and check if the capital letter is the 1st letter or not. If so, all I do is make the letter lowercase and if it isn't the first letter, I do the same thing but insert a space before it.
def amendTheSentence(s):
s_list = list(s)
for i in range(len(s_list)):
while(s_list[i].isupper()):
if (i == 0):
s_list[i].lower()
else:
s_list.insert(i-1, " ")
s_list[i].lower()
return ''.join(s_list)
However, for the test case, this is the behavior:
Input: s: "CodesignalIsAwesome"
Output: undefined
Expected Output: "codesignal is awesome"
Console Output: Empty
You can use re.sub for this:
re.sub(r'(?<!\b)([A-Z])', ' \\1', s)
Code:
import re
def amendTheSentence(s):
return re.sub(r'(?<!\b)([A-Z])', ' \\1', s).lower()
On run:
>>> amendTheSentence('GoForPhone')
go for phone
Try this:
def amendTheSentence(s):
start = 0
string = ""
for i in range(1, len(s)):
if s[i].isupper():
string += (s[start:i] + " ")
start = i
string += s[start:]
return string.lower()
print(amendTheSentence("CodesignalIsAwesome"))
print(amendTheSentence("ThatAreLikeThis"))
Output:
codesignal is awesome
that are like this
def amendTheSentence(s):
new_sentence=''
for char in s:
if char.isupper():
new_sentence=new_sentence + ' ' + char.lower()
else:
new_sentence=new_sentence + char
return new_sentence
new_sentence=amendTheSentence("CodesignalIsAwesome")
print (new_sentence)
result is codesignal is awesome

Use a condition within a loop

A simple substitution cipher may be created by shifting or rotating the alphabet by a certain number of places. Using this system with a rotation of 5 gives us the following alphabets:
Plaintext alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZ
Ciphertext alphabet: FGHIJKLMNOPQRSTUVWXYZABCDE
Any plain text message can be translated into the ciphertext by replacing each letter of the plain text alphabet with the letter in the ciphertext alphabet in the equivalent position. Spaces are left unchanged. For example, using the cipher above, the word DOG is enciphered as OBK.
Given a String and a rotation value, return the String translated into the ciphertext using the simple substitution method described above. You may assume that the text contains only spaces or capital letters and that the rotation value is always non-negative
function name: rotate_text
arguments:
text - input text to be encoded
n - an integer value specifying how many characters to rotate the text by
returns: a string containing the text rotated as described above
Testing
I am able to pass the test, but the result said I am u therenable to pass hidden or more test, Could someone help me?
def rotate_text(string1, int1):
loL = ['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']
strtoList = list(string1)
list1 = []
newStr = ""
if int1 == len(loL):
int1 = int1 % 26
for i in range(len(strtoList)):
if strtoList[i] in loL:
loLindex = loL.index(strtoList[i])
list1 += [loL[loLindex + int1]]
elif strtoList[i] == " ":
list1 += [" "]
for i in range(len(list1)):
newStr += list1[i]
return newStr
You need:
list1 += [loL[(loLindex + int1) % len(loL)]]
for whenever the cypher "loops back to the first letters".
And then
if int1 == len(loL):
int1 = int1 % 26
becomes irrelevant as well.
And BTW, you don't need to build a list and then make it a string. You can grow your string directly too...

Implementing the Caesar cipher algorithm in Python

So I'm trying to do a code that will shift every letter in a word back by a number of letters in the alphabet (wrapping around for the end). For example, if I want to shift by 2 and I input CBE, I should get AZC. or JOHN into HMFL. I got a code to work for only one letter, and I wonder if there's a way to do a nested for loop for python (that works?)
def move(word, shift):
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
original = ""
for letter in range(26, len(alphabet)):
if alphabet[letter] == word: #this only works if len(word) is 0, I want to be able to iterate over the letters in word.
original += alphabet[letter-shift]
return original
You could start like this
def move(word, shift):
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
return "".join([alphabet[alphabet.find(i)-shift] for i in word])
Basically, this list comprehension constructs a list of the single letters. Then, the index of the letter in the alphabet is found by the .find method. The (index - shift) is the desired new index, which is extracted from alphabet. The resulting list is joined again and returned.
Note that it does obviously not work on lowercase input strings (if you want that use the str.upper method). Actually, the word should only consist of letters present in alphabet. For sentences the approach needs to treat whitespaces differently.
Don't find the letter in the alphabet that way -- find it with an index operation. Let char be the letter in question:
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
...
char_pos = alphabet.index(char)
new_pos = (char_pos - shift) % len(alphabet)
new_char = alphabet[new_pos]
Once you understand this, you can collapse those three lines to a single line.
Now, to make it operate on an entire word ...
new_word = ""
for char in word:
# insert the above logic
new_word += new_char
Can you put all those pieces together?
You'll still need your check to see that char is a letter. Also, if you're interested, you can build a list comprehension for all the translated characters and the apply ''.join() to get your new word.
For instance ...
If the letter is in the alphabet (if char in alphabet), shift the given distance and get the new letter, wrapping around the end if needed (% 26). If it's not a capital letter, then use the original character.
Make a list from all these translations, and then join them into a string. Return that string.
def move(word, shift):
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
return ''.join([alphabet[(alphabet.find(char) - shift) % 26]
if char in alphabet else char
for char in word])
print move("IBM", 1)
print move("The 1812 OVERTURE is COOL!", 13)
Output:
HAL
Ghe 1812 BIREGHER is PBBY!
A_VAL = ord('a')
def move(word, shift):
new_word = ""
for letter in word:
new_letter = ord(letter) - shift
new_word += chr(new_letter) if (new_letter >= A_VAL) else (26 + new_letter)
return new_word
Note that this will only work for lowercase words. As soon as you start mixing upper and lowercase letters you'll need to start checking for them. But this is a start. I discarded your nested loop idea because you should avoid those if at all possible.
You could use : chr() give you the character for a ascii number, ord() give you the ascii number for the matching character.
Here is an old Vigenere project :
def code_vigenere(ch,cle):
text = ch.lower()
clef = cle.lower()
L = len(cle)
res = ''
for i,l in enumerate(text):
res += chr((ord(l) - 97 + ord(cle[i%L]) - 97)%26 +97)
return res

What would be the easiest way to search through a list?

It's actually a string but I just converted it to a list because the answer is supposed to be returned as a list. I've been looking at this problem for hours now and cannot get it. I'm supposed to take a string, like "Mary had a little lamb" for example and another string such as "ab" for example and search through string1 seeing if any of the letters from string2 occur. So if done correctly with the two example it would return
["a=4","b=1"]
I have this so far:
def problem3(myString, charString):
myList = list(myString)
charList = list(charString)
count = 0
newList = []
newString = ""
for i in range(0,len(myList)):
for j in range(0,len(charList)):
if charList[j] == myList[i]:
count = count + 1
newString = charList[j] + "=" + str(count)
newList.append(newString)
return newList
Which returns [a=5] I know it's something with the newList.append(string) and where it should be placed, anyone have any suggestions?
You can do this very easily with list comprehensions and the count function that strings (and lists!) have:
Split the search string into a list of chars.
For each character in the search string, loop over the input string and determine how much it occurs (via count).
Example:
string = 'Mary had a little lamb'
search_string = 'ab'
search_string_chars = [char for char in search_string]
result = []
for char in search_string_chars:
result.append('%s=%d' % (char, string.count(char)))
Result:
['a=4', 'b=1']
Note that you don't need to split the search_string ('ab') into a list of characters, as strings are already lists of characters - the above was done that way to illustrate the concept. Hence, a reduced version of the above could be (which also yields the same result):
string = 'Mary had a little lamb'
search_string = 'ab'
result = []
for char in search_string:
result.append('%s=%d' % (char, string.count(char)))
Here's a possible solution using Counter as mentioned by coder,
from collections import Counter
s = "Mary had a little lambzzz"
cntr = Counter(s)
test_str = "abxyzzz"
results = []
for letter in test_str:
if letter in s:
occurrances = letter + "=" + str(cntr.get(letter))
else:
occurrances = letter + "=" + "0"
if occurrances not in results:
results.append(occurrances)
print(results)
output
['a=4', 'b=1', 'x=0', 'y=1', 'z=3']
import collections
def count_chars(s, chars):
counter = collections.Counter(s)
return ['{}={}'.format(char, counter[char]) for char in set(chars)]
That's all. Let Counter do the work of actually counting the characters in the string. Then create a list comprehension of format strings using the characters in chars. (chars should be a set and not a list so that if there are duplicate characters in chars, the output will only show one.)

How Do I Fix This String Issue in Python?

I am trying to add text with vowels in certain words (that are not consecutive vowels like ie or ei), for example:
Word: 'weird'
Text to add before vowel: 'ib'
Result: 'wibeird'
Thus the text 'ib' was added before the vowel 'e'. Notice how it didn't replace 'i' with 'ib' because when the vowel is consecutive I don't want it to add text.
However, when I do this:
Word: 'dog'
Text to add before vowel: 'ob'
Result: 'doboog'
Correct Result Should Be: 'dobog'
I've been trying to debug my program but I can't seem to figure out the logic in order to make sure it prints 'wibeird' and 'dobog' correctly.
Here is my code, substitute first_syl with 'ob' and word with 'dog' after you run it first with 'weird.
first_syl = 'ib'
word = 'weird'
vowels = "aeiouAEIOU"
diction = "bcdfghjklmnpqrstvwxyz"
empty_str = ""
word_str = ""
ch_str = ""
first_vowel_count = True
for ch in word:
if ch in diction:
word_str += ch
if ch in vowels and first_vowel_count == True:
empty_str += word_str + first_syl + ch
word_str = ""
first_vowel_count = False
if ch in vowels and first_vowel_count == False:
ch_str = ch
if word[-1] not in vowels:
final_str = empty_str + ch_str + word_str
print (final_str)
I am using Python 3.2.3. Also I don't want to use any imported modules, trying to do this to understand the basics of strings and loops in python.
Have you considered regular expressions?
import re
print (re.sub(r'(?<![aeiou])[aeiou]', r'ib\g<0>', 'weird')) #wibeird
print (re.sub(r'(?<![aeiou])[aeiou]', r'ob\g<0>', 'dog')) #dobog
Never use regex when you don't have to. There's a famous quote that goes
Some people, when confronted with a problem, think
“I know, I'll use regular expressions.” Now they have two problems.
This can easily be solved with basic if-then statements. Here's a commented version explaining the logic being used:
first_syl = 'ib' # the characters to be added
word = 'dOg' # the input word
vowels = "aeiou" # instead of a long list of possibilities, we'll use the
# <string>.lower() func. It returns the lowercase equivalent of a
# string object.
first_vowel_count = True # This will tell us if the iterator is at the first vowel
final_str = "" # The output.
for ch in word:
if ch.lower() not in vowels: # If we're at a consonant,
first_vowel_count = True # the next vowel to appear must be the first in
# the series.
elif first_vowel_count: # So the previous "if" statement was false. We're
# at a vowel. This is also the first vowel in the
# series. This means that before appending the vowel
# to output,
final_str += first_syl # we need to first append the vowel-
# predecessor string, or 'ib' in this case.
first_vowel_count = False # Additionally, any vowels following this one cannot
# be the first in the series.
final_str += ch # Finally, we'll append the input character to the
# output.
print(final_str) # "dibOg"

Categories