Related
#Password Generator Project
import random
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', '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 = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
symbols = ['!', '#', '$', '%', '&', '(', ')', '*', '+']
print("Welcome to the PyPassword Generator!")
nr_letters= int(input("How many letters would you like in your password?\n"))
nr_symbols = int(input(f"How many symbols would you like?\n"))
nr_numbers = int(input(f"How many numbers would you like?\n"))
#Eazy Level - Order not randomised:
#e.g. 4 letter, 2 symbol, 2 number = JduE&!91
def my_function():
for i in range(1,nr_letters+1):
variable=random.choice(letters)
print(variable, end='')
for j in range(1,nr_symbols+1):
variable1=random.choice(symbols)
print(variable1, end='')
for k in range(1,nr_numbers+1):
variable2=random.choice(numbers)
print(variable2, end='')
#Hard Level - Order of characters randomised:
#e.g. 4 letter, 2 symbol, 2 number = g^2jk8&P
#my_function()
function_to_list=my_function()
print[(function_to_list)]
shuffle_my_function=random.shuffle(function_to_list)
print(shuffle_my_function)
This is a kind of personal project here my task is to generate a password. On the easy level just print the password sequence wise whereas on the hard level I want my password to be shuffled.
My easy level code is working perfectly but on the hard level, I want to shuffle the result of the easy level for that I thought that if I define a function of the easy part and then somehow convert that function into the list I can easily use shuffle function . so please help me. please try to do give a solution in my way of thinking and then please suggest your way of doing it
This is a common beginner problem. When you print something, it's there on the screen, but only as text. And the program can't see that text. You have to do something to the variables to keep track of them as you go. In this case, you need to append them to a list. Not only that, but you need to return the list to the caller, so that function_to_list = my_function() assigns something other than None to function_to_list:
def my_function():
list_of_characters = []
for i in range(nr_letters):
list_of_characters.append(random.choice(letters))
for j in range(nr_symbols):
list_of_characters.append(random.choice(symbols))
for k in range(nr_numbers):
list_of_characters.append(random.choice(numbers))
return list_of_characters
Notice that I took out the print statements. That's because a function should do only one thing and do it well. You can print your list and your password as soon as you get them back:
list_from_function = my_function()
print(list_from_function)
To print the list as a single string, join the letters it contains with the emtpy string:
print(''.join(list_from_function))
You can shuffle the result, or do whatever you want:
random.shuffle(list_from_function)
print(list_from_function)
Keep in mind that shuffle operates in place and returns None. That means that if you try to print its return value, you get nothing.
You don't need to use for loop. You can pass argument to random.choices() indicating how many items you want.
import random
import string
letters = string.ascii_letters
numbers = string.digits
symbols = ['!', '#', '$', '%', '&', '(', ')', '*', '+']
# For demo, I hardcoded the numbers
nr_letters = 4
nr_symbols = 5
nr_numbers = 3
# create a list from randomly choosen characters
password_characters = random.choices(letters, k = nr_letters) \
+ random.choices(symbols, k = nr_symbols) \
+ random.choices(numbers, k = nr_numbers)
# shuffle the list:
random.shuffle(password_characters)
# convert the list to string
password = ''.join(password_characters)
Output:
>>> print(password)
>>> &J0*4oR!I3$!
When I get my decoder to run I can translate a word from Morse to normal but if I use more than one word it doesn't separate the words, how do I separate the words? Here is my code:
code_dict = {'.-...': '&', '--..--': ',', '....-': '4', '.....': '5',
'...---...': 'SOS', '-...': 'B', '-..-': 'X', '.-.': 'R',
'.--': 'W', '..---': '2', '.-': 'A', '..': 'I', '..-.': 'F',
'.': 'E', '.-..': 'L', '...': 'S', '..-': 'U', '..--..': '?',
'.----': '1', '-.-': 'K', '-..': 'D', '-....': '6', '-...-': '=',
'---': 'O', '.--.': 'P', '.-.-.-': '.', '--': 'M', '-.': 'N',
'....': 'H', '.----.': "'", '...-': 'V', '--...': '7', '-.-.-.': ';',
'-....-': '-', '..--.-': '_', '-.--.-': ')', '-.-.--': '!', '--.': 'G',
'--.-': 'Q', '--..': 'Z', '-..-.': '/', '.-.-.': '+', '-.-.': 'C', '---...': ':',
'-.--': 'Y', '-': 'T', '.--.-.': '#', '...-..-': '$', '.---': 'J', '-----': '0',
'----.': '9', '.-..-.': '"', '-.--.': '(', '---..': '8', '...--': '3'
}
def decodeMorse(morseCode):
results = []
for item in morseCode.split(' '):
results.append(code_dict.get(item))
results = ''.join(results)
return results.lower()
morseCode = input('Message: ')
print(decodeMorse(morseCode))
Edit:
hello my name is, is:
.... . .-.. .-.. --- -- -.-- -. .- -- . .. ...
when I run the decoder it gives me hellomynameis, I would like it to give me hello my name is
Your example made it not possible. You are not giving any other separator than a space in the input and so you are not able to divide words in any way.
Your solution is to give your input a word separator (for example (double space), then split with .split(" ") and loop tru words).
Other solution might be nltk library, which might have some special functions for that - but here I'm just guessing.
Let's say you have a string:
mystring = "Welcome to the InterStar cafe, serving you since 2412!"
I am looking for a way to convert that string into a number, like say:
encoded_string = number_encode(mystring)
print(encoded_string)
08713091353153848093820430298
..that you can convert back to the original string.
decoded_string = number_decode(encoded_string)
print(decoded_string)
"Welcome to the InterStar cafe, serving you since 2412!"
It doesn't have to be cryptographically secure, but it does have to put out the same number for the same string regardless of what computer it's running on.
encode it to a bytes in a fixed encoding, then convert the bytes to an int with int.from_bytes. The reverse operation is to call .to_bytes on the resulting int, then decode back to str:
mystring = "Welcome to the InterStar cafe, serving you since 2412!"
mybytes = mystring.encode('utf-8')
myint = int.from_bytes(mybytes, 'little')
print(myint)
recoveredbytes = myint.to_bytes((myint.bit_length() + 7) // 8, 'little')
recoveredstring = recoveredbytes.decode('utf-8')
print(recoveredstring)
Try it online!
This has one flaw, which is that if the string ends in NUL characters ('\0'/\x00') you'll lose them (switching to 'big' byte order would lose them from the front). If that's a problem, you can always just pad with a '\x01' explicitly and remove it on the decode side so there are no trailing 0s to lose:
mystring = "Welcome to the InterStar cafe, serving you since 2412!"
mybytes = mystring.encode('utf-8') + b'\x01' # Pad with 1 to preserve trailing zeroes
myint = int.from_bytes(mybytes, 'little')
print(myint)
recoveredbytes = myint.to_bytes((myint.bit_length() + 7) // 8, 'little')
recoveredstring = recoveredbytes[:-1].decode('utf-8') # Strip pad before decoding
print(recoveredstring)
If you are simply looking for making a certain string unreadable by a human you might use base64, base64.b64encode(s, altchars=None) and base64.b64decode(s, altchars=None, validate=False):
Take into account that it requires bytes-like object, so you should start your strings with b"I am a bytes-like string":
>>> import base64
>>> coded = base64.b64encode(b"Welcome to the InterStar cafe, serving you since 2412!")
>>> print(coded)
b'V2VsY29tZSB0byB0aGUgSW50ZXJTdGFyIGNhZmUsIHNlcnZpbmcgeW91IHNpbmNlIDI0MTIh'
>>> print(base64.b64decode(coded))
b"Welcome to the InterStar cafe, serving you since 2412!"
If you already have your strings, you can convert them with str.encode('utf-8'):
>>> myString = "Welcome to the InterStar cafe, serving you since 2412!"
>>> bString = myString.encode('utf-8')
>>> print(bString)
b'Welcome to the InterStar cafe, serving you since 2412!'
>>> print(bString.decode())
'Welcome to the InterStar cafe, serving you since 2412!'
If you really need to convert the string to only numbers, you would have to use #ShadowRanger's answer.
I think the other answers are better than this one, but purely mathematically, there is an obvious way of doing this. You just have to interpret a message as an integer written in another base system with different symbols
def frombase(s, sym):
b = len(sym)
n = 0
bl = 1
for a in reversed(s):
n += sym.index(a) * bl
bl *= b
return n
def tobase(n, sym):
b = len(sym)
s = ''
while n > 0:
kl = n % b
n //= b
s += sym[kl]
return s[::-1] if s else sym[0]
and then for your specific case
symbols = [
' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'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', ',', '.', '?', '!', '-', ':', ';',
'_', '"', "'", '#', '$', '%', '&', '/', '(', ')',
'=', '+', '*', '<', '>', '~'
]
encodeword = lambda w: frombase(w, symbols)
decodeword = lambda n: tobase(n, symbols)
Though the first symbol (" ") will be omitted if there's nothing in front of it, similarly to 0001 = 1.
If you really want to represent all possible symbols, you can write them as a sequence of their ord values (integers), seperated by the , symbol. Then you encode that in the base with an added , symbol:
symbols = [',', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] # , is zero
txt2int = lambda w: encodeword(','.join(str(ord(x)) for x in w))
int2txt = lambda n: ''.join(chr(int(x)) for x in decodeword(n).split(','))
Regarding the size of the returned integer: txt2int(w) = encodeword(w) = O(len(w)), meaning e.g. 'Hi there!' would encode to a number with about 9 digits.
When i run the scirpt below, i get no output at all. What i really want to do is: Create a string from an iterable and then use this string as an argument to re.findall.
Print(tab), gives a-z0-9.
import re
my_tab = ['a-z',
'0-9']
tab = ''.join(my_tab)
line = 'and- then 3 times minus 456: no m0re!'
re.findall('tab', 'line')
What am i missing here? Is this the most pythonic way to achieve this??
This will not work, you are telling the regular expression to search for the string 'tab' in the string 'line' .
Even if you did not make that mistake. And did indeed search using the string 'a-z 0-9' which you named tab with the string 'and- then 3 times minus 456: no m0re!' which you named line you would find nothing, this is because 'a-z 0-9' is not valid as regular expression capture group, and will result in no matches in this case.
If you wanted to find any instance of a lower-case letter (a-z) or a number (0-9) you could use this:
>>> re.findall('([a-z\d])', 'and- then 3 times minus 456: no m0re!')
['a', 'n', 'd', 't', 'h', 'e', 'n', '3', 't', 'i', 'm', 'e', 's', 'm', 'i', 'n', 'u', 's', '4', '5', '6', 'n', 'o', 'm', '0', 'r', 'e']
But I do not see how this helps you? Maybe you could explain what you are trying to do.. Either way, I suggest you read about regular expression to learn more.
You have done 'tab' and not tab. One is a string, another is a variable. You want to do re.findall(tab, line) (see how tab is no longer a string). You also did this for line.
However, if you print tab beforehand, you'll notice you have:
a-z0-9
When I think you're intending to have
[a-z0-9]
So you can concatenate strings:
>>> print re.findall('['+tab+']',line) # Here we add a bracket to each side
# of a-z0-9 to create a valid regex
# capture group [a-z0-9]
['a', 'n', 'd', 't', 'h', 'e', 'n', '3', 't', 'i', 'm', 'e', 's', 'm', 'i', 'n', 'u', 's', '4', '5', '6', 'n', 'o', 'm', '0', 'r', 'e']
Or you can use str.format():
>>> print re.findall('[{}]'.format(tab),line)
['a', 'n', 'd', 't', 'h', 'e', 'n', '3', 't', 'i', 'm', 'e', 's', 'm', 'i', 'n', 'u', 's', '4', '5', '6', 'n', 'o', 'm', '0', 'r', 'e']
re.findall(tab, line)
You have used two strings not variables. And actually I think what you want is re.findall('[a-z0-9]', line). But for this goal, you could just use list comprehension [x for x in list(line) if x != ' '].
I am writing python script which is generating C++ code based on the data.
I have python variable string which contains a string which can be composed
of characters like " or newlines.
What is the best way to escape this string for code generation?
The way I use is based on the observation that C++ strings basically
obey the same rules regarding charactes and escaping as Javascript/JSON string.
Python since version 2.6 has a built-in JSON library which can serialize Python
data into JSON. Therefore, the code is, assuming we don't need enclosing
quotes, just as follows:
import json
string_for_printing = json.dumps(original_string).strip('"')
I use this code, so far without problems:
def string(s, encoding='ascii'):
if isinstance(s, unicode):
s = s.encode(encoding)
result = ''
for c in s:
if not (32 <= ord(c) < 127) or c in ('\\', '"'):
result += '\\%03o' % ord(c)
else:
result += c
return '"' + result + '"'
It uses octal escapes to avoid all potentially problematic characters.
We can do better using specifics of C found here (https://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html#Character-Constants) and Python's built-in printable function:
def c_escape():
import string
mp = []
for c in range(256):
if c == ord('\\'): mp.append("\\\\")
elif c == ord('?'): mp.append("\\?")
elif c == ord('\''): mp.append("\\'")
elif c == ord('"'): mp.append("\\\"")
elif c == ord('\a'): mp.append("\\a")
elif c == ord('\b'): mp.append("\\b")
elif c == ord('\f'): mp.append("\\f")
elif c == ord('\n'): mp.append("\\n")
elif c == ord('\r'): mp.append("\\r")
elif c == ord('\t'): mp.append("\\t")
elif c == ord('\v'): mp.append("\\v")
elif chr(c) in string.printable: mp.append(chr(c))
else:
x = "\\%03o" % c
mp.append(x if c>=64 else (("\\%%0%do" % (1+c>=8)) % c, x))
return mp
This has the advantage of now being a mapping from ordinal value of a character ord(c) to the exact string. Using += for strings is slow and bad practice, so this allows for "".join(...) which is far more performant in Python. Not to mention, indexing a list/table is much faster than doing computations on characters each time through. Also do not waste octal characters either by checking if less characters are needed. However, to use this, you must verify the next character is not a 0 through 7 otherwise you must use the 3 digit octal format.
The table looks like:
[('\\0', '\\000'), ('\\1', '\\001'), ('\\2', '\\002'), ('\\3', '\\003'), ('\\4', '\\004'), ('\\5', '\\005'), ('\\6', '\\006'), '\\a', '\\b', '\\t', '\\n', '\\v', '\\f', '\\r', ('\\16', '\\016'), ('\\17', '\\017'), ('\\20', '\\020'), ('\\21', '\\021'), ('\\22', '\\022'), ('\\23', '\\023'), ('\\24', '\\024'), ('\\25', '\\025'), ('\\26', '\\026'), ('\\27', '\\027'), ('\\30', '\\030'), ('\\31', '\\031'), ('\\32', '\\032'), ('\\33', '\\033'), ('\\34', '\\034'), ('\\35', '\\035'), ('\\36', '\\036'), ('\\37', '\\037'), ' ', '!', '\\"', '#', '$', '%', '&', "\\'", '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '\\?', '#', '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', '{', '|', '}', '~', '\\177', '\\200', '\\201', '\\202', '\\203', '\\204', '\\205', '\\206', '\\207', '\\210', '\\211', '\\212', '\\213', '\\214', '\\215', '\\216', '\\217', '\\220', '\\221', '\\222', '\\223', '\\224', '\\225', '\\226', '\\227', '\\230', '\\231', '\\232', '\\233', '\\234', '\\235', '\\236', '\\237', '\\240', '\\241', '\\242', '\\243', '\\244', '\\245', '\\246', '\\247', '\\250', '\\251', '\\252', '\\253', '\\254', '\\255', '\\256', '\\257', '\\260', '\\261', '\\262', '\\263', '\\264', '\\265', '\\266', '\\267', '\\270', '\\271', '\\272', '\\273', '\\274', '\\275', '\\276', '\\277', '\\300', '\\301', '\\302', '\\303', '\\304', '\\305', '\\306', '\\307', '\\310', '\\311', '\\312', '\\313', '\\314', '\\315', '\\316', '\\317', '\\320', '\\321', '\\322', '\\323', '\\324', '\\325', '\\326', '\\327', '\\330', '\\331', '\\332', '\\333', '\\334', '\\335', '\\336', '\\337', '\\340', '\\341', '\\342', '\\343', '\\344', '\\345', '\\346', '\\347', '\\350', '\\351', '\\352', '\\353', '\\354', '\\355', '\\356', '\\357', '\\360', '\\361', '\\362', '\\363', '\\364', '\\365', '\\366', '\\367', '\\370', '\\371', '\\372', '\\373', '\\374', '\\375', '\\376', '\\377']
Example usage encoding some 4-byte integers as C-strings in little-endian byte order with new lines inserted every 50 characters:
v
mp = c_escape()
vals = [30,50,100]
bytearr = [z for i, x in enumerate(vals) for z in x.to_bytes(4, 'little', signed=x<0)]
"".join(mp[x] if not type(mp[x]) is tuple else mp[x][1 if not i == len(bytearr)-1 and bytearr[i+1] in list(range(ord('0'), ord('7')+1)) else 0] + ("\"\n\t\"" if (i % 50) == 49 else "") for i, x in enumerate(bytearr))
#output: '\\36\\0\\0\\0002\\0\\0\\0d\\0\\0\\0'