use only part of the data premutation - python

import itertools
alphabet = {
"A": 1,
"B": 2,
"C": 3,
"D": 4,
"E": 5,
"F": 6,
"G": 7,
"H": 8,
"I": 9,
"J": 10,
"K": 11,
"L": 12,
"M": 13,
"N": 14,
"O": 15,
"P": 16,
"Q": 17,
"R": 18,
"S": 19,
"T": 20,
"U": 21,
"V": 22,
"W": 23,
"X": 24,
"Y": 25,
"Z": 26
}
def gen_combination_values(n):
comb_values = {}
for i in range(n + 1):
for product in itertools.product(alphabet.keys(), repeat=i):
prod = list(product)
prod.sort()
value = 0
comb = ""
for char in prod:
value += alphabet[char]
comb += char
try:
comb_values[value].add(comb)
except KeyError:
comb_values[value] = set()
comb_values[value].add(comb)
print(comb_values)
return comb_values
I have this script
and I would like to use only a part of the permutation how to do it?
I want the next part of the script to use only all results up to 10
{0: {''}, 1: {'A'}, 2: {'B', 'AA'}, 3: {'C', 'AB', 'BA'}, 4: {'BB' , 'AC', 'D', 'CA'}, 5: {'AD', 'BC', 'E', 'CB', 'DA'}, 6: {'F', 'CC', ' AE ',' DB ',' BD ',' EA '}, 7: {' CD ',' AF ',' G ',' EB ',' FA ',' BE ',' DC '}, 8: {'AG', 'CE', 'EC', 'H', 'BF', 'FB', 'DD', 'GA'}, 9: {'AH', 'DE', 'HA', ' BG ',' CF ',' ED ',' I ',' GB ',' FC '}, 10: {' EE ',' HB ',' DF ',' FD ',' IA ',' AI ' , 'J', 'BH', 'CG', 'GC'},
and the rest not to use
11: {'FE', 'BI', 'CH', 'AJ', 'JA', 'DG', 'GD', 'IB', 'HC', 'EF'}, 12: {'EG' , 'CI', 'IC', 'BJ', 'FF', 'DH', 'HD', 'JB', 'GE'}, 13: {'EH', 'HE', 'DI', ' CJ ',' FG ',' JC ',' ID ',' GF '}, 14: {' DJ ',' EI ',' IE ',' HF ',' JD ',' GG ',' FH ' }, 15: {'EJ', 'IF', 'GH', 'JE', 'FI', 'HG'}, 16: {'IG', 'JF', 'FJ', 'GI', ' HH '}, 17: {' JG ',' GJ ',' HI ',' IH '}, 18: {' JH ',' II ',' HJ '}, 19: {' IJ ',' JI ' }, 20: {'JJ'}}
how to achieve this? Basically here's the whole code I don't know what to do with all the attempts failed
I'm looking for only the first ten premutations to be used from the code

I suggest a re-write of your gen_combination_values() function. There are less cumbersome ways to build your dictionary (which I show in this code). You then need to construct a new dictionary to return which is based on your limit (which defaults to 10).
import itertools
ALPHABET = {k:i for i, k in enumerate('ABCDEFGHIJ', 1)}
def gen_combination_values(n, limit=10):
comb_values = {}
for i in range(n + 1):
for product in itertools.product(ALPHABET, repeat=i):
value = sum(ALPHABET[c] for c in product)
comb = ''.join(c for c in product)
comb_values.setdefault(value, set()).add(comb)
return {k:v for k, v in comb_values.items() if k <= limit}
print(gen_combination_values(2))
Output:
{0: {''}, 1: {'A'}, 2: {'B', 'AA'}, 3: {'C', 'BA', 'AB'}, 4: {'D', 'AC', 'BB', 'CA'}, 5: {'DA', 'E', 'AD', 'BC', 'CB'}, 6: {'CC', 'AE', 'EA', 'BD', 'DB', 'F'}, 7: {'AF', 'FA', 'CD', 'BE', 'G', 'EB', 'DC'}, 8: {'AG', 'GA', 'CE', 'EC', 'FB', 'DD', 'H', 'BF'}, 9: {'CF', 'FC', 'AH', 'BG', 'ED', 'DE', 'GB', 'HA', 'I'}, 10: {'DF', 'EE', 'BH', 'IA', 'CG', 'AI', 'HB', 'GC', 'J', 'FD'}}

There is a small error in your main code, but this should do what you want to do I think:
import itertools
alphabet = {
"A": 1,
"B": 2,
"C": 3,
"D": 4,
"E": 5,
"F": 6,
"G": 7,
"H": 8,
"I": 9,
"J": 10
}
def gen_combination_values(n):
comb_values = {}
for i in range(n + 1):
for product in itertools.product(alphabet.keys(), repeat=i):
value = 0
comb = ""
for char in product:
value += alphabet[char]
comb += char
try:
comb_values[value].add(comb)
except KeyError:
comb_values[value] = set()
comb_values[value].add(comb)
print(comb_values)
return comb_values
def gematria(word):
result = 0
for char in word:
result += alphabet[char]
return result
if __name__ == '__main__':
values = gen_combination_values(2)
for i,(k,v) in enumerate(values.items()):
if k <= 10:
print(i)

Related

Why this dictionary values are all the same?

I am trying to write this dictionary comprehension and I don't know why all the dictionary values are the same.
The code is:
from string import ascii_uppercase
dictionary = {key: value for key in range(0, len(ascii_uppercase)) for value in ascii_uppercase}
The result is:
{0: 'Z', 1: 'Z', 2: 'Z', 3: 'Z', 4: 'Z', 5: 'Z', 6: 'Z', 7: 'Z', 8: 'Z', 9: 'Z', 10: 'Z', 11: 'Z', 12: 'Z', 13: 'Z', 14: 'Z', 15: 'Z', 16: 'Z', 17: 'Z', 18: 'Z', 19: 'Z', 20: 'Z', 21: 'Z', 22: 'Z', 23: 'Z', 24: 'Z', 25: 'Z'}
Why it is only giving me the last character of the string as all the values?
How can I fix it?
If you convert the dict comprehension into regular loops, you have this:
dictionary = {}
for key in range(0, len(ascii_uppercase)): # for every number in range 0-26
for value in ascii_uppercase: # for every letter in range a-z
dictionary[key] = value # d[num] = letter
The last letter for every number is 'z' so your dictionary is updated with it at the end of inner loop for each number.
You can try:
di = {}
for i, letter in enumerate(ascii_uppercase):
di[i] = letter
or
di = {i: letter for i, letter in enumerate(ascii_uppercase)}
or
di = dict(enumerate(ascii_uppercase))
Because the inner loop always end as the end of list, better is to Use enumerate() with dict() for this:
dictionary = dict(enumerate(ascii_uppercase))
The second for-loop gets fully executed before the first one so it messes up the result. You can try this approach with just one for-loop instead:
dictionary = {i: ascii_uppercase[i] for i in range(len(ascii_uppercase))}
Change your code to this
from string import ascii_uppercase
dictionary = {key: value for key,value in enumerate(ascii_uppercase, 0)}
Output
{0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'E', 5: 'F', 6: 'G', 7: 'H', 8: 'I', 9: 'J', 10: 'K', 11: 'L', 12: 'M', 13: 'N', 14: 'O', 15: 'P', 16: 'Q', 17: 'R', 18: 'S', 19: 'T', 20: 'U', 21: 'V', 22: 'W', 23: 'X', 24: 'Y', 25: 'Z'}
While there are other suitable answers, I believe this is what you think you are doing.
from string import ascii_uppercase
{key: value for key,value in zip(range(0, len(ascii_uppercase)),ascii_uppercase)}

How do I fix my message encryption/decryption program?

I'm making a program that takes user input and either encrypts it or decrypts it using my custom dictionary.
The encryption works just fine, but I'm having issues making the decryption process work. For example, when you encrypt the letter "a", the letter becomes the number "22". but if you try to decrypt the number "22", it outputs "hh" since my dictionary has the letter "h" set to "2" and "a" set to "22".
How do I fix this? I'm a high school student with not a lot of experience with Python and would love any feedback regarding my program.
#The dictionary i used for the translation is as follows: T=1 H=2 E=3 Q=4 U=5 I=6 C=7 K=8 B=9 R=10 O=11 W=12 N=13 F=14 X=15 J=16 M=17 P=18 S=19 V=20 L=21 A=22 Z=23 Y=24 D=25 G=26
#Encryption Function
def encrypt(text):
code = {' ': ' ', 'a': '22 ', 'b': '9 ', 'c': '7 ', 'd': '25 ', 'e': '3 ', 'f': '14 ', 'g': '26 ', 'h': '2 ', 'i': '6 ', 'j': '16 ', 'k': '8 ', 'l': '21 ', 'm': '17 ', 'n': '13 ', 'o': '11 ', 'p': '18 ', 'q': '4 ', 'r': '10 ', 's': '19 ', 't': '1 ', 'u': '5 ', 'v': '20 ', 'w': '12 ', 'x': '15 ', 'y': '24 ', 'z': '23 '}
encryption = ""
for x in text:
encryption += code[x.lower()]
return encryption
#Decryption Function
def decrypt(number):
code = {' ': ' ', '22': 'a', '9': 'b', '7': 'c', '25': 'd', '3': 'e', '14': 'f', '26': 'g', '2': 'h', '6': 'i', '16': 'j', '8': 'k', '21': 'l', '17': 'm', '13': 'n', '11': 'o', '18': 'p', '4': 'q', '10': 'r', '19': 's', '1': 't', '5': 'u', '20': 'v', '12': 'w', '15': 'x', '24': 'y', '23': 'z'}
decryption = ""
for y in number:
decryption += code[y]
return decryption
#Variable to loop user input if input isn't valid
Loop = 1
while Loop == 1:
#user input
Option = str.lower(input("Do you want to encrypt or decrypt a message?: "))
#encryption
if Option == "encrypt":
Encryption_Text = input("What is the message you would like to encrypt: ")
print(encrypt(Encryption_Text))
Loop = 0
#decryption
elif Option == "decrypt":
Decryption_Number = input("What is the message you would like to decrypt: ")
print(decrypt(Decryption_Number))
Loop = 0
#invalid user input
else:
print("please input a valid option...")
Loop = 1
Add a breakpoint before for y in number:, then debug, continue, you will find number 22 is spilted, like the following pic shows:
From VARIABLES in the left block, you can see y:2, so you'll get h and output is hh
In this project you can change decryption += code[y] into decryption = code[number]
[edit]
since you want to input more than one number, you can accept the numbers and using split(),
code changes are below:
for y in number.split():
decryption += code[y]+" "
i came up with this
# The dictionary i used for the translation is as follows: T=1 H=2 E=3 Q=4 U=5 I=6 C=7 K=8 B=9 R=10 O=11 W=12 N=13 F=14 X=15 J=16 M=17 P=18 S=19 V=20 L=21 A=22 Z=23 Y=24 D=25 G=26
# Encryption Function
def encrypt(text):
code = {' ': '-', 'a': '22 ', 'b': '9 ', 'c': '7 ', 'd': '25 ', 'e': '3 ', 'f': '14 ', 'g': '26 ', 'h': '2 ',
'i': '6 ', 'j': '16 ', 'k': '8 ', 'l': '21 ', 'm': '17 ', 'n': '13 ', 'o': '11 ', 'p': '18 ', 'q': '4 ',
'r': '10 ', 's': '19 ', 't': '1 ', 'u': '5 ', 'v': '20 ', 'w': '12 ', 'x': '15 ', 'y': '24 ', 'z': '23 '}
encryption = ""
for x in text:
encryption += code[x.lower()]
return encryption
# Decryption Function
def decrypt(number):
code = {" ":" ", '-': ' ', '22': 'a', '9': 'b', '7': 'c', '25': 'd', '3': 'e', '14': 'f', '26': 'g', '2': 'h',
'6': 'i', '16': 'j', '8': 'k', '21': 'l', '17': 'm', '13': 'n', '11': 'o', '18': 'p', '4': 'q', '10': 'r',
'19': 's', '1': 't', '5': 'u', '20': 'v', '12': 'w', '15': 'x', '24': 'y', '23': 'z'}
decryption = ""
numbers = number.split(" ")
del numbers[-1]
for y in numbers:
if "-" in y:
num = y.split("-")[1]
decryption += " " + code[num]
else:
decryption += code[y]
return decryption
# Variable to loop user input if input isn't valid
Loop = 1
while Loop == 1:
# user input
Option = str.lower(input("Do you want to encrypt or decrypt a message?: "))
# encryption
if Option == "1":
Encryption_Text = input("What is the message you would like to encrypt: ")
print(encrypt(Encryption_Text))
Loop = 0
# decryption
elif Option == "2":
Decryption_Number = input("What is the message you would like to decrypt: ")
print(decrypt(Decryption_Number))
Loop = 0
# invalid user input
else:
print("please input a valid option...")
Loop = 1
i have modified the decrypt method, after seeing the comment under the other answer

Python. How to modify/replace elements of a list which is a value in a dictionary?

I have two dictionaries:
D_1 = {1: 'A', 2: 'B', 3: 'C', 4: 'D', 5: 'E', 6: 'F', 7: 'G', 8: 'H', 9: 'I', 10: 'J', 11: 'K', 12: 'L', 13: 'M', 14: 'N', 15: 'O', 16: 'P', 17: 'Q', 18: 'R', 19: 'S', 20: 'T', 21: 'U', 22: 'V', 23: 'W', 24: 'X', 25: 'Y', 26: 'Z'}
D_2 = {1: ['A', 'A', 'R', 'O', 'N'], 2: ['A', 'B', 'B', 'E', 'Y'], 3: ['A', 'B', 'B', 'I', 'E']}
My task is to replace the letters in values of D2 with corresponding keys from D1. For example I would want the first key and value pair in D2 to look like this : {1:[1,1,19,16,15]}
I have modified D2 where i made the values into lists instead of strings thinking that it would make my task easier.
dd = {v:k for (k, v) in D_1.items()}
{x: [dd[a] for a in y] for (x, y) in D_2.items()}
First line reverts D_1. Second line applies dd to values in D_2.
I think your D_1 is redundant. What you can do here is to use ascii_uppercase:
from string import ascii_uppercase
{k: [ascii_uppercase.index(i) + 1 for i in v] for k, v in D_2.items()}
Output:
{1: [1, 1, 18, 15, 14], 2: [1, 2, 2, 5, 25], 3: [1, 2, 2, 9, 5]}
Using ord
D_2 = {1: ['A', 'A', 'R', 'O', 'N'], 2: ['A', 'B', 'B', 'E', 'Y'], 3: ['A', 'B', 'B', 'I', 'E']}
{k: [ord(val)-64 for val in v] for (k, v) in D_2.items()}
Output:
{1: [1, 1, 18, 15, 14], 2: [1, 2, 2, 5, 25], 3: [1, 2, 2, 9, 5]}
m = map(lambda v:[{v: k for k, v in D_1.items()}[e] for e in v], D_2.values())
encapsulated in a map and create the new dictionary when useful:
dict(list(enumerate(m, start=1)))
# {1: [1, 1, 18, 15, 14], 2: [1, 2, 2, 5, 25], 3: [1, 2, 2, 9, 5]}

In python one list converted to dict like a tree topology

In python2.7, I have one list
['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q']
and I need to transform into a dict like
{
'A':['B','C'],
'B':['D','E'],
'C':['F','G'],
'D':['H','I'],
'E':['J','K'],
'F':['L','M'],
'G':['N','O'],
'H':['P','Q'],
'I':[],
'J':[],
'K':[],
'L':[],
'M':[],
'N':[],
'O':[],
'P':[],
'Q':[]
}
With zip() and itertools.izip_longest() you can do that like:
Code:
import itertools as it
in_data = list('ABCDEFGHIJKLMNOPQ')
out_data = {k: list(v) if v else [] for k, v in
it.izip_longest(in_data, zip(in_data[1::2], in_data[2::2]))}
import json
print(json.dumps(out_data, indent=2))
Results:
{
"A": [
"B",
"C"
],
"C": [
"F",
"G"
],
"B": [
"D",
"E"
],
"E": [
"J",
"K"
],
"D": [
"H",
"I"
],
"G": [
"N",
"O"
],
"F": [
"L",
"M"
],
"I": [],
"H": [
"P",
"Q"
],
"K": [],
"J": [],
"M": [],
"L": [],
"O": [],
"N": [],
"Q": [],
"P": []
}
Here's an old-fashion method that's pretty optimized that uses the array indexing method as described in the following tutorial: https://www.geeksforgeeks.org/construct-complete-binary-tree-given-array/
The first line fills out the non-leaves with the values of children. The second line fills the leaves to be empty lists. I'll note that we know the number of internal nodes is (len(values) // 2).
values = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q']
dictionary = {values[i]:[values[2*i+1], values[2*i+2]] for i in range((len(values) // 2))}
dictionary.update({values[i]:[] for i in range((len(values) // 2) + 1, len(values))})
alphabet=['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q']
d={} # empty dictionary
counter=2
for i in range(0,len(alphabet)):
if i==0: # at letter 'A' only
lst=[alphabet[i+1],alphabet[i+2]] # lst that will be used as value of key in dictionary
elif i<(len(alphabet)-1)/2: # at letter 'B' through 'H'
lst=[alphabet[i+counter],alphabet[i+counter+1]] # lst that will be used as value of key in dictionary
counter+=1 # increment counter
else: # all letters after 'H'
lst=[] # an empty list that will be used as value of key in dictionary
d[alphabet[i]]=lst # add 'lst' as a value for the letter key in the dictionary
print(d) # print the dictionary
# {'A': ['B', 'C'], 'B': ['D', 'E'], 'C': ['F', 'G'], 'D': ['H', 'I'], 'E': ['J', 'K'], 'F': ['L', 'M'], 'G': ['N', 'O'], 'H': ['P', 'Q'], 'I': [], 'J': [], 'K': [], 'L': [], 'M': [], 'N': [], 'O': [], 'P': [], 'Q': []}
you can create tree topology dict by index relation:
def generateTree(arr):
tree = {}
for i, v in enumerate(arr):
tree[v] = []
if i * 2 + 1 < len(arr):
tree[v].append(arr[i * 2 + 1])
if i * 2 + 2 < len(arr):
tree[v].append(arr[i * 2 + 2])
return tree
output:
{'A': ['B', 'C'], 'B': ['D', 'E'], 'C': ['F', 'G'], 'D': ['H', 'I'], 'E': ['J', 'K'], 'F': ['L', 'M'], 'G': ['N', 'O'], 'H': ['P', 'Q'], 'I': [], 'J': [], 'K': [], 'L': [], 'M': [], 'N': [], 'O': [], 'P': [], 'Q': []}
Hope that will help you, and comment if you have further questions. : )
You can use itertools:
from itertools import chain, repeat
data = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q']
lists = [[first, second] for first, second in zip(data[1::2], data[2::2])]
result = {char: list(value) for char, value in zip(data, chain(lists, repeat([])))}
result
Output:
{'A': ['B', 'C'],
'B': ['D', 'E'],
'C': ['F', 'G'],
'D': ['H', 'I'],
'E': ['J', 'K'],
'F': ['L', 'M'],
'G': ['N', 'O'],
'H': ['P', 'Q'],
'I': [],
'J': [],
'K': [],
'L': [],
'M': [],
'N': [],
'O': [],
'P': [],
'Q': []}
try this:
LL = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q']
dd = {}
for i,e in enumerate(LL):
LLL = []
if ((i+1) + len(dd) < len(LL)): LLL = [LL[((i+1) + len(dd))], LL[((i+1) + len(dd))+1]]
dd[e] = LLL
print dd
{'A': ['B', 'C'],
'B': ['D', 'E'],
'C': ['F', 'G'],
'D': ['H', 'I'],
'E': ['J', 'K'],
'F': ['L', 'M'],
'G': ['N', 'O'],
'H': ['P', 'Q'],
'I': [],
'J': [],
'K': [],
'L': [],
'M': [],
'N': [],
'O': [],
'P': [],
'Q': []}
a little more readable:
dd = {}
for i,e in enumerate(LL):
LLL = []
intv = (i+1) + len(dd)
if (intv < len(LL)): LLL = [LL[(intv)], LL[(intv)+1]]
dd[e] = LLL
print dd

Using a dict to translate numbers to letters in python

I have a string 'alphabet' with all the letters in the alphabet and a list of ints corresponding to those those letters (0-25).
Ex:
num_list = [5,3,1] would translate into letter_list = ['f','d','b']
I currently can translate with:
letter_list = [alphabet[a] for a in num_list]
However, I would like to use a dict for the same thing, retrieve 'letter' keys from dict with 'number' values.
alpha_dict = {'a':0,'b':1,'c':2}... etc
How do I change my statement to do this?
Simply iterate through your alphabet string, and use a dictionary comprehension to create your dictionary
# Use a dictionary comprehension to create your dictionary
alpha_dict = {letter:idx for idx, letter in enumerate(alphabet)}
You can then retrieve the corresponding number to any letter using alpha_dict[letter], changing letter to be to whichever letter you want.
Then, if you want a list of letters corresponding to your num_list, you can do this:
[letter for letter, num in alpha_dict.items() if num in num_list]
which essentially says: for each key-value pair in my dictionary, put the key (i.e. the letter) in a list if the value (i.e. the number) is in num_list
This would return ['b', 'd', 'f'] for the num_list you provided
You could also invert alpha_dict to do this:
>>> import string
>>> alpha_dict = dict(enumerate(string.ascii_lowercase))
>>> alpha_dict
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z'}
>>> numbers = [5, 3, 1]
>>> [alpha_dict[x] for x in numbers]
['f', 'd', 'b']
This way your dictionary maps numbers to letters, instead of letters to numbers.
You can build a dict of letter/numbers as such:
import string
alpha_dict = {
i: string.ascii_lowercase[i]
for i in list(range(0, len(string.ascii_lowercase)))
}
num_list = [5,3,1]
letter_list = [alpha_dict.get(a) for a in num_list]
However it would be easier just to use the list like this:
import string
num_list = [5,3,1]
letter_list = [string.ascii_lowercase[a] for a in num_list]
I think -- like the other answers -- that a list should be used (to utilize the handy index calling) but dictionaries should NOT be used, period. SO...
from string import ascii_lowercase # ONLY import ascii_lowercase
numList = [numbers, in, your, list] # like you said in your question
translation = "".join ([ascii_lowercase[num] for num in numList])
letters = [chr(i) for i in range(97, 123)]
alph_index = dict(zip(letters, range(26)))
print(">> letters=", letters)
print(">> alph_index=", alph_index)
ord('a') = 97
chr(97) = 'a'
97 is a, 65 is A, 122 is z
Output:
>> 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']
>> alph_index= {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 5, 'g': 6, 'h': 7, 'i': 8, 'j': 9, 'k': 10, 'l': 11, 'm': 12, 'n': 13, 'o': 14, 'p': 15, 'q': 16, 'r': 17, 's': 18, 't': 19, 'u': 20, 'v': 21, 'w': 22, 'x': 23, 'y': 24, 'z': 25}

Categories

Resources