Python : Apply distributive law to elements in list - python

I want to do below in python2.7 . It works in case of 2 subelements but I can have multiple subelements.
NOT = "not"
OR = "or"
AND = "and"
def convertMain(prop) :
if isinstance(prop, str) :
answer = prop
else :
op = prop[0]
#tree1 = convertIntoCNF(prop[1])
#tree2 = convertIntoCNF(prop[2])
"""{ assert: tree1 and tree2 are in cnf }"""
if op == AND :
answer = [AND] + [convertIntoCNF(item) for item in prop[1:]]
else : # op == OR
if (len(prop) == 3) :
tree1 = convertIntoCNF(prop[1])
tree2 = convertIntoCNF(prop[2])
answer = distOr2(tree1, tree2)
return answer
def distOr2(p1,p2):
if isinstance(p1, list) and p1[0] == AND :
#{ assert: p1 = P11 & P12 }
answer = [AND, distOr2(p1[1],p2), distOr2(p1[2],p2)]
elif isinstance(p2, list) and p2[0] == AND :
#{ assert: p2 = P21 & P22 }
answer = [AND, distOr2(p1,p2[1]), distOr2(p1,p2[2])]
else :
#{ assert: since p1 and p2 are both in cnf, then both are disjunctive clauses, which can be appended }
answer = [OR, p1, p2]
return answer
The above code works for below:
Input : ['and', ['or', ['and', '-P', 'Q'], 'R'], ['or', '-P', '-R']]
Output : ['and', ['and', ['or', '-P', 'R'], ['or', 'Q', 'R']], ['or', '-P', '-R']]
Explanation:
Input is expression ((-P V Q) V R) ^ (-P V -R))
Output is expression ((-P V R) ^ (Q V R)) ^ (-P V -R)
I want to make this work for any number of subelements, like in below example 'S' is third element in input so ['or', 'S', 'R'] should be added in output:
Input : ['and', ['or', ['and', '-P', 'Q', 'S'], 'R'], ['or', '-P', '-R']]
Output : ['and', ['and', ['or', '-P', 'R'], ['or', 'Q', 'R'], ['or', 'S', 'R']], ['or', '-P', '-R']]
Thanks.

You can create a method that recursively converts anything with more than two subelements into a form where every list has two subelements (i.e. where every logical connective only has 2 arguments). For example:
def makeBinary(prop):
if isinstance(prop, str):
return prop
elif len(prop) == 3:
return [prop[0], makeBinary(prop[1]), makeBinary(prop[2])]
else:
return [prop[0], makeBinary(prop[1]), makeBinary([prop[0]] + prop[2:])]
Then you can call this on any proposition before running it through the code you already have, and your code can safely assume that no connective will have more than two arguments.

Related

Select all string in list and append a string - python

I wanna add "." to the end of any item of doing variable.
and I want output like this => I am watching.
import random
main = ['I', 'You', 'He', 'She']
main0 = ['am', 'are', 'is', 'is']
doing = ['playing', 'watching', 'reading', 'listening']
rd = random.choice(main)
rd0 = random.choice(doing)
result = []
'''
if rd == main[0]:
result.append(rd)
result.append(main0[0])
if rd == main[1]:
result.append(rd)
result.append(main0[1])
if rd == main[2]:
result.append(rd)
result.append(main0[2])
if rd == main[3]:
result.append(rd)
result.append(main0[3])
'''
result.append(rd0)
print(result)
well, I tried those codes.
'.'.append(doing)
'.'.append(doing[0])
'.'.append(rd0)
but no one of them works, and only returns an error that:
Traceback (most recent call last):
File "c:\Users\----\Documents\Codes\Testing\s.py", line 21, in <module>
'.'.append(rd0)
AttributeError: 'str' object has no attribute 'append'
Why not just select a random string from each list and then build the output as you want:
import random
main = ['I', 'You', 'He', 'She']
verb = ['am', 'are', 'is', 'is']
doing = ['playing', 'watching', 'reading', 'listening']
p1 = random.choice(main)
p2 = random.choice(verb)
p3 = random.choice(doing)
output = ' '.join([p1, p2, p3]) + '.'
print(output) # You is playing.
Bad English, but the logic seems to be what you want here.
Just add a period after making the string:
import random
main = ['I', 'You', 'He', 'She']
main0 = ['am', 'are', 'is', 'is']
doing = ['playing', 'watching', 'reading', 'listening']
' '.join([random.choice(i) for i in [main, main0, doing]]) + '.'

Python Identifier Identification

I'm reading a Python file in a Python program and I want to get the list of all identifiers, literals, separators and terminator in the Python file being read. Using identifiers as example:
one_var = "something"
two_var = "something else"
other_var = "something different"
Assuming the variables above are in the file being read, the result should be:
list_of_identifiers = [one_var, two_var, other_var]
Same thing goes for literals, terminators and separators. Thanks
I already wrote code for all operators and keywords:
import keyword, operator
list_of_operators = []
list_of_keywords = []
more_operators = ['+', '-', '/', '*', '%', '**', '//', '==', '!=', '>', '<', '>=', '<=', '=', '+=', '-=', '*=', '/=', '%=', '**=', '//=', '&', '|', '^', '~', '<<', '>>', 'in', 'not in', 'is', 'is not', 'not', 'or', 'and']
with open('file.py') as data_source:
for each_line in data_source:
new_string = str(each_line).split(' ')
for each_word in new_string:
if each_word in keyword.kwlist:
list_of_keywords.append(each_word)
elif each_word in operator.__all__ or each_word in more_operators:
list_of_operators.append(each_word)
print("Operators found:\n", list_of_operators)
print("Keywords found:\n", list_of_keywords)
import ast
with open('file.py') as data_source:
ast_root = ast.parse(data_source.read())
identifiers = set()
for node in ast.walk(ast_root):
if isinstance(node, ast.Name):
identifiers.add(node.id)
print(identifiers)

redis: hmset expire, but hgetall can get subkey info

python code:
value = {'sct': 's', 'scn': 'A', 'fct': 'd', 'fcn': 'K', 'bet_value':10}
res = rc.hmset(key, value)
rc.expire(key, 3600)
3600 seconds later
rc.hgetall(key)
result:
{'sct': 's', 'scn': 'A', 'fct': 'd', 'fcn': 'K'}
rc.ttl(key) has no result
The question is that the "key" should be expired after 3600s, but I can still get info with the command "hetall".
The ttl command return None, according to the document it should be -2 or -1
What's wrong? anybody can help?

Python script to generate words from letters and two letter combination

I'm looking to write a short script that will allow me to generate all possible letter combinations with the parameters I set.
For example:
_ _ b _ a
Parameters:
word = 5 letters
3th, 5th letter = b, a
1st letter = ph, sd, nn, mm or gh
2nd, 4rd letter = any vowel (aeiouy) and rc
in other words, I'm looking to write a script that would return me all 5*7*7 results.
Thank you
You can create iterables for keeping the possible alternatives for each place:
firsts = ['ph', 'sd', 'nn', 'mm', 'gh']
seconds = fourths = ['a', 'e', 'i', 'o', 'u', 'y', 'rc']
thirds = 'b'
fifths = 'a'
List comprehension
You could use a list comprehension:
print [''.join((first, second, third, fourth, fifth))
for first in firsts
for second in seconds
for third in thirds
for fourth in fourths
for fifth in fifths]
Output
['phabaa', 'phabea', 'phabia', 'phaboa', 'phabua', 'phabya', 'phabrca', 'phebaa', 'phebea', 'phebia', 'pheboa', 'phebua', 'phebya', 'phebrca', 'phibaa', 'phibea', 'phibia', 'phiboa', 'phibua', 'phibya', 'phibrca', 'phobaa', 'phobea', 'phobia', 'phoboa', 'phobua', 'phobya', 'phobrca', 'phubaa', 'phubea', 'phubia', 'phuboa', 'phubua', 'phubya', 'phubrca', 'phybaa', 'phybea', 'phybia', 'phyboa', 'phybua', 'phybya', 'phybrca', 'phrcbaa', 'phrcbea', 'phrcbia', 'phrcboa', 'phrcbua', 'phrcbya', 'phrcbrca', 'sdabaa', 'sdabea', 'sdabia', 'sdaboa', 'sdabua', 'sdabya', 'sdabrca', 'sdebaa', 'sdebea', 'sdebia', 'sdeboa', 'sdebua', 'sdebya', 'sdebrca', 'sdibaa', 'sdibea', 'sdibia', 'sdiboa', 'sdibua', 'sdibya', 'sdibrca', 'sdobaa', 'sdobea', 'sdobia', 'sdoboa', 'sdobua', 'sdobya', 'sdobrca', 'sdubaa', 'sdubea', 'sdubia', 'sduboa', 'sdubua', 'sdubya', 'sdubrca', 'sdybaa', 'sdybea', 'sdybia', 'sdyboa', 'sdybua', 'sdybya', 'sdybrca', 'sdrcbaa', 'sdrcbea', 'sdrcbia', 'sdrcboa', 'sdrcbua', 'sdrcbya', 'sdrcbrca', 'nnabaa', 'nnabea', 'nnabia', 'nnaboa', 'nnabua', 'nnabya', 'nnabrca', 'nnebaa', 'nnebea', 'nnebia', 'nneboa', 'nnebua', 'nnebya', 'nnebrca', 'nnibaa', 'nnibea', 'nnibia', 'nniboa', 'nnibua', 'nnibya', 'nnibrca', 'nnobaa', 'nnobea', 'nnobia', 'nnoboa', 'nnobua', 'nnobya', 'nnobrca', 'nnubaa', 'nnubea', 'nnubia', 'nnuboa', 'nnubua', 'nnubya', 'nnubrca', 'nnybaa', 'nnybea', 'nnybia', 'nnyboa', 'nnybua', 'nnybya', 'nnybrca', 'nnrcbaa', 'nnrcbea', 'nnrcbia', 'nnrcboa', 'nnrcbua', 'nnrcbya', 'nnrcbrca', 'mmabaa', 'mmabea', 'mmabia', 'mmaboa', 'mmabua', 'mmabya', 'mmabrca', 'mmebaa', 'mmebea', 'mmebia', 'mmeboa', 'mmebua', 'mmebya', 'mmebrca', 'mmibaa', 'mmibea', 'mmibia', 'mmiboa', 'mmibua', 'mmibya', 'mmibrca', 'mmobaa', 'mmobea', 'mmobia', 'mmoboa', 'mmobua', 'mmobya', 'mmobrca', 'mmubaa', 'mmubea', 'mmubia', 'mmuboa', 'mmubua', 'mmubya', 'mmubrca', 'mmybaa', 'mmybea', 'mmybia', 'mmyboa', 'mmybua', 'mmybya', 'mmybrca', 'mmrcbaa', 'mmrcbea', 'mmrcbia', 'mmrcboa', 'mmrcbua', 'mmrcbya', 'mmrcbrca', 'ghabaa', 'ghabea', 'ghabia', 'ghaboa', 'ghabua', 'ghabya', 'ghabrca', 'ghebaa', 'ghebea', 'ghebia', 'gheboa', 'ghebua', 'ghebya', 'ghebrca', 'ghibaa', 'ghibea', 'ghibia', 'ghiboa', 'ghibua', 'ghibya', 'ghibrca', 'ghobaa', 'ghobea', 'ghobia', 'ghoboa', 'ghobua', 'ghobya', 'ghobrca', 'ghubaa', 'ghubea', 'ghubia', 'ghuboa', 'ghubua', 'ghubya', 'ghubrca', 'ghybaa', 'ghybea', 'ghybia', 'ghyboa', 'ghybua', 'ghybya', 'ghybrca', 'ghrcbaa', 'ghrcbea', 'ghrcbia', 'ghrcboa', 'ghrcbua', 'ghrcbya', 'ghrcbrca']
itertools.product
Another nice way is to use itertools.product:
from itertools import product
print [''.join(letters)
for letters in product(firsts, seconds, thirds, fourths, fifths)]
Output
['phabaa', 'phabea', 'phabia', 'phaboa', 'phabua', 'phabya', 'phabrca', 'phebaa', 'phebea', 'phebia', 'pheboa', 'phebua', 'phebya', 'phebrca', 'phibaa', 'phibea', 'phibia', 'phiboa', 'phibua', 'phibya', 'phibrca', 'phobaa', 'phobea', 'phobia', 'phoboa', 'phobua', 'phobya', 'phobrca', 'phubaa', 'phubea', 'phubia', 'phuboa', 'phubua', 'phubya', 'phubrca', 'phybaa', 'phybea', 'phybia', 'phyboa', 'phybua', 'phybya', 'phybrca', 'phrcbaa', 'phrcbea', 'phrcbia', 'phrcboa', 'phrcbua', 'phrcbya', 'phrcbrca', 'sdabaa', 'sdabea', 'sdabia', 'sdaboa', 'sdabua', 'sdabya', 'sdabrca', 'sdebaa', 'sdebea', 'sdebia', 'sdeboa', 'sdebua', 'sdebya', 'sdebrca', 'sdibaa', 'sdibea', 'sdibia', 'sdiboa', 'sdibua', 'sdibya', 'sdibrca', 'sdobaa', 'sdobea', 'sdobia', 'sdoboa', 'sdobua', 'sdobya', 'sdobrca', 'sdubaa', 'sdubea', 'sdubia', 'sduboa', 'sdubua', 'sdubya', 'sdubrca', 'sdybaa', 'sdybea', 'sdybia', 'sdyboa', 'sdybua', 'sdybya', 'sdybrca', 'sdrcbaa', 'sdrcbea', 'sdrcbia', 'sdrcboa', 'sdrcbua', 'sdrcbya', 'sdrcbrca', 'nnabaa', 'nnabea', 'nnabia', 'nnaboa', 'nnabua', 'nnabya', 'nnabrca', 'nnebaa', 'nnebea', 'nnebia', 'nneboa', 'nnebua', 'nnebya', 'nnebrca', 'nnibaa', 'nnibea', 'nnibia', 'nniboa', 'nnibua', 'nnibya', 'nnibrca', 'nnobaa', 'nnobea', 'nnobia', 'nnoboa', 'nnobua', 'nnobya', 'nnobrca', 'nnubaa', 'nnubea', 'nnubia', 'nnuboa', 'nnubua', 'nnubya', 'nnubrca', 'nnybaa', 'nnybea', 'nnybia', 'nnyboa', 'nnybua', 'nnybya', 'nnybrca', 'nnrcbaa', 'nnrcbea', 'nnrcbia', 'nnrcboa', 'nnrcbua', 'nnrcbya', 'nnrcbrca', 'mmabaa', 'mmabea', 'mmabia', 'mmaboa', 'mmabua', 'mmabya', 'mmabrca', 'mmebaa', 'mmebea', 'mmebia', 'mmeboa', 'mmebua', 'mmebya', 'mmebrca', 'mmibaa', 'mmibea', 'mmibia', 'mmiboa', 'mmibua', 'mmibya', 'mmibrca', 'mmobaa', 'mmobea', 'mmobia', 'mmoboa', 'mmobua', 'mmobya', 'mmobrca', 'mmubaa', 'mmubea', 'mmubia', 'mmuboa', 'mmubua', 'mmubya', 'mmubrca', 'mmybaa', 'mmybea', 'mmybia', 'mmyboa', 'mmybua', 'mmybya', 'mmybrca', 'mmrcbaa', 'mmrcbea', 'mmrcbia', 'mmrcboa', 'mmrcbua', 'mmrcbya', 'mmrcbrca', 'ghabaa', 'ghabea', 'ghabia', 'ghaboa', 'ghabua', 'ghabya', 'ghabrca', 'ghebaa', 'ghebea', 'ghebia', 'gheboa', 'ghebua', 'ghebya', 'ghebrca', 'ghibaa', 'ghibea', 'ghibia', 'ghiboa', 'ghibua', 'ghibya', 'ghibrca', 'ghobaa', 'ghobea', 'ghobia', 'ghoboa', 'ghobua', 'ghobya', 'ghobrca', 'ghubaa', 'ghubea', 'ghubia', 'ghuboa', 'ghubua', 'ghubya', 'ghubrca', 'ghybaa', 'ghybea', 'ghybia', 'ghyboa', 'ghybua', 'ghybya', 'ghybrca', 'ghrcbaa', 'ghrcbea', 'ghrcbia', 'ghrcboa', 'ghrcbua', 'ghrcbya', 'ghrcbrca']
The nice part of this second solution is that you don't have to hardcode the logic, and if needed you could just replace the iterables with others, even when you have more or less places:
from itertools import product
def genwords(*iterables):
return [''.join(letters) for letters in product(*iterables)]
print genwords(firsts, seconds, thirds, fourths, fifths)
print genwords('123', 'abc')
Output
['phabaa', 'phabea', 'phabia', 'phaboa', 'phabua', 'phabya', 'phabrca', 'phebaa', 'phebea', 'phebia', 'pheboa', 'phebua', 'phebya', 'phebrca', 'phibaa', 'phibea', 'phibia', 'phiboa', 'phibua', 'phibya', 'phibrca', 'phobaa', 'phobea', 'phobia', 'phoboa', 'phobua', 'phobya', 'phobrca', 'phubaa', 'phubea', 'phubia', 'phuboa', 'phubua', 'phubya', 'phubrca', 'phybaa', 'phybea', 'phybia', 'phyboa', 'phybua', 'phybya', 'phybrca', 'phrcbaa', 'phrcbea', 'phrcbia', 'phrcboa', 'phrcbua', 'phrcbya', 'phrcbrca', 'sdabaa', 'sdabea', 'sdabia', 'sdaboa', 'sdabua', 'sdabya', 'sdabrca', 'sdebaa', 'sdebea', 'sdebia', 'sdeboa', 'sdebua', 'sdebya', 'sdebrca', 'sdibaa', 'sdibea', 'sdibia', 'sdiboa', 'sdibua', 'sdibya', 'sdibrca', 'sdobaa', 'sdobea', 'sdobia', 'sdoboa', 'sdobua', 'sdobya', 'sdobrca', 'sdubaa', 'sdubea', 'sdubia', 'sduboa', 'sdubua', 'sdubya', 'sdubrca', 'sdybaa', 'sdybea', 'sdybia', 'sdyboa', 'sdybua', 'sdybya', 'sdybrca', 'sdrcbaa', 'sdrcbea', 'sdrcbia', 'sdrcboa', 'sdrcbua', 'sdrcbya', 'sdrcbrca', 'nnabaa', 'nnabea', 'nnabia', 'nnaboa', 'nnabua', 'nnabya', 'nnabrca', 'nnebaa', 'nnebea', 'nnebia', 'nneboa', 'nnebua', 'nnebya', 'nnebrca', 'nnibaa', 'nnibea', 'nnibia', 'nniboa', 'nnibua', 'nnibya', 'nnibrca', 'nnobaa', 'nnobea', 'nnobia', 'nnoboa', 'nnobua', 'nnobya', 'nnobrca', 'nnubaa', 'nnubea', 'nnubia', 'nnuboa', 'nnubua', 'nnubya', 'nnubrca', 'nnybaa', 'nnybea', 'nnybia', 'nnyboa', 'nnybua', 'nnybya', 'nnybrca', 'nnrcbaa', 'nnrcbea', 'nnrcbia', 'nnrcboa', 'nnrcbua', 'nnrcbya', 'nnrcbrca', 'mmabaa', 'mmabea', 'mmabia', 'mmaboa', 'mmabua', 'mmabya', 'mmabrca', 'mmebaa', 'mmebea', 'mmebia', 'mmeboa', 'mmebua', 'mmebya', 'mmebrca', 'mmibaa', 'mmibea', 'mmibia', 'mmiboa', 'mmibua', 'mmibya', 'mmibrca', 'mmobaa', 'mmobea', 'mmobia', 'mmoboa', 'mmobua', 'mmobya', 'mmobrca', 'mmubaa', 'mmubea', 'mmubia', 'mmuboa', 'mmubua', 'mmubya', 'mmubrca', 'mmybaa', 'mmybea', 'mmybia', 'mmyboa', 'mmybua', 'mmybya', 'mmybrca', 'mmrcbaa', 'mmrcbea', 'mmrcbia', 'mmrcboa', 'mmrcbua', 'mmrcbya', 'mmrcbrca', 'ghabaa', 'ghabea', 'ghabia', 'ghaboa', 'ghabua', 'ghabya', 'ghabrca', 'ghebaa', 'ghebea', 'ghebia', 'gheboa', 'ghebua', 'ghebya', 'ghebrca', 'ghibaa', 'ghibea', 'ghibia', 'ghiboa', 'ghibua', 'ghibya', 'ghibrca', 'ghobaa', 'ghobea', 'ghobia', 'ghoboa', 'ghobua', 'ghobya', 'ghobrca', 'ghubaa', 'ghubea', 'ghubia', 'ghuboa', 'ghubua', 'ghubya', 'ghubrca', 'ghybaa', 'ghybea', 'ghybia', 'ghyboa', 'ghybua', 'ghybya', 'ghybrca', 'ghrcbaa', 'ghrcbea', 'ghrcbia', 'ghrcboa', 'ghrcbua', 'ghrcbya', 'ghrcbrca']
['1a', '1b', '1c', '2a', '2b', '2c', '3a', '3b', '3c']
I would approach this as follows, using itertools.product in a generator function (to avoid building the whole list unless you absolutely have to):
from itertools import product
def words(definition):
for t in product(*definition):
yield "".join(t)
The only trick is providing the definition in an appropriate format; it must be a list of iterables, each of which provides the options for each "letter". This is easy where each option for a letter is a single character:
>>> list(words(["f", "o", "aeiou"]))
['foa', 'foe', 'foi', 'foo', 'fou']
But with your multiple-character letters you will need to supply a list or tuple:
>>> list(words([['ph', 'sd', 'nn', 'mm', 'gh'],
['a', 'e', 'i', 'o', 'u', 'y', 'rc'],
'b',
['a', 'e', 'i', 'o', 'u', 'y', 'rc'],
'a']))
['phabaa', 'phabea', 'phabia', ..., 'ghrcbya', 'ghrcbrca']
Note that in Python 3.3 onwards, this can be done in a single line with yield from:
def words(definition):
yield from map("".join, product(*definition))

Where is dictionary size changing?

In my Python Utilities Github repo I have a function which removes strips nonprinting characters and invalid Unicode bytes from strings, mappings, and sequences:
def filterCharacters(s):
"""
Strip non printable characters
#type s dict|list|tuple|bytes|string
#param s Object to remove non-printable characters from
#rtype dict|list|tuple|bytes|string
#return An object that corresponds with the original object, nonprintable characters removed.
"""
validCategories = (
'Lu', 'Ll', 'Lt', 'LC', 'Lm', 'Lo', 'L', 'Mn', 'Mc', 'Me', 'M', 'Nd', 'Nl', 'No', 'N', 'Pc',
'Pd', 'Ps', 'Pe', 'Pi', 'Pf', 'Po', 'P', 'Sm', 'Sc', 'Sk', 'So', 'S', 'Zs', 'Zl', 'Zp', 'Z'
)
convertToBytes = False
if isinstance(s, dict):
new = {}
for k,v in s.items(): # This is the offending line
new[k] = filterCharacters(v)
return new
if isinstance(s, list):
new = []
for item in s:
new.append(filterCharacters(item))
return new
if isinstance(s, tuple):
new = []
for item in s:
new.append(filterCharacters(item))
return tuple(new)
if isinstance(s, bytes):
s = s.decode('utf-8')
convertToBytes = True
if isinstance(s, str):
s = ''.join(c for c in s if unicodedata.category(c) in validCategories)
if convertToBytes:
s = s.encode('utf-8')
return s
else:
return None
Sometimes this function throws an exception:
Traceback (most recent call last):
File "./util.py", line 56, in filterCharacters
for k,v in s.items():
RuntimeError: dictionary changed size during iteration
I don't see where I am changing the dictionary sent as an argument. Why is this exception being thrown, then?
Thanks!
In python 3 dict.items() returns dict_view object (not list as in python 2). Looking through CPython code I've noticed comments like
Objects/dictobject.c
dict_items(register PyDictObject *mp)
{
...
/* Preallocate the list of tuples, to avoid allocations during
* the loop over the items, which could trigger GC, which
* could resize the dict. :-(
*/
...
if (n != mp->ma_used) {
/* Durnit. The allocations caused the dict to resize.
* Just start over, this shouldn't normally happen.
*/
Py_DECREF(v);
goto again;
}
...
}
So not only dict deletions and insertions could cause this error to show but any allocations! oO!
Procedure of resizing is also interesting. Look at
static int
dictresize(PyDictObject *mp, Py_ssize_t minused)
{
...
}
But that's all internals.
Solution
Try converting dict_view to list with
if isinstance(s, dict):
new = {}
items = [i for i in s.items()]
for k,v in items:
new[k] = filterCharacters(v)
return new

Categories

Resources