How to remove string quotations, commas and parenthesis from Python itertools output? - python

This nice script generates all 4 character permutations of the given set s, and prints them on new lines.
import itertools
s = ('7', '8', '-')
l = itertools.product(s, repeat=4)
print(*l, sep='\n')
Sample output:
...
('9', '-', '7', '8')
('9', '-', '7', '9')
('9', '-', '8', '7')
('9', '-', '8', '8')
('9', '-', '8', '9')
...
I can't figure out how to remove all single quotes, commas and left/right parenthesis.
Desired output:
...
9-78
9-79
9-87
9-88
9-89
...
Tried adding:
c = []
for i in l:
i = i.replace(",", '')
c.append(i)
print(*c, sep='\n')
Error: AttributeError: 'tuple' object has no attribute 'replace'
Also tried: I can't seem to find where to put the print(' '.join()) logic.

Each time you are printing a value, you can use:
for vals in l:
print("".join([str(v) for v in vals]))
This just joins all the characters, noting that .join requires the values to be strings.
You can also use:
for vals in l:
print(*vals)
... but that has a space between values.

Related

Split a String with multiple delimiter and get the used delimiter

I want to split a String in python using multiple delimiter. In my case I also want the delimiter which was used returned in a list of delimiters.
Example:
string = '1000+20-12+123-165-564'
(Methods which split the string and return lists with numbers and delimiter)
numbers = ['1000', '20', '12', '123', '165', '564']
delimiter = ['+', '-', '+', '-', '-']
I hope my question is understandable.
You might use re.split for this task following way
import re
string = '1000+20-12+123-165-564'
elements = re.split(r'(\d+)',string) # note capturing group
print(elements) # ['', '1000', '+', '20', '-', '12', '+', '123', '-', '165', '-', '564', '']
numbers = elements[1::2] # last 2 is step, get every 2nd element, start at index 1
delimiter = elements[2::2] # again get every 2nd element, start at index 2
print(numbers) # ['1000', '20', '12', '123', '165', '564']
print(delimiter) # ['+', '-', '+', '-', '-', '']
Just capture (...) the delimiter along with matching/splitting with re.split:
import re
s = '1000+20-12+123-165-564'
parts = re.split(r'([+-])', s)
numbers, delims = parts[::2], parts[1::2]
print(numbers, delims)
['1000', '20', '12', '123', '165', '564'] ['+', '-', '+', '-', '-']

How can I adjust the repetition of for loops?

I wanted to think about this problem personally But I know there are experienced people here who have great solutions. I'm trying to create a code number generator and I will improve that to includes all letter cases. But my problem is that for example, for an 8-letter string, I have to copy the for loop eight times, and I can not say how many strings I want by setting a number. Now I want to ask if there is a solution that prevents for for duplication in the code and can only be achieved by setting a generate number?
myPass = []
print("Calculate started..")
for a in string.digits:
for b in string.digits:
for c in string.digits:
for d in string.digits:
for e in string.digits:
for f in string.digits:
for g in string.digits:
for h in string.digits:
myPass.append(a + b + c + d + e + f + g + h)
print("Calculate finish..")
For example, I want to have a function that performs the above process by just setting a number. This is how I can adjust the number of strings:
def Generate(lettersCount):
print("Generate for loops for 12 times..") # for e.g.
print("12 letters passwords calculated..") # for e.g.
Generate(12) # 12 for loop's generated..
Any ideas and suggestions are accepted here.
Do you want something like this?
import itertools as it
my_string = '1234'
s = it.permutations(my_string, len(my_string))
print([x for x in s])
Output: [('1', '2', '3', '4'), ('1', '2', '4', '3'), ('1', '3', '2', '4'), ('1', '3', '4', '2'), ('1', '4', '2', '3'), ('1', '4', '3', '2'), ('2', '1', '3', '4'), ('2', '1', '4', '3'), ('2', '3', '1', '4'), ('2', '3', '4', '1'), ('2', '4', '1', '3'), ('2', '4', '3', '1'), ('3', '1', '2', '4'), ('3', '1', '4', '2'), ('3', '2', '1', '4'), ('3', '2', '4', '1'), ('3', '4', '1', '2'), ('3', '4', '2', '1'), ('4', '1', '2', '3'), ('4', '1', '3', '2'), ('4', '2', '1', '3'), ('4', '2', '3', '1'), ('4', '3', '1', '2'), ('4', '3', '2', '1')]
Edit: Use print(["".join(x) for x in s]) if you want to add to get strings.
Output: ['1234', '1243', '1324', '1342', '1423', '1432', '2134', '2143', '2314', '2341', '2413', '2431', '3124', '3142', '3214', '3241', '3412', '3421', '4123', '4132', '4213', '4231', '4312', '4321']
Use
import itertools as it
my_string = '1234'
my_list = it.permutations(my_string, len(my_string))
with open('your_file.txt', 'w') as f:
for item in my_list:
f.write("%s\n" % item)
if you want to save the result to a file. If you print a very long result to console, the console usually starts deleting the old lines.
You can make the recursive function like the following.
class PasswordGenerator():
def __init__(self):
self.password_list = []
def generate_password(self, len, added_string=""):
if len == 0:
self.password_list.append(added_string)
else:
for i in string.digits:
self.generate_rand_with_for(len - 1, i + added_string)
Then you can use this class to get the list of passwords.
password_gen = PasswordGenerator()
password_gen.generate_password(12)
print(password_gen.password_list)
Or you can implement this using the python generator.
import string
from random import choices
def generate_random_string(len):
while True:
yield ''.join(choices(string.ascii_letters + string.digits, k = len))
gen = generate_random_string(12)
Then you can get one string from this generator at any time.
print(next(gen))
Or you can get any number of passwords like the following
number_of_passwords = 100000
for index, item in enumerate(gen_loop):
print(item)
if index == number_of_passwords:
break
In python there is a function called ord(). This function returns the unicode value of a character. Digits from 0 to 9 are also characters. We can view the unicode values of the characters from '0' to '9' as follows...
for c in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']:
print('Character : ', c, ' and Unicode value : ', ord(c))
You will ge a out put like this...
Character : 0 and Unicode value : 48
Character : 1 and Unicode value : 49
Character : 2 and Unicode value : 50
Character : 3 and Unicode value : 51
Character : 4 and Unicode value : 52
Character : 5 and Unicode value : 53
Character : 6 and Unicode value : 54
Character : 7 and Unicode value : 55
Character : 8 and Unicode value : 56
Character : 9 and Unicode value : 57
There is a function in the module "random" called "randint()"
random.randint(a, b)
Return a random integer N such that a <= N <= b. Alias for randrange(a, b+1).
Now considering that your paawrod will only contain digits from '0' to '9', you can solve your problem with the code below ()...
def passwordGenerator(password_length):
password = ''
for length in range(password_length):
password += chr(random.randint(48, 57))
return password
print(passwordGenerator(12))
Few examples of the generated passwords are given below...
852501224302
501575191222
271006502875
914595005843
The function chr() in python returns the string representation from the unicode value.
Are you trying to make a password generator ?
That can be accomplished with the random module and a single for loop.
all_symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
import random
def password_gen():
return ''.join(random.choice(all_symbols)for i in range(15))
password = password_gen()
print(f"Secure password - {password}")

How to merge or delete an element in a list that duplicates the previous item?

I have a list:
output = ['9', '-', '-', '7', '-', '4', '4', '-', '3', '-', '0', '2']
and I'm trying trying to reduce the '-','-' section to just a single '-', however, haven't had much luck in trying.
final = [output[i] for i in range(len(output)) if output[i] != output[i-1]]
final = 9-7-4-3-02
I've tried that above, but it also reduces the '4','4' to only '4'. So any help would be great.
You should check if the item is equal to the previous item and to '-', which can easily be done in Python using a == b == c.
Note that you should also handle the first character differently, since output[0] == output[0-1] will compare the first item with the last item, which might lead to invalid results.
The following code will handle this:
final = [output[0]] + [output[i] for i in range(1, len(output)) if not (output[i] == output[i-1] == '-')]
The zip() function is your friend for situations where you need to compare/process elements and their predecessor:
final = [a for a,b in zip(output,['']+output) if (a,b) != ('-','-')]
You can use itertools.groupby:
from itertools import groupby as gb
output = ['9', '-', '-', '7', '-', '4', '4', '-', '3', '-', '0', '2']
r = [j for a, b in gb(output) for j in ([a] if a == '-' else b)]
Output:
['9', '-', '7', '-', '4', '4', '-', '3', '-', '0', '2']

How to decrypt a string that I know its pattern in Python?

I'm working on an encrypted string that is made up of 5 integers, and I figured out its pattern, I tried to write a python OrderedDict like this:
od = OrderedDict([('0', '9'), ('1', '2'), ('2', '0'), ('3', '7'), ('4', '1'),
('5', '3'), ('6', '8'), ('7', '6'), ('8', '5'), ('9', '4')])
So I wrote some codes to decrypt the string.
The "encrypted" string is an example.
def replace_all(text, dic):
for k, v in dic.items():
text = text.replace(k, v)
return text
encrypted = '14012'
decrypted = replace_all(encrypted, od)
I just can't get the correct answer, the string 14012 should be decrypted to 21920,but I just get 01400.
What should I do with my codes to get the correct string?
You iterate over the dict items one by one, so '1' gets translated to '2', and then '2' gets translated to '0', which is why the result starts with '0' instead of '2', for example.
You can use the str.translate() method instead:
table = ''.join(od.get(chr(i), chr(i)) for i in range(256))
print(encrypted.translate(table))
This outputs:
21920
There's no need to use OrderedDict in this case, by the way, since order does not matter in building the translation table.
#blhsing has it right, think about what happens to text each loop:
>>> decrypted = replace_all(encrypted, od)
14912
24922
04900
01900
01400
You will want to translate item by item
I like ''.join([od[i] for i in encrypted])

Splitting a string with repeated characters into a list

I am not well experienced with Regex but I have been reading a lot about it. Assume there's a string s = '111234' I want a list with the string split into L = ['111', '2', '3', '4']. My approach was to make a group checking if it's a digit or not and then check for a repetition of the group. Something like this
L = re.findall('\d[\1+]', s)
I think that \d[\1+] will basically check for either "digit" or "digit +" the same repetitions. I think this might do what I want.
Use re.finditer():
>>> s='111234'
>>> [m.group(0) for m in re.finditer(r"(\d)\1*", s)]
['111', '2', '3', '4']
If you want to group all the repeated characters, then you can also use itertools.groupby, like this
from itertools import groupby
print ["".join(grp) for num, grp in groupby('111234')]
# ['111', '2', '3', '4']
If you want to make sure that you want only digits, then
print ["".join(grp) for num, grp in groupby('111aaa234') if num.isdigit()]
# ['111', '2', '3', '4']
Try this one:
s = '111234'
l = re.findall(r'((.)\2*)', s)
## it this stage i have [('111', '1'), ('2', '2'), ('3', '3'), ('4', '4')] in l
## now I am keeping only the first value from the tuple of each list
lst = [x[0] for x in l]
print lst
output:
['111', '2', '3', '4']
If you don't want to use any libraries then here's the code:
s = "AACBCAAB"
L = []
temp = s[0]
for i in range(1,len(s)):
if s[i] == s[i-1]:
temp += s[i]
else:
L.append(temp)
temp = s[i]
if i == len(s)-1:
L.append(temp)
print(L)
Output:
['AA', 'C', 'B', 'C', 'AA', 'B']

Categories