I've written a small (destructive) function that takes two 2D lists (or "grids" as I call them) and a set of coordinates. It inserts the first grid inside the second grid, assumed to be as big or bigger as the first one (no checks implemented). The coordinates denote the top-left corner of the first grid.
def insert_grid(subj, obj, cords=(0, 0)):
u, v = cords
h = len(subj)
w = len(subj[0])
for y in range(0, h):
for x in range(0, w):
obj[u + y][v + x] = subj[y][x]
I was wondering if there was a cleaner, more pythonic way to achieve the same effect. The standard lib methodology would as always be prefered above everything else.
Thank you. Alisa.
You can simplify slightly:
def insert_grid(subj, obj, cords=(0, 0)):
u, v = cords
w = len(subj[0])
for index, row in enumerate(subj, u):
obj[index][v:v+w] = row
This replaces all columns in a row in one go.
Related
So I need to generate a mean for both the list of x coordinates and the list of y coordinates from one function using another function, but I'm not exactly sure how to do so. Here's what I've got so far, the first function is correct, it's just the second one that needs work, I'm just not sure what to do. 'datafile1' is simply a list of x and y coordinates separated by a tab. I should mention that this has to be done through a separate function, otherwise I would have just done this in a more simpler way.
import math
import statistics
def fileRead():
"Reads the input file and stores the x and y coordinates in a parallel list"
dataFile = open('datafile1.txt', 'r')
dataList = [] # list comprised of x and y pairs
x = [] # list comprised of just x coordinates
y = [] # list comprised of just y coordinates
for dataLine in dataFile:
dataList.append(dataLine)
dataSplit = dataLine.split()
x.append(float(dataSplit[0]))
y.append(float(dataSplit[1]))
return x, y
def getMean(dataList):
"Computes the mean of the data set"
dataMean = statistics.mean(dataList)
return dataMean
Since calculating the mean isn't exactly complex (it's just a function call), why don't you just calculate it inline right after calling fileRead()?
(x, y) = fileRead()
xMean = statistics.mean(x)
yMean = statistics.mean(y)
I am trying to find the last iteration in a loop so that I can skip it. This is not ideal I'm aware, however my issue is separate.
I am new to python, but if I'm not mistaken, this for loop is in unpacking the variable letter. This makes the second run through of the for loop empty or in some sense broken. If my understanding here is in anyway incorrect, feel free to comment or edit.
this_iteration = 0
for [x, y, dx, dy, r], letter in letters_positions:
last_iteration = this_iteration
this_iteration += 1
this_iteration = 0
for [x, y, dx, dy, r], letter in letters_positions:
if this_iteration == last_iteration:
continue
this_iteration += 1
I tried unsuccessfully passing this in the second for loop, but the second for loop still does not run.
for letter in letters_positions:
Is there a way for me to repack the variables together for a second run through the loop?
UPDATE: This is CairoSVG, not my own code, but I'll try to post more context the best I can. letters_positions is taken from an svg file. The important two lines that precede my code are the following.
from .helpers import distance, normalize, point_angle, zip_letters
letters_positions = zip_letters(x, y, dx, dy, rotate, node.text)
Original CairoSVG code can be found on github here.
https://github.com/Kozea/CairoSVG/blob/master/cairosvg/text.py
Edit (example):
this_iteration = 0
letters_positions = list(letters_positions)
for [x, y, dx, dy, r], letter in letters_positions:
last_iteration = this_iteration
this_iteration += 1
this_iteration = 0
for [x, y, dx, dy, r], letter in letters_positions:
if this_iteration == last_iteration:
continue
this_iteration += 1
From helpers.py in the github link you posted:
# Incidentally, they say that this method returns a list with the current letter's positions.
# This isn't true - it is returning a generator.
# To return a list, the outermost parenthesis need to be replaced with square brackets,
# or by simply adding list before the parenthesis
# i.e. [...] or list(...)
def zip_letters(xl, yl, dxl, dyl, rl, word):
"""Returns a list with the current letter's positions (x, y and rotation).
E.g.: for letter 'L' with positions x = 10, y = 20 and rotation = 30:
>>> [[10, 20, 30], 'L']
Store the last value of each position and pop the first one in order to
avoid setting an x,y or rotation value that have already been used.
"""
# Notice the parenthesis below - this is a generator that gets exhausted after one iteration
return (
([pl.pop(0) if pl else None for pl in (xl, yl, dxl, dyl, rl)], char)
for char in word)
Thus, you empty it after the first iteration. Create a list or some other data structure out of it letters_positions = list(letters_positions), and then you can loop over it as many times as you'd like.
letters_positions is a sequence. If you don't want to iterate over the final element, do iterate over letters_positions[:-1]
EDIT: if you're using Python3, you might have to call list on letters_positions first
I have to create 2 functions that involve a 2 dimension list in order to make a grid for a basic Python game :
The first function must take in parameter an int n and return a list of 2 dimensions with n columns and n lines with all values to 0.
The second one must take a 2 dimension list in parameter and print the grid but return nothing.
Here is what I came with:
def twoDList(x, y):
arr = [[x for x in range(6)] for y in range(6)] # x = height and y = width
return arr
def displayGrid(arr):
for i in range(0, 5):
print(arr[i][i])
Could you please help me to improve the code regarding the instructions and help me to understand how to display the whole grid with the code please?
Here are 2 methods using no 3rd party libraries.
One simple way to create a 2D array is to keep appending an array to an array:
for x in range(10): #width
for y in range(10): #height
a.append(y) #you can also append other data is you want it to be empty, this just makes it 0-9
arr.append(a) #add the 1-9
a = [] #clear the inner array
Here, I re-created the same array (a) 10 times, so it's kind of inefficient, but the point is that you can use the same structure with custom data input to make your own 2D array.
Another way to get the exact same 2D array is list comprehension
arr = [[x for x in range(10)] for y in range(10)]
This is probably what you were trying to do with the code you provided, which is, as mentioned in the comments, syntactically incorrect.
To print, just tweak the code you have to have 2 loops: one for x and one for y:
for x in range(5):
for y in range(5):
print(arr[x][y])
I still see erros in your code:
In your first function, since x,y are your inputs, you want to USE them in your list comprehension. You're not using them in your code
def twoDList(x, y):
arr = [[x for x in range(6)] for y in range(6)] # x = height and y = width
return arr
In your example, no matter what the value of x or y is, you're getting a 6x6 grid. You want to use x and y and replace the fixed values you have over there (HINT: change your '6').
Won't do that for you,
In your print function, you might want to use two variables, once per each dimension, to use as indexes.
Also, don't use fixed values in here, get them from your input (i'm guessing this is homework, so won't put the whole code)
def displayGrid(arr):
for i in range(0, 5):
for j in range(0, 5):
print(arr[i][j])
I was trying to write a general program to check The 17x17 problem SOLVED!, 4-coloring of a17x17 grid with no monochromatic rectangles. Solution link: 17.txt.
This is what I wrote:
from itertools import product
def is_solution(myfile,m,n):
""" m-lines, n-columns """
grid = [c.strip() for c in line.split(',')] for line in open(myfile).readlines()]
for x0,y0 in product(xrange(m),xrange(n)):
start = grid[x0][y0]
for x in xrange(x0+1,m):
if grid[x][y0] == start:
for y in xrange(y0+1,n):
if grid[x0][y] == start == grid[x][y]:
return False
return True
print is_solution('17.txt',17,17)
Is there a more readable, concise or efficient way (in that order of priority) to write this? Maybe a different approach with different data structures... Since i am learning Python at the moment, any advice is very welcome.
You should cleanly separate the logic for in-/output from the verification logic (this basically applies to any code). This also includes that you only put definitions at the module's top level. The actual program usually goes into a conditional like in the code below which is only executed if the file is called directly from the command line (and not if it is only imported by another file).
The dimensions of the grid can be derived from the input. No need for separate parameters here.
You should work with integers instead of strings (this is optional, but more clean, IMO)
My attempt (taking the file from STDIN, can be called like python script.py < 17.txt):
import itertools
def has_monochromatic_rectangles(grid):
# use range instead of xrange here (xrange is not in Python 3)
points = list(itertools.product(range(len(grid)), range(len(grid[0]))))
# check if for any rectangle, all 4 colors are equal
# (this is more brute-force than necessary, but you placed simplicity
# above efficiency. Also, for 17x17, it doesn't matter at all ;)
return any(grid[x1][y1] == grid[x1][y2] == grid[x2][y1] == grid[x2][y2]
for (x1,y1), (x2,y2) in itertools.product(points, points)
if x1 != x2 and y1 != y2)
def has_max_colors(grid, most):
# collect all grid values and uniquify them by creating a set
return len(set(sum(grid, []))) <= most
if __name__ == '__main__':
# read from STDIN (could easily be adapted to read from file, URL, ...)
import sys
grid = [map(int, line.split(',')) for line in sys.stdin]
assert has_max_colors(grid, 4)
assert not has_monochromatic_rectangles(grid)
import urllib
grid=urllib.urlopen("http://www.cs.umd.edu/~gasarch/BLOGPAPERS/17.txt")
grid=[map(int,row.split(",")) for row in grid]
print grid
def check_grid(grid):
for i in range(17):
for j in range(17):
for i2 in range(i):
for j2 in range(j):
colours=[grid[a][b] for a in (i,i2) for b in (j,j2)]
assert(len(set(colours))>1)
check_grid(grid)
grid[1][1]=2
check_grid(grid)
Obligatory one-liner*!
Assuming you've loaded the 17x17 data into a numpy array named A (see #robertking's answer to use urllib), you can do it with one line with numpy!
print (array([len(set(A[i:i+k1,j:j+k2][zip(*[(0,0), (0,-1),(-1,0),(-1,-1)])])) for i in xrange(16) for j in xrange(16) for k1 in xrange(2,17) for k2 in xrange(2,17)])!=1).all()
* Don't actually do this in one-line. Here it is expanded out a bit for clarity:
corners = zip(*[(0,0), (0,-1),(-1,0),(-1,-1)])
for k1 in xrange(2,17):
for k2 in xrange(2,17):
for i in xrange(16):
for j in xrange(16):
# Pull out each sub-rectange
sub = A[i:i+k1, j:j+k2]
# Only use the corners
sub = sub[corners]
# Count the number of unique elements
uniq = len(set(sub))
# Check if all corners are the same
if uniq == 1:
print False
exit()
print True
Here is another way to think about it.
import urllib
grid=urllib.urlopen("http://www.cs.umd.edu/~gasarch/BLOGPAPERS/17.txt")
grid=[map(int,row.split(",")) for row in grid]
def check(grid):
colour_positions=lambda c,row:set(i for i,colour in enumerate(row) if colour==c) #given a row and a colour, where in the row does that colour occur
to_check=[[colour_positions(c,row) for row in grid] for c in range(1,5)] #for each row and each colour, get the horizontal positions.
from itertools import combinations
for i in to_check:
for a,b in combinations(i,2):
if len(a&b)>1: #for each colour, for each combination of rows, do we ever get more than 1 horizontal position in common (e.g. a rectangle)
return False
return True
print check(grid)
grid[1][1]=2
print check(grid)
I have a list-of-list-of-lists, where the first two act as a "matrix", where I can access the third list as
list3 = m[x][y]
and the third list contains a mix of strings and numbers, but each list has the same size & structure. Let's call a specific entry in this list The Number of Interest. This number always has the same index in this list!
What's the fastest way to get the 'coordinates' (x,y) for the list that has the largest Number of Interest in Python?
Thank you!
(So really, I'm trying to pick the largest number in m[x][y][k] where k is fixed, for all x & y, and 'know' what its address is)
max((cell[k], x, y)
for (y, row) in enumerate(m)
for (x, cell) in enumerate(row))[1:]
Also, you can assign the result directly to a couple of variables:
(_, x, y) = max((cell[k], x, y)
for (y, row) in enumerate(m)
for (x, cell) in enumerate(row))
This is O(n2), btw.
import itertools
indexes = itertools.product( xrange(len(m)), xrange(len(m[0]))
print max(indexes, key = lambda x: m[x[0]][x[1]][k])
or using numpy
import numpy
data = numpy.array(m)
print numpy.argmax(m[:,:,k])
In you are interested in speeding up operations in python, you really need to look at numpy.
Assuming "The Number of Interest" is in a known spot in the list, and there will be a nonzero maximum,
maxCoords = [-1, -1]
maxNumOfInterest = -1
rowIndex = 0
for row in m:
colIndex = 0
for entry in row:
if entry[indexOfNum] > maxNumOfInterest:
maxNumOfInterest = entry[indexOfNum]
maxCoords = [rowIndex,colIndex]
colIndex += 1
rowIndex += 1
Is a naive method that will be O(n2) on the size of the matrix. Since you have to check every element, this is the fastest solution possible.
#Marcelo's method is more succulent, but perhaps less readable.