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