format and Print a list in a file - python

i have one list with some coordinates in it, when i am printing it like that:
for i in range(0,len(List)):
print("".join(["(%d, %d) \n" % (y[i], y[i+1]) for y in (List)]))
the output is this:
(0, 3)
(0, 2)
(0, 1)
(1, 1)
(1, 2)
(2, 2)
(2, 1)
(3, 1)
(3, 0)
(2, 0)
(1, 0)
(0, 0)
i want to save the output in a .txt, but that is not a problem, my problem is that the .txt must be formmated like this:
(0, 3), (0, 2)
(0, 2), (0, 1)
(0, 1),(1, 1)
(1, 1),(1, 2)
(1, 2),(2, 2)
.....
i've tried many things but nothing worked..
it must be easy, but i am new to python
thank you in advance

This does the trick:
l = [(0, 3), (0, 2), (0, 1), (1, 1), (1, 2), (2, 2)]
for i in range(0, len(l), 2):
print(', '.join([str(l[i]), str(l[i+1])]))
# (0, 3), (0, 2)
# (0, 1), (1, 1)
# (1, 2), (2, 2)

You can use zip.
mylist = [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
# That doesn't have to be the numbers though, you can use your own.
for a, b in zip(mylist, mylist[1:]):
print("{}, {}".format(a, b), file = myfile) # Will print to myfile.
That's assuming that you are printing to an open file. Leave the file argument out if you don't want to print anywhere else, but the default screen.
in myfile.txt:
(0, 0), (0, 1)
(0, 1), (0, 2)
(0, 2), (1, 0)
(1, 0), (1, 1)
(1, 1), (1, 2)
(1, 2), (2, 0)
(2, 0), (2, 1)
(2, 1), (2, 2)
The output is in tuples, not lists.

Well, besides other answers playing with indices, you can also use zip:
for a, b, c, d in zip(List, List[1:], List[2:], List[3:]):
print('({}, {}), ({}, {})'.format(a, b, c, d))

Regarding expected output:
l = [(0, 3), (0, 2), (0, 1), (1, 1), (1, 2), (2, 2)]
for i,j in zip(l,l[1:]):
print str(i) + "," + str(j) # or print ",".join([str(i),str(j)])
#output
(0, 3),(0, 2)
(0, 2),(0, 1)
(0, 1),(1, 1)
(1, 1),(1, 2)
(1, 2),(2, 2)
If you want list chunking with 2 elements,Try this
def chunks(l, n):
for i in xrange(0, len(l), n):
yield l[i:i+n]
for i,j in list(chunks(l,2)):
print ",".join([str(i),str(j)])
#output
(0, 3),(0, 2)
(0, 1),(1, 1)
(1, 2),(2, 2)

Your code:
for i in range(0,len(List)):
print("".join(["(%d, %d) \n" % (y[i], y[i+1]) for y in (List)]))
Turning this into a list comp.
t = ["".join(["(%d, %d) \n" % (y[i], y[i+1]) for y in (List)]) for i in range(0,len(List))]
(equivalent to)
s = []
for i in range(0,len(List)):
s.append("".join(["(%d, %d) \n" % (y[i], y[i+1]) for y in (List)]))
Then:
first = True
other = None
r = ""
for i in t:
if not first:
r += other+", "+i+"\n"
first = True
else:
other = i
first = False
f = open("out.txt","w")
f.write(t)
f.close() #go to notepad

Related

How to handle return from recursion

I'm trying to make a polyomino generator of level N. I successfully made a function that connects a tile with a root in every possible way and returns all combinations. Now I need to extend this to level N. I've done my best, but still can't handle recursion the right way.
Here's my function:
def connect_n(tiles,root,n=1):
if not isinstance(tiles[0], list): tiles = [tiles]
result = []
if n == 1:
for tile in tiles:
result += connect(tile, root)
return result
else:
return connect_n(tiles, root,n-1)
This function successfully creates N nested functions and executes base case at n==1. But then with obtained result, it just goes up and up and exits with that result without any other iterations. I'm sure I'm missing something. I tried to move conditions and loops around without success.
I have following input:
root = (0,0)
N = 3 #for example, can be any number > 0
Function connect(root,root) returns:
[[(0, 0), (1, 0)]]
Then functionconnect([[(0, 0), (1, 0)]],root) returns
[[(0, 0), (1, 0), (2, 0), (3, 0)],
[(0, 0), (0, 1), (1, 0), (2, 0)],
[(0, 0), (0, 1), (1, 0), (1, 1)],
[(0, 0), (1, 0), (1, 1), (2, 1)]]
And so on.
Function connect_n output should be
[[(0, 0), (1, 0)]] for N=1
[[(0, 0), (1, 0), (2, 0), (3, 0)],
[(0, 0), (0, 1), (1, 0), (2, 0)],
[(0, 0), (0, 1), (1, 0), (1, 1)],
[(0, 0), (1, 0), (1, 1), (2, 1)]] for N=2
And so on.
I'm not sure I understand the algorithm, but I think this is what you want:
def connect_n(tiles, root, n=1):
if n == 1:
return connect(tiles, root)
else:
return connect_n(connect_n(tiles, root, n-1)), root)

How to implement a matrix with classes

I need to implement a matrix with N cells and these cells depend on K parameters, some fixed and other variables. I would like to do all this through the use of classes.
could someone explain to me the basic procedure?
I know, I should not answer this since it's a "homework", but I cannot resist a matrix class!!
Basically, a matrix is nothing more than a list of lists. Implementing it as a class means you should add some basic functionalities (methods) like, get the value of a specific row/column, print the matrix etc...
Here a simple one you can start with:
class Matrix2D:
def __init__(self):
'''
Init an empty matrix.
'''
self.matrix = []
self.rows = 0
self.columns = 0
self.name = 'Unnamed'
def __str__(self):
return self.matrix
def generate(self, rows, columns, verbose=False):
'''
Return a list of lists containing the indices of the matrix (row, col)
and prints it by row.
int, int -> [[(int, int), ...], ...]
'''
self.rows = rows
self.columns = columns
self.matrix = [[(row, col) for col in range(columns)] for row in range(rows)]
if verbose == True:
print(f'Generated a {self.rows} row/s by {self.columns} column/s matrix')
print('--------' * columns)
self.printme()
print('--------' * columns)
return self.matrix
def printme(self, verbose=False):
'''
Print the matrix by row.
'''
if verbose == True:
print(f'I am a {self.rows} row/s by {self.columns} column/s matrix')
for row in self.matrix:
print(row)
def get_row(self, n, verbose=False):
'''
Return the row n of the matrix.
'''
if verbose == True:
print(f'matrix[row={n}]...')
print(self.matrix[n])
return self.matrix[n]
def get_col(self, n, verbose=False):
'''
Return the column n of the matrix.
'''
column_items = []
i = 0
while i < self.rows:
column_items.append(self.matrix[i][n])
i += 1
if verbose == True:
print(f'matrix[col={n}]...')
for item in column_items:
print(item)
return column_items
def get_cell(self, row, col, verbose=False):
'''
Return a specific cell of the matrix.
'''
if verbose == True:
print(f'cell[row={row}, col={col}]...')
print(self.matrix[row][col])
return self.matrix[row][col]
def write_cell(self, row, col, data, verbose=False):
'''
Assign some data to a specific cell of the matrix.
'''
self.matrix[row][col] = data
if verbose == True:
print('Data wrote into cell[row={row}, col={col}]...')
print(self.matrix[row][col])
return self.matrix[row][col]
Test:
print('#########')
m = Matrix2D()
m.generate(4,5,True)
m.printme()
m.get_row(1,True)
m.get_col(1,True)
m.get_cell(3,2,True)
m.write_cell(3,2, (9,9,9),True)
Output:
#########
Generated a 4 row/s by 5 column/s matrix
----------------------------------------
[(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)]
----------------------------------------
[(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)]
matrix[row=1]...
[(1, 0), (1, 1), (1, 2), (1, 3), (1, 4)]
matrix[col=1]...
(0, 1)
(1, 1)
(2, 1)
(3, 1)
cell[row=3, col=2]...
(3, 2)
Data wrote into cell[row={row}, col={col}]...
(9, 9, 9)
Next, you can add some extra methods for more fancy operations like matrix multiplication, transposition etc... Have fun!

Remove duplicate unordered tuples from list

In a list of tuples, I want to have just one copy of a tuple where it may be (x, y) or (y, x).
So, in:
# pairs = list(itertools.product(range(3), range(3)))
pairs = [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
the result should be:
result = [(0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2)] # updated pairs
This list of tuples is generated using itertools.product() but I want to remove the duplicates.
My working solution:
pairs = [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
result = []
for pair in pairs:
a, b = pair
# reordering in increasing order
temp = (a, b) if a < b else (b, a)
result.append(temp)
print(list(set(result))) # I could use sorted() but the order doesn't matter
How can this be improved?
You could use combinations_with_replacement
The code for combinations_with_replacement() can be also expressed as a subsequence of product() after filtering entries where the elements are not in sorted order (according to their position in the input pool)
import itertools
pairs = list(itertools.combinations_with_replacement(range(3), 2))
print(pairs)
>>> [(0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2)]
edit I just realized, your solution matches my solution. What you are doing is just fine. If you need to do this for a very large list, then there are some other options you may want to look into, like a key value store.
If you need to remove dupes more programatically, then you can use a function like this:
def set_reduce(pairs):
new_pairs = set([])
for x,y in pairs:
if x < y:
new_pairs.add((x,y))
else:
new_pairs.add((y,x))
return new_pairs
running this results in
>>>set_reduce(pairs)
set([(0, 1), (1, 2), (0, 0), (0, 2), (2, 2), (1, 1)])
This is one solution which relies on sparse matrices. This works for the following reasons:
An entry in a matrix cannot contain two values. Therefore, uniqueness is guaranteed.
Selecting the upper triangle ensures that (0, 1) is preferred above (1, 0), and inclusion of both is not possible.
import numpy as np
from scipy.sparse import csr_matrix, triu
lst = [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1),
(1, 2), (2, 0), (2, 1), (2, 2)]
# get row coords & col coords
d1, d2 = list(zip(*lst))
# set up sparse matrix inputs
row, col, data = np.array(d1), np.array(d2), np.array([1]*len(lst))
# get upper triangle of matrix including diagonal
m = triu(csr_matrix((data, (row, col))), 0)
# output coordinates
result = list(zip(*(m.row, m.col)))
# [(0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2)]

Shorten a list of tuples by cutting out loops?

I have a function that generates a list of tuples like:
[(0, 0), (1, 1), (1, 2), (1,3), (2, 4), (3, 5), (4, 5)]
which are used to represent a path of tiles (row, column) in a game I'm making.
The function that I use to generate these paths isn't perfect, since it often produces "loops", as shown below:
[(2, 0), (2, 1), (1, 2), (0, 3), (0, 4), (1, 5), (2, 5), (3, 4), (3, 3),
(3, 2), (4, 1)]
The path above should instead look like:
[(2, 0), (2, 1), (3, 2), (4, 1)]
These paths can contain any number of loops, which can be of any size and shape.
So my question is, how do I write a function in python that cuts the loopy list and returns a new, shorter list that does not have these loops.
My attempt below:
def Cut_Out_Loops(Path):
NewList = list(Path)
Cutting = True
a = 0
for Cords in Path:
a += 1
try:
for i in range(a + 2, len(Path)):
if (Path[i][0] == Cords[0] and abs(Path[i][1] - Cords[1]) == 1:
NewList = NewList[0:a] + NewList[i:]
Path = list(NewList)
elif Path[i][1] == Cords[1] and abs(Path[i][0] - Cords[0]) == 1:
NewList = NewList[0:a] + NewList[i:]
Path = list(NewList)
elif abs(Path[i][0] - Cords[0]) == 1 and abs(Path[i][1] - Cords[1]) == 1:
NewList = NewList[0:a] + NewList[i:]
Path = list(NewList)
elif abs(Path[i][1] - Cords[1]) == 1 and abs(Path[i][0] - Cords[0]) == 1:
NewList = NewList[0:a] + NewList[i:]
Path = list(NewList)
Cutting = False
except IndexError:
Cutting = True
Although your definition of a "loop" isn't too clear, try this
def clean(path):
path1 = []
for (x1,y1) in path:
for (i,(x2,y2)) in enumerate(path1[:-1]):
if abs(x1-x2) <= 1 and abs(y1-y2) <= 1:
path1 = path1[:i+1]
break
path1.append((x1,y1))
return path1
It definitely works for your example:
>>> path = [(2, 0), (2, 1), (1, 2), (0, 3), (0, 4), (1, 5), (2, 5), (3, 4), (3, 3), (3, 2), (4, 1)]
>>> clean(path)
[(2, 0), (2, 1), (3, 2), (4, 1)]
That said, it is just the most straightforward of brute force solutions. The complexity is quadratic.
How long are your paths? If they're all under 1000 elements, even a naive brute-force algorithm would work:
path = [
(2, 0),
(2, 1),
(1, 2),
(0, 3),
(0, 4),
(1, 5),
(2, 5),
(3, 4),
(3, 3),
(3, 2),
(4, 1)
]
def adjacent(elem, next_elem):
return (abs(elem[0] - next_elem[0]) <= 1 and
abs(elem[1] - next_elem[1]) <= 1)
new_path = []
i = 0
while True:
elem = path[i]
new_path.append(elem)
if i + 1 == len(path):
break
j = len(path) - 1
while True:
future_elem = path[j]
if adjacent(elem, future_elem):
break
j -= 1
i = j
print new_path

Python itertools.product reorder the generation

I have this:
shape = (2, 4) # arbitrary, could be 3 dimensions such as (3, 5, 7), etc...
for i in itertools.product(*(range(x) for x in shape)):
print(i)
# output: (0, 0) (0, 1) (0, 2) (0, 3) (1, 0) (1, 1) (1, 2) (1, 3)
So far, so good, itertools.product advances the rightmost element on every iteration. But now I want to be able to specify the iteration order according to the following:
axes = (0, 1) # normal order
# output: (0, 0) (0, 1) (0, 2) (0, 3) (1, 0) (1, 1) (1, 2) (1, 3)
axes = (1, 0) # reversed order
# output: (0, 0) (1, 0) (2, 0) (3, 0) (0, 1) (1, 1) (2, 1) (3, 1)
If shapes had three dimensions, axes could have been for instance (0, 1, 2) or (2, 0, 1) etc, so it's not a matter of simply using reversed(). So I wrote some code that does that but seems very inefficient:
axes = (1, 0)
# transposed axes
tpaxes = [0]*len(axes)
for i in range(len(axes)):
tpaxes[axes[i]] = i
for i in itertools.product(*(range(x) for x in shape)):
# reorder the output of itertools.product
x = (i[y] for y in tpaxes)
print(tuple(x))
Any ideas on how to properly do this?
Well, this is in fact a manual specialised product. It should be faster since axes are reordered only once:
def gen_chain(dest, size, idx, parent):
# iterate over the axis once
# then trigger the previous dimension to update
# until everything is exhausted
while True:
if parent: next(parent) # StopIterator is propagated upwards
for i in xrange(size):
dest[idx] = i
yield
if not parent: break
def prod(shape, axes):
buf = [0] * len(shape)
gen = None
# EDIT: fixed the axes order to be compliant with the example in OP
for s, a in zip(shape, axes):
# iterate over the axis and put to transposed
gen = gen_chain(buf, s, a, gen)
for _ in gen:
yield tuple(buf)
print list(prod((2,4), (0,1)))
# [(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3)]
print list(prod((2,4), (1,0)))
# [(0, 0), (1, 0), (2, 0), (3, 0), (0, 1), (1, 1), (2, 1), (3, 1)]
print list(prod((4,3,2),(1,2,0)))
# [(0, 0, 0), (1, 0, 0), (0, 0, 1), (1, 0, 1), (0, 0, 2), (1, 0, 2), ...
If you can afford it memory-wise: Let itertools.product do the hard work, and use zip to switch the axes around.
import itertools
def product(shape, axes):
prod_trans = tuple(zip(*itertools.product(*(range(shape[axis]) for axis in axes))))
prod_trans_ordered = [None] * len(axes)
for i, axis in enumerate(axes):
prod_trans_ordered[axis] = prod_trans[i]
return zip(*prod_trans_ordered)
Small test:
>>> print(*product((2, 2, 4), (1, 2, 0)))
(0, 0, 0) (1, 0, 0) (0, 0, 1) (1, 0, 1) (0, 0, 2) (1, 0, 2) (0, 0, 3) (1, 0, 3) (0, 1, 0) (1, 1, 0) (0, 1, 1) (1, 1, 1) (0, 1, 2) (1, 1, 2) (0, 1, 3) (1, 1, 3)
The above version is fast if there are not too may products. For large result sets, the following is faster, but... uses eval (although in a rather safe way):
def product(shape, axes):
d = dict(("r%i" % axis, range(shape[axis])) for axis in axes)
text_tuple = "".join("x%i, " % i for i in range(len(axes)))
text_for = " ".join("for x%i in r%i" % (axis, axis) for axis in axes)
return eval("((%s) %s)" % (text_tuple, text_for), d)
Edit: If you want to not only change the order of iteration, but also the shape (as in the OP's example), small changes are needed:
import itertools
def product(shape, axes):
prod_trans = tuple(zip(*itertools.product(*(range(s) for s in shape))))
prod_trans_ordered = [None] * len(axes)
for i, axis in enumerate(axes):
prod_trans_ordered[axis] = prod_trans[i]
return zip(*prod_trans_ordered)
And the eval version:
def product(shape, axes):
d = dict(("r%i" % axis, range(s)) for axis, s in zip(axes, shape))
text_tuple = "".join("x%i, " % i for i in range(len(axes)))
text_for = " ".join("for x%i in r%i" % (axis, axis) for axis in axes)
return eval("((%s) %s)" % (text_tuple, text_for), d)
Test:
>>> print(*product((2, 2, 4), (1, 2, 0)))
(0, 0, 0) (1, 0, 0) (2, 0, 0) (3, 0, 0) (0, 0, 1) (1, 0, 1) (2, 0, 1) (3, 0, 1) (0, 1, 0) (1, 1, 0) (2, 1, 0) (3, 1, 0) (0, 1, 1) (1, 1, 1) (2, 1, 1) (3, 1, 1)
I don't know how efficient this is, but you should be able to do something like this...
shape = (2, 4, 3)
axes = (2, 0, 1)
# Needed to get the original ordering back
axes_undo = tuple(reversed(axes))
# Reorder the shape in a configuration so that .product will give you
# the order you want.
reordered = tuple(reversed(map(lambda x: shape[x], list(axes))))
# When printing out the results from .product, put the results back
# into the original order.
for i in itertools.product(*(range(x) for x in reordered)):
print(tuple(map(lambda x: i[x], list(axes_undo))))
I tried is up to 4 dimensions and it seems to work. ;)
I'm just swapping the dimensions around and then swapping them back.
Have you tried timing to see how much longer it takes? What you have shouldn't be much slower than without reordering.
You could try modify what you have to use in-place splice assignment.
tpaxes = tuple(tpaxes)
for i in itertools.product(*(range(x) for x in shape)):
# reorder the output of itertools.product
i[:] = (i[y] for y in tpaxes)
print(tuple(x))
Also you could get a speedup by making tpaxes a local variable of a function rather than a global variable (which has slower lookup times)
Otherwise my suggestion is somehow write your own product function..
for i in itertools.product(*(range(x) for x in reversed(shape))):
print tuple(reversed(i))
import itertools
normal = (0, 1)
reverse = (1, 0)
def axes_ordering(x):
a, b = x
return b - a
shape = (2, 4)
for each in itertools.product(*(range(x) for x in shape)):
print(each[::axes_ordering(normal)], each[::axes_ordering(reverse)])
result:
(0, 0) (0, 0)
(0, 1) (1, 0)
(0, 2) (2, 0)
(0, 3) (3, 0)
(1, 0) (0, 1)
(1, 1) (1, 1)
(1, 2) (2, 1)
(1, 3) (3, 1)

Categories

Resources