I want to create an encryption script that encrypts the string given to it, here's how it went.
# First, I created a list of the string I got
string = '16271'
string_list = []
for letter in string:
string_list.append(letter)
Then, I have a list called encrypt_list which the letters which I want to add in order to encrypt my string.
So, I use the following code to add a random letter from the encrypt_list after each letter/component in the string_list and then join the list and print as a string.
for i in range(0, len(string) - 1):
string_list.insert(for letter in string_list: string_list.index(letter) + 1, encrypt_list[random.randint(0, len(encrypt_list) - 1)])
print("The encrypted string is: ")
print(''.join(string_list))
I expected the output to be: 1A6b2n781 (I bolded the letter to show my actual string in it) But I am getting an error, that I cannot use the for loop in the insert function, and I cannot find another way of doing that, please help. Hope I make my problem clear
Not sure what your encrypted_list looks like, but if it's a list of letters, this would work:
import random
string = '16271'
encrypted_list = ['r', 't', 's', 'o', 'j', 'e']
encrypted_string = ''.join([s + random.choice(encrypted_list) for s in string])
Something like this?
# First, I created a list of the string I got
import random
string = '16271'
string_list = []
for letter in string:
string_list.append(letter)
the_other_list = ['lorem', 'dorem', 'forem', 'borem']
for i in range(0, len(the_other_list)):
the_other_list[i] = string_list[random.randint(0, len(string_list) - 1)] + the_other_list[i]
print(''.join(the_other_list))
Result example: 1lorem2dorem2forem7borem
You can use a for loop, adding one letter to the list at a time, then adding a randomly selected letter immediately afterwards (if we're not processing the last letter in the list). I've used constants from string to define the space of characters to sample from; you can adjust this as you see fit.
This should be simpler than trying to do repeated insertion in the middle of the list (where you'd have to handle memory shifting as you're inserting, plus it'd get slower for larger texts because you'd be attempting to insert in the middle of a list).
# First, I created a list of the string I got
import random
import string
encrypt_text = string.ascii_uppercase + string.ascii_lowercase + string.digits
plaintext = '16271'
letters = []
for index, letter in enumerate(plaintext):
letters.append(letter)
if index != len(plaintext) - 1:
letters.append(random.choice(encrypt_text))
print("The encrypted string is: ")
print(''.join(letters))
Based on how you defined the problem, I would recommend implementing it as a generator:
import random
import string
def _gen_string(s):
alphabet = string.ascii_letters
for c in s:
yield c
yield random.choice(alphabet)
Then you can use that as the basis for your encryption:
def encrypt(s):
return ''.join(_gen_string(s))
encrypt('16271')
# 1J6P2U7Z1i
Of course, this is not really encryption. It's obscurity and obscurity is not a form of security that should be relied upon :-)
Related
I’m new to computer science and really stuck on this question so any help would be great :).
Firstly I was given the following global variable:
ARROWS = ‘<>^v’
The idea is to create a function that takes in a string and an integer (n). The function should then replace the first n number of characters with ‘X’. So far this is easy, however, the problem is that the characters should ONLY be replaced if it is a part of the global variable ARROWS. If it isn’t, it should not be modified but still counts as one of the n numbers. The following exemplifies what needs to be done:
>>>function(‘>>.<>>...’, 4)
‘XX.X>>...’
>>>function(‘>..>..>’, 6)
‘X..X..>’
>>>function(‘..>>>.’, 2)
‘..>>>.’
Please help :)
Hi it seems to me (if you want to avoid using libraries) that you can iterate over the characters in the string and do comparisons to decide if the character needs to be changed. Here is some sample code which should help you.
ARROWS = '<>^v'
def replace_up_to(in_str, n):
# store the new character in this list
result = []
for i, char in enumerate(in_str):
# decide if we need to change the char
if i < n and char in ARROWS:
result.append("X")
continue
result.append(char)
# return a new string from our result list
return "".join(result)
The solution is very straightforward. Hope this helps. :)
ARROWS = "<>^v"
arrows_set = set(ARROWS)
def function(word, n):
newWord = ""
for i in range(0, len(word)):
if word[i] in arrows_set and i < n:
newWord += 'X'
else:
newWord += word[i]
return newWord
print(function(">>.<>>...", 4))
print(function(">..>..>", 6))
You can use the re module to match a regex set of your arrows.
import re
txt_to_replace = "aa^aaa<>aaa>"
x= re.sub(r'[<>^v]', 'X', txt_to_replace ,3 )
# x is now aaXaaaXXaaa>
You can use re.sub() to replace any of the characters in ARROW.
To limit it to the first N characters of the input string, perform the replacement on a slice and concatenate that with the remainder of the input string.
import re
def replace_arrow(string, limit):
arrows_regex = r'[<>^v]'
first_n = string[:limit]
rest = string[limit:]
return re.sub(arrows_regex, 'X', first_n) + rest
input: ['baNaNa', 7] # string and step size
required output : 'utGtGt' # every character of string shifted backwards by step size
import ast
in_string = input()
lis = ast.literal_eval(in_string)
st = lis[0]
step = lis[1]
alphabets = 'abcdefghijklmnopqrstuvwxyz'
password = ''
for letter in st:
if letter in alphabets:
index_val = alphabets.index(letter) - (step)
password += alphabets[index_val]
print(password)
Output i am getting is 'utgtgt'. I want 'utGtGt'. Help on this would be appreciated a lot.
The string module has methods to create a transformation dictionary and a translate method to do exactly what you want:
st = "baNaNa"
step = 7
alphabets = 'abcdefghijklmnopqrstuvwxyz'
alph2 = alphabets.upper()
# lower case translation table
t = str.maketrans(alphabets, alphabets[-step:]+alphabets[:-step])
# upper case translation table
t2 = str.maketrans(alph2, alph2[-step:]+alph2[:-step])
# merge both translation tables
t.update(t2)
print(st.translate(t))
Output:
utGtGt
You give it the original string and an equal long string to map letters to and apply that dictionary using str.translate(dictionary).
The sliced strings equate to:
print(alphabets)
print(alphabets[-step:]+alphabets[:-step])
abcdefghijklmnopqrstuvwxyz
tuvwxyzabcdefghijklmnopqrs
which is what your step is for.
See Understanding slice notation if you never saw string slicing in use.
by processing each charater and checking it's cardinal no and making calculation accordingly help you to reach the result
def func(string, size):
if size%26==0:
size=26
else:
size=size%26
new_str = ''
for char in string:
if char.isupper():
if ord(char)-size<ord('A'):
new_str+=chr(ord(char)-size+26)
else:
new_str+=chr(ord(char)-size)
elif char.islower():
if ord(char)-size<ord('a'):
new_str+=chr(ord(char)-size+26)
else:
new_str+=chr(ord(char)-size)
return new_str
res =func('baNaNa', 7)
print(res)
# output utGtGt
Here's a simple solution that makes use of the % modulo operator to shift letters backwards.
It basically collects all of the letters in a reverse index lookup dictionary, so looking up letter positions is O(1) instead of using list.index(), which is linear O(N) lookups.
Then it goes through each letter and calculates the shift value from the letter index e.g. for the letter a with a shift value of 7, the calculation will be (0 - 7) % 26, which will give 19, the position of u.
Then once you have this shift value, convert it to uppercase or lowercase depending on the case of the original letter.
At the end we just str.join() the result list into one string. This is more efficient than doing += to join strings.
Demo:
from string import ascii_lowercase
def letter_backwards_shift(word, shift):
letter_lookups = {letter: idx for idx, letter in enumerate(ascii_lowercase)}
alphabet = list(letter_lookups)
result = []
for letter in word:
idx = letter_lookups[letter.lower()]
shifted_letter = alphabet[(idx - shift) % len(alphabet)]
if letter.isupper():
result.append(shifted_letter.upper())
else:
result.append(shifted_letter.lower())
return ''.join(result)
Output:
>>> letter_backwards_shift('baNaNa', 7)
utGtGt
I would probably go with #Patrick Artner's pythonic solution. I just showed the above implementation as a learning exercise :-).
I'm working with a hangman like project whereas if the user inputs a letter and matches with the solution, it replaces a specific asterisk that corresponds to the position of the letter in the solution. I'm trying to do this by getting the index of the instance of that letter in the solution then replacing the the matching index in the asterisk.
The thing here is that I only get the first instance of a recurring character when I used var.index(character) whereas I also have to replace the other instance of that letter. Here's the code:
word = 'turtlet'
astk = '******'
for i in word:
if i == t:
astk[word.index('i')] = i
Here it just replaces the first instance of 't' every time. How can I possibly solve this?
index() gives you only the index of the first occurrence of the character (technically, substring) in a string. You should take advantage of using enumerate(). Also, instead of a string, your guess (hidden word) should be a list, since strings are immutable and do not support item assignment, which means you cannot reveal the character if the user's guess was correct. You can then join() it when you want to display it. Here is a very simplified version of the game so you can see it in action:
word = 'turtlet'
guess = ['*'] * len(word)
while '*' in guess:
print(''.join(guess))
char = input('Enter char: ')
for i, x in enumerate(word):
if x == char:
guess[i] = char
print(''.join(guess))
print('Finished!')
Note the the find method of the string type has an optional parameter that tells where to start the search. So if you are sure that the string word has at least two ts, you can use
firstindex = word.find('t')
secondindex = word.find('t', firstindex + 1)
I'm sure you can see how to adapt that to other uses.
I believe there's a better way to do your specific task.
Simply keep the word (or phrase) itself and, when you need to display the masked phrase, calculate it at that point. The following snippet shows how you can do this:
>>> import re
>>> phrase = 'My hovercraft is full of eels'
>>> letters = ' mefl'
>>> display = re.sub("[^"+letters+"]", '*', phrase, flags=re.IGNORECASE)
>>> display
'M* ***e****f* ** f*ll *f eel*'
Note that letters should start with the characters you want displayed regardless (space in my case but may include punctuation as well). As each letter is guessed, add it to letters and recalculate/redisplay the masked phrase.
The regular expression substitution replaces all characters that are not in letters, with an asterisk.
for i in range(len(word)):
if word[i] == "t":
astk = astk[:i] + word[i] + astk[i + 1:]
The question I'm answering requires you to validate a Car Reg Plate. It must look for a sequence of two letters, then three numbers, then three letters, otherwise return a message like "not a valid postcode"
I need to know how to check if a string contains a certain letter, or number, by comparing it with a list.
So far, I've got this:
# Task 2
import random
import re
def regNumber():
# Generate a Car Reg Number
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"]
numbers = ["1","2","3","4","5","6","7","8","9","0"]
letter1 = random.choice(letters)
letter2 = random.choice(letters)
number1 = random.choice(numbers)
number2 = random.choice(numbers)
letter3 = random.choice(letters)
letter4 = random.choice(letters)
letter5 = random.choice(letters)
licensePlate = (letter1 + letter2 + number1 + number2 + letter3 + letter4 + letter5)
return licensePlate, letters, numbers
carReg, letters, numbers = regNumber()
print(carReg)
if letters not in carReg: print("Success")
However, I get this error:
TypeError: 'in <string>' requires string as left operand, not list
Any help appreciated.
You need to be checking for characters in your string with this method, it will not simply iterate over your list for you.
Try using something like this instead, to check every character in your list of strings:
if any(letter in carReg for letter in letters):
This will cut out on the first True, which is I think what you're looking for.
Note: If using any like this is unfamiliar territory for you, you can also always just iterate over every string within your list of strings to check for those given characters.
Update: If you're attempting to match a given format of letters and numbers, it would make much more sense (IMHO) for you to familiarize yourself with Python's regex methods to pattern match to a valid license plate than attempt to use loops to validate one. I won't write the regex for your particular case, but to give you an idea, the following would allow you to match 3 letters followed by 1-4 digits (valid license plate where I live)
match_plate = re.compile(r"^[A-Z]{3}\d{1,4}$",re.I)
If you really must use a list to check, you will have to use a series of conditional statements to split the license plate into parts over which you can validate with iterations.
The error is telling you the exact issue in this case,
letters is a list being returend from regNumber but in requires a string on the leftside
like 'ASD111' in carReg
change
if letters not in carReg: print("Success")
to
for l in letters:
if l not in carReg:
print("Success")
in your code you are having a list of strings and, that is why I have changed your if condition to a for loop so that each element of the list is checked for occurance in carReg string.
alternatively, i think you should be using a flag to solve your probem. Like so:
flag = 0
for l in letters:
if l in carReg:
flag = 1
break
if flag == 0:
print("Success")
Another way in which you could generate a certain number of letters rather than having to use so many variables would be to use just two variables that would allow the generation of, for the first one, 2 letters and for the second 3 letters.
An example of how I would implement this would be:
def randomLetters1(y):
return ''.join(random.choice(string.ascii_uppercase) for x in range(y))
firstLetters = (randomLetters1(2))
secondLetters = (randomLetters1(3))
I know this because I have had to do this exact same task.
You could do it without regular expressions:
Define the pattern you want using str methods in a list
pattern = [str.isalpha, str.isalpha,
str.isdigit, str.isdigit, str.isdigit,
str.isalpha, str.isalpha, str.isalpha]
Use that pattern to check a string.
def is_foo(pattern, s):
'''Return True if s matches pattern
s is a string
pattern is a list of functions that return a boolean
len(s) == len(pattern)
each function in pattern is applied to the corresponding character in s
'''
# assert len(s) == len(pattern)
return all(f(c) for f, c in zip(pattern, s))
Usage
if is_foo(pattern, 'aa111aaa'):
print 'yes!!!'
if not is_foo(pattern, '11aa111'):
print ':('
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
So, I need to input a scrambled alphabet, and then input a secret message using that alphabet. My program needs to unscramble the secret message. I have written this so far and am stuck. I was hoping someone could help me. What I tried so far is changing every index in the list to A-Z. My question is how do I use what I wrote for that and make it work for the secret message I input as well.
s = ()
alphabet = input("Please input the scrambled alphabet in order: ")
message = input("Now input the scrambled message: ")
alphabet.upper()
s = dict(alphabet)
num = 1
while num < 2:
s[0] = chr(65)
s[1] = chr(66)
s[2] = chr(67)
s[3] = chr(68)
s[4] = chr(69)
s[5] = chr(70)
s[6] = chr(71)
s[7] = chr(72)
s[8] = chr(73)
s[9] = chr(74)
s[10] = chr(75)
s[11] = chr(76)
s[12] = chr(77)
s[13] = chr(78)
s[14] = chr(79)
s[15] = chr(80)
s[16] = chr(81)
s[17] = chr(82)
s[18] = chr(83)
s[19] = chr(84)
s[20] = chr(85)
s[21] = chr(86)
s[22] = chr(87)
s[23] = chr(88)
s[24] = chr(89)
s[25] = chr(90)
num +=1
print (s)
for alpha in message.upper():
if alpha < "A" or alpha > "Z":
print(alpha,end="")
else:
print(s [ord(alpha) -65 ], end="")
First, creating the big dictionary s is entirely unnecessary. It literally does nothing: the line:
s [ord(alpha) -65 ]
Is turning a letter into a number, subtracting 65, and then putting it through a dictionary that adds 65 and turns it back into a number.
Secondly, the line alphabet.upper() doesn't actually change the alphabet, it just returns an uppercase version. You need to do
alphabet = alphabet.upper()
Now for the meaty part. What you meant to do was create a dictionary mapping letters in the code alphabet to letters in the real alphabet. The line dict(alphabet) doesn't do this. Instead, iterate through the characters in the string and assign each to the corresponding letter. You're on the right track using chr, but are going to way too much work. How about this:
s = {}
for i in range(26): # iterate from 0 to 25
s[alphabet[i]] = chr(65 + i)
since chr(65 + i) is the letter in the normal, ordered alphabet, and alphabet[i] is the scrambled one.
Once you have that dictionary, running through letter by letter and changing it should be easy (and it's left to you).
You could use the string translate() method:
import string
intab = 'abcdefghijklmnopqrstuvwxyz' # or string.ascii_lowercase
outtab = 'xyzabcdefghijklmnopqrstuvw'
tab = string.maketrans(intab, outtab)
s = raw_input('Type some text: ').lower()
print s.translate(tab)
maketrans() creates a table with both alphabets, and translate() just replace each character of the string by its pair in the table.
I don't know Python - this is pseudocode
create array of scrambled alphabet
create array of "normal" alphabet
foreach char in message, find char in scrambled array, then output corresponding "normal" char
You could make a dictionary:
alphabet({'a':'alpha', 'b':'bravo','c':'charlie', etc.})
so abc would translate to alphabravocharlie
where 'a','b',.. are the coded letters and 'alpha','bravo',... are their actual values. Make "cypher" by reversing this.
See the section of online tutorials on dictionaries:
http://docs.python.org/dev/library/collections.html
I believe you're asking 'If I type in a string of characters (I'm assuming a string with no delimiter), how can I make that a dictionary where the first letter = A, the second = B, etc.' (sorry if this is the incorrect interpretation). If that is the case, you could do something like this (note the usage of raw_input - input is a built-in that evaluates the parameter - it will not assign):
alphabet = raw_input("Please input the scrambled alphabet in order: ")
message = raw_input("Now input the scrambled message: ")
secret_map = {}
# Step through the provided string, incrementing the character number by index.
# Index will start at 65 + 0 = A (change to 98 if you want lowercase)
for index, letter in enumerate(alphabet):
secret_map[letter] = chr(65 + index)
# Now join the string together, mapping each letter to its corresponding value
new_str = ''.join([secret_map[char] for char in message])
# Print the resulting string
print new_str
Since this is homework (and perhaps you haven't gotten to list comprehensions), this is equivalent to creating new_str:
new_str = ''
for letter in message:
new_str += secret_map[letter]
Let me know if this isn't what you were looking for.
I just couldn't resist expanding on stummjr's answer to create a more pythonic version of both encoding and decoding (I added some extra variables to try and make each step more clear):
import random, string
cypher_list = list(string.ascii_lowercase)
random.shuffle(cypher_list)
cypher_text = ''.join(cypher_list)
encode_tab = string.maketrans(string.ascii_lowercase, cypher_text)
decode_tab = string.maketrans(cypher_text, string.ascii_lowercase)
orig_text = 'this means war'
crypt_text = orig_text.translate(encode_tab)
clear_text = crypt_text.translate(decode_tab)
print cypher_text
print crypt_text
print clear_text
assert(clear_text == orig_text)