Related
I am trying to read from a file with several tuples separated by commas. A sample input file looks like:
(0, 0), (0, 2), (0, 4), (-1, -1), (0, -2), (1, -1), (-1, -3),
(-1, 1), (-1, 3), (1, 1), (1, 3), (1, 5), (2, 0), (2, 2), (3, 3),
(2, 4), (3, 5), (4, 4), (5, 3), (6, 4), (5, 5), (7, 5)
After reading from this file, I need a tuple like this:
G = ((0, 0), (0, 2), (0, 4), (-1, -1), (0, -2), (1, -1), (-1, -3), \
(-1, 1), (-1, 3), (1, 1), (1, 3), (1, 5), (2, 0), (2, 2), (3, 3), \
(2, 4), (3, 5), (4, 4), (5, 3), (6, 4), (5, 5), (7, 5))
How this can be done efficiently? Regards.
Since they look like proper python tuples you can use literal_eval. Its fast as safe:
Safely evaluate an expression node or a string containing a Python
expression. The string or node provided may only consist of the following
Python literal structures: strings, numbers, tuples, lists, dicts, booleans,
and None.
import ast
s = '''(0, 0), (0, 2), ...'''
result = ast.literal_eval('({0})'.format(s))
Assuming there is a file.txt with the following content:
(0, 0), (0, 2), (0, 4), (-1, -1), (0, -2), (1, -1), (-1, -3)
(-1, 1), (-1, 3), (1, 1), (1, 3), (1, 5), (2, 0), (2, 2), (3, 3),
(2, 4), (3, 5), (4, 4), (5, 3), (6, 4), (5, 5), (7, 5)
You can use literal_eval() on each line in a loop and extend resulting list:
from ast import literal_eval
result = []
with open('file.txt', 'r') as f:
for line in f:
result.extend(literal_eval(line.strip()))
print result
prints:
[(0, 0), (0, 2), (0, 4), (-1, -1), (0, -2), (1, -1), (-1, -3), (-1, 1), (-1, 3), (1, 1), (1, 3), (1, 5), (2, 0), (2, 2), (3, 3), (2, 4), (3, 5), (4, 4), (5, 3), (6, 4), (5, 5), (7, 5)]
FYI, literal_eval() is safe:
Safely evaluate an expression node or a string containing a Python
expression. The string or node provided may only consist of the
following Python literal structures: strings, numbers, tuples, lists,
dicts, booleans, and None.
Hope that helps.
I'm creating "Boggle" in python, and I have a list of tuples that represent coordinates on a game board:
all_coordinates = [(0, 0), (1, 0), (2, 0), (0, 1), (1, 1), (2, 1), (0, 2), (1, 2), (2, 2), (0, 3), (1, 3), (2, 3)]
I'm trying to create a new list of lists of tuples that will represent all possible paths on the board.
It'd look something like this:
[[(0,0),(1,0)], ... , [(0,0),(1,0),(2,0),(2,1)] , ... , [(2, 1), (2, 2), (2, 3)], ...]
I tried using itertools.combinations and itertools.permutations but it doesn't seem to do the job, for example the following path:
[(2,1),(1,1),(1,0),(2,0)]
does not appear on the list.
This particular function doesn't necessarily have to output 'valid' paths (valid = moving one step horizontally, vertically or diagonally each time), just all of the possible combinations from the tuples representing the board. I have a function that checks if a certain path returns a valid word. I'm trying to print out all possible paths that return a valid word on the board.
itertools.permutations does indeed produce all the permutations, including the [(2,1),(1,1),(1,0),(2,0)] one that you said was missing. Note that each call to permutations gets you all the permutations of a particular length:
>>> all_coordinates = [(0, 0), (1, 0), (2, 0), (0, 1), (1, 1), (2, 1), (0, 2), (1, 2), (2, 2), (0, 3), (1, 3), (2, 3)]
>>> from itertools import permutations
>>> ((2,1),(1,1),(1,0),(2,0)) in permutations(all_coordinates, 4)
True
If you want to see all the permutations from, say, length 2 to length 4, try:
for k in range(2, 5):
for p in permutations(all_coordinates, k):
print(p)
The resulting sequence is very long; as others have pointed out, you might want to come up with another method for generating paths that only include adjacent coordinates (e.g. a breadth-first search).
(edit) Just for fun, here's a very quick DFS approach to building all the paths up to length 4 by looking only at adjacent coordinates:
>>> def print_paths(path):
... print(path)
... if len(path) >= 4:
... return
... x, y = path[-1]
... for dx in range(-1, 2):
... for dy in range(-1, 2):
... c = x + dx, y + dy
... if c not in path and c in all_coordinates:
... print_paths(path + [c])
...
>>> print_paths([(2, 1)])
[(2, 1)]
[(2, 1), (1, 0)]
[(2, 1), (1, 0), (0, 0)]
[(2, 1), (1, 0), (0, 0), (0, 1)]
[(2, 1), (1, 0), (0, 0), (1, 1)]
[(2, 1), (1, 0), (0, 1)]
[(2, 1), (1, 0), (0, 1), (0, 0)]
[(2, 1), (1, 0), (0, 1), (0, 2)]
[(2, 1), (1, 0), (0, 1), (1, 1)]
[(2, 1), (1, 0), (0, 1), (1, 2)]
[(2, 1), (1, 0), (1, 1)]
[(2, 1), (1, 0), (1, 1), (0, 0)]
[(2, 1), (1, 0), (1, 1), (0, 1)]
[(2, 1), (1, 0), (1, 1), (0, 2)]
[(2, 1), (1, 0), (1, 1), (1, 2)]
[(2, 1), (1, 0), (1, 1), (2, 0)]
[(2, 1), (1, 0), (1, 1), (2, 2)]
[(2, 1), (1, 0), (2, 0)]
[(2, 1), (1, 0), (2, 0), (1, 1)]
[(2, 1), (1, 1)]
[(2, 1), (1, 1), (0, 0)]
[(2, 1), (1, 1), (0, 0), (0, 1)]
[(2, 1), (1, 1), (0, 0), (1, 0)]
[(2, 1), (1, 1), (0, 1)]
[(2, 1), (1, 1), (0, 1), (0, 0)]
[(2, 1), (1, 1), (0, 1), (0, 2)]
[(2, 1), (1, 1), (0, 1), (1, 0)]
[(2, 1), (1, 1), (0, 1), (1, 2)]
[(2, 1), (1, 1), (0, 2)]
[(2, 1), (1, 1), (0, 2), (0, 1)]
[(2, 1), (1, 1), (0, 2), (0, 3)]
[(2, 1), (1, 1), (0, 2), (1, 2)]
[(2, 1), (1, 1), (0, 2), (1, 3)]
[(2, 1), (1, 1), (1, 0)]
[(2, 1), (1, 1), (1, 0), (0, 0)]
[(2, 1), (1, 1), (1, 0), (0, 1)]
[(2, 1), (1, 1), (1, 0), (2, 0)]
(...)
how should I make my check for conflict work and go through all possible ways so as to return the optimal way??
objectiv: return optimal coordinates solution without conflict for the instance e.g (0,0) , (0,2)..
what we have an example (n*m)=(5*5):
A for Vertically: height=a=3, width=b=2
B for horizontally:height=a=2, width=b=3
if A=(0,0) means: e.g (0,0) till (0+height,O+width) must fit in n*m and must not be occupied
coordinates={'C': [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (4, 0), (4, 1), (4, 2), (4, 3), (4, 4)]}
so i want to test as from (0,0) if A or B passes recursively and return an optimal solution at the end, i have tried this in form of a tree it didn't work, since i always need to check on already solved solutions to know if next coordinate fits or not
dic= dict({"A": [], "B": []})
p={'C': [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (4, 0), (4, 1), (4, 2), (4, 3), (4, 4)]}
def enumOptimal(p,dic,ii):
if A : dic['A'].append(A)
enumOptimal(next p,dic,ii)
if B : dic['B'].append(B)
enumOptimal(next p,dic,ii)
enum(next Point, dic)#in case neither A nor B fits
if ii >len(p): print dic
I have a list of tuples:
[(0, 1), (0, 1), (0, 0), (0, 0), (1, 0), (1, 0), (1, 1), (1, 0), (1, 0), (2, 0), (2, 1), (2, 0), (3, 0), (3, 1), (3, 1), (3, 0), (3, 0), (4, 0), (4, 1), (4, 0), (4, 1), (4, 1), (5, 0), (5, 0), (5, 1), (5, 1)]
and I want to sum the right-side of tuples where the left-side is equal, and to put it in another tuples-list, so for the above list i'll get:
[(0,2),(1,1),(2,1),(3,2),(4,3),(5,2)]
I tried this:
k=0
for i,TCtup in enumerate(wordsMatchingList):
if wordsMatchingList[i][0]==k:
TC_matches+=wordsMatchingList[i][1]
print("k: {} /// TC_matches: {}".format(k,TC_matches)) #for checking
else:
groupedWordsMatchingList.append(tuple((k,TC_matches)))
TC_matches=0
k+=1
but from k=1 it just loop one time less for every k because of the else condition.
thank you
If your tuples are guaranteed to come in order like this—all the (0, x), then all the (1, x), etc.—you can use groupby:
>>> xs = [(0, 1), (0, 1), (0, 0), (0, 0), (1, 0), (1, 0), (1, 1), (1, 0), (1, 0), (2, 0), (2, 1), (2, 0), (3, 0), (3, 1), (3, 1), (3, 0), (3, 0), (4, 0), (4, 1), (4, 0), (4, 1), (4, 1), (5, 0), (5, 0), (5, 1), (5, 1)]
>>> from itertools import groupby
>>> from operator import itemgetter
>>> groups = groupby(xs, key=itemgetter(0))
>>> ys = [(key, sum(map(itemgetter(1), group))) for key, group in groups]
If they aren't, but you can sort them (you have a list, not just an arbitrary iterable, and it isn't so huge that log-linear time will be too expensive):
>>> groups = groupby(sorted(xs, key=itemgetter(0)), key=itemgetter(0))
If you can't sort them, you can manually build up the totals as you go:
>>> from collections import Counter
>>> totals = Counter()
>>> for k, v in xs:
... totals[k] += v
>>> ys = list(totals.items())
yet another way,
t.sort(key=lambda x: x[0]) #sort before groupby (required)
g=itertools.groupby(t, lambda x: x[0])
new_l = []
for k,v in g:
new_l.append((k, sum([x[1] for x in v])))
Another approach is using a defaultdict (from collections) and to iterate the list of tuples.
from collections import defaultdict
lst = [(0, 1), (0, 1), (0, 0), (0, 0), (1, 0), (1, 0), (1, 1), (1, 0), (1, 0), (2, 0), (2, 1), (2, 0), (3, 0), (3, 1), (3, 1), (3, 0), (3, 0), (4, 0), (4, 1), (4, 0), (4, 1), (4, 1), (5, 0), (5, 0), (5, 1), (5, 1)]
d = defaultdict(int)
for (u,v) in lst:
d[u]+=v
# list(d.items()) [(0, 2), (1, 1), (2, 1), (3, 2), (4, 3), (5, 2)]
I'd recommend using a library with a groupby function. pandas, for instance, can be useful
>>> s = pd.DataFrame(list_)
>>> s.groupby(0, as_index=False).sum().agg(tuple,1).tolist()
[(0, 2), (1, 1), (2, 1), (3, 2), (4, 3), (5, 2)]
In [5]: [(j, sum([i[1] for i in a if i[0] == j])) for j in set([i[0] for i in a])]
Out[5]: [(0, 2), (1, 1), (2, 1), (3, 2), (4, 3), (5, 2)]
lst = [(0, 1), (0, 1), (0, 0), (0, 0), (1, 0), (1, 0), (1, 1), (1, 0), (1, 0), (2, 0), (2, 1), (2, 0), (3, 0), (3, 1), (3, 1), (3, 0), (3, 0), (4, 0), (4, 1), (4, 0), (4, 1), (4, 1), (5, 0), (5, 0), (5, 1), (5, 1)]
[(i,sum([q[1] for q in lst if q[0] == i])) for i in range(lst[-1][0]+1)]
gives:
[(0,2),(1,1),(2,1),(3,2),(4,3),(5,2)]
Given a list l=range(n), how can I iterate over all distinct pairs of distinct pairs from that list.
For example, if l = [0,1,2,3] I would like [((0,1), (0,2)),((0,1),(0,3)), ((0,1),(1,2)), ((0,1), (1,3)),((0,1), (2,3)), ((0,2), (0,3)), ((0,2),(1,2)),((0,2),(1,3)),((0,2),(2,3))...
You can use itertools.combinations:
from itertools import combinations
for pair in combinations(combinations(l, 2), 2):
# use pair
The first call creates the initial pairs:
>>> l = [0,1,2,3]
>>> list(combinations(l, 2))
[(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]
The second pairs them again:
>>> list(combinations(combinations(l, 2), 2))
[((0, 1), (0, 2)), ((0, 1), (0, 3)), ((0, 1), (1, 2)), ((0, 1), (1, 3)),
((0, 1), (2, 3)), ((0, 2), (0, 3)), ((0, 2), (1, 2)), ((0, 2), (1, 3)),
((0, 2), (2, 3)), ((0, 3), (1, 2)), ((0, 3), (1, 3)), ((0, 3), (2, 3)),
((1, 2), (1, 3)), ((1, 2), (2, 3)), ((1, 3), (2, 3))]