python codefights Count The Black Boxes, modeling the diagonal of a rectangle - python

Given the dimensions of a rectangle,(m,n), made up of unit squares, output the number of unit squares the diagonal of the rectangle touches- that includes borders and vertices.
My algorithm approaches this by cycling through all the unit squares(under assumption that can draw our diagonal from (0,0) to (m,n)
My algorithm solves 9 of 10 tests, but is too inefficient to solve the tenth test in given time.
I"m uopen to all efficiency suggestions, but in the name of asking a specific question... I seem to be having a disconnect in my own logic concerning adding a break statement, to cut some steps out of the process. My thinking is, this shouldn't matter, but it does affect the result, and I haven't been able to figure out why.
So, can someone help me understand how to insert a break that doesn't affect the output.
Or how to eliminate a loop. I"m currently using nested loops.
So, yeah, I think my problems are algorithmic rather than syntax.
def countBlackCells(m, n):
counter=0
y=[0,0]
testV=0
for i in xrange(n): #loop over m/x first
y[0]=float(m)/n*i
y[1]=float(m)/n*(i+1)
#print(str(y))
for j in xrange(m): #loop over every n/y for each x
if((y[0]<=(j+1) and y[0]>=j) or (y[1]>=(j) and y[1]<=j+1)):#is min of line in range inside teh box? is max of line?
counter+=1
#testV += 1
else: pass # break# thinking that once you are beyond the line in either direction, your not coming back to it by ranging up m anymore. THAT DOESN"T SEEM TO BE THE CASE
#tried adding a flag (testV), so that inner loop would only break if line was found and then lost again, still didn't count ALL boxes. There's something I'm not understanding here.
return counter
Some sample, input/output
Input:
n: 3
m: 4
Output:
6
Input:
n: 3
m: 3
Output:
7
Input:
n: 33
m: 44
Output:
86

Find G - the greatest common divisor of m and n.
If G > 1 then diagonal intersects G-1 inner vertices, touching (not intersecting) 2*(G-1) cells.
And between these inner vertices there are G sub-rectangles with mutually prime sides M x N (m/G x n/G)
Now consider case of mutually prime M and N. Diagonal of such rectangle does not intersect any vertex except for starting and ending. But it must intersect M vertical lines and N horizontal lines, and at every intersection diagonal enters into the new cell, so it intersects M + N - 1 cells (subtract 1 to account for the first corner where both vertical and horizontal lines are met together)
So use these clues and deduce final solution.

I used math.gcd() to solve the problem in python.
def countBlackCells(n, m):
return m+n+math.gcd(m,n)-2

Related

Possible ways to draw n diagonals in an mxm square such that they do not touch each other

I'm trying to write the code to draw n diagonals in an m by m square such that they do not touch each other.
For example, for m=2 and n=3:
I tried to approach it by creating a list of pairs of points by generating the permutations and checking the solution before proceeding. Therefore, I have (m+1)*(m+1) points that create the cells of an m by m square.
def dist(a,b):
return ((a[0] - b[0])**2 + (a[1] - b[1])**2)**.5
def can_be_extended_to_solution(perm):
i = len(perm) - 1
for j in range(i):
for k in range(2):
for l in range(2):
if dist(perm[i][k],perm[j][l]) == 0:
return False
return True
def diagonal(perm,n,m):
if len(perm)==n:
print(perm)
return
temp =[]
for k in range(m):
for i in range(m):
if [k,i] not in perm:
for j in [+1,-1]:
if [k+j,i+j] not in perm and (k+j<m and i+j<m) and (0<k+j and 0<i+j):
temp = [[k,i],[k+j,i+j]]
perm.append(temp)
if can_be_extended_to_solution(perm):
diagonal(perm,n,m)
perm.pop()
m=2
n=3
diagonal([],m+1,n)
The output:
The code works and I'm getting the expected result. However, it's very slow. I'm trying to learn to improve my coding skills and do it more efficiently. So, I'd appreciate it if someone reviews my code and tells me what I can do better and what mistakes I'm making. I see that I have many loops and that's the reason for the slow speed, but I can't figure out any other way to implement those loops or avoid them.
Unique Diagonals
An algorithmic map of the unique diagonals
Probably, the code can improve if you try using the algorithm based on this pattern.
I am using 1 as positive diagonal, -1 as negative (slope=-45deg) diagonal.
My impression on the pattern is that based on the starting cell and neighbouring cells will get selected based on this.
I may update this answer with some code if possible. Does this help?
More inputs may help. let me know.

Combining recursion with a loop to find maximal value

I am trying to solve a recursion exercise and get really confused.
the question is as follows:
let's say i have an apartment which is n squared meters,
i = [1,2,3..., n] are units of square meters, and [p1, p2, p3, ..., pn] are the corresponding prices per square meter (for ex. p1 is the price for 1 squared meter, and pn is the price for n squared meters).
I want to find the optimal way to divide my apartment which will give me the "maximal income".
Example - if i have 4 squared meter apartment, and the price list for the sizes 1,2,3,4 are correspondingly [1,5,8,9], then these are the set of options:
leave the apartment as one 4 squared meter unit (value: 9)
split the 4 square meters into 1,1,1,1 square meters (total value: 4)
split the 4 square meters into 1,1,2 square meters (total value: 7)
split the 4 square meters into 2,2 square meters (total value: 10)
split the 4 square meters into 1,3 square meters (total value: 9)
therefore my function "profit" should return the number 10 for the input:
profit([1,5,8,9], 4)
i have been asked to solve this using the following pattern where recursion calls must be only inside the loop:
def profit(value, size):
...
for i in range(size):
...
return ...
i managed to solve this without the loop condition after a very long time, but it really frustrates me how hard and un-intuitive recursion function are.
i would really appreciate general guidance tips for these kind of question, or even if you can refer me to other sources which might help me learn this topic better. it's too hard for me to follow sometimes.
and of course, would appreciate your help with this specific function...
Solved it using the following function:
def profit(value,size):
if size <= 0:
return 0
lst1 = []
for i in range(size):
lst1.append(profit(value, size-(i+1))+value[i])
return max(lst1)
You can create a function that finds the possible combinations of the range of the square size. Then, for each combination that sums to four, the maximum floor size can be found:
def profit(value, size):
def combinations(d, _size, current = []):
if sum(current) == _size:
yield current
else:
for i in d:
if sum(current+[i]) <= _size:
yield from combinations(d, _size, current+[i])
options = list(combinations(range(1, size+1), size))
prices = dict(zip(range(1, size+1), value))
result = max(options, key=lambda x:sum(prices[i] for i in x))
return sum(prices[i] for i in result)
print(profit([1,5,8,9], 4))
Output:
10
I don't want to give you the full answer, since this seems like it could be an assignment. However, I will try to push you in the right direction as to why recursion is optimal here. I've added one line of code to your example that I think will help you out. Before adding it to your code, I suggest you try to completely wrap your head around what is happening here.
def profit(value, size):
for i in range(size):
# Get the profit of the size before this combined with a 1
profit(value, size - 1) + profit(value, 1)
If you're having trouble understanding why this is useful, feel free to leave a comment and I can give you a more in depth explanation later.
EDIT:
A key concept to keep in mind when implementing a recursive function are your base cases.
In this example, you already know what the values are for each size, so incorporate that into your solution.
def profit(value, size):
# BASE CASE
if size == 1 :
return value[0]
# Size > 1
for i in range(size):
# Return the maximum value of all given combinations.
return max(value[size], profit(value, size - 1) + profit(value, 1))
This is an almost complete solution now, there's just one piece missing.
Hint: This code currently fails to test profit(value, 2) + profit(value, 2) (which happens to be the maximum profit in this scenario)

Efficient Particle-Pair Interactions Calculation

I have an N-body simulation that generates a list of particle positions, for multiple timesteps in the simulation. For a given frame, I want to generate a list of the pairs of particles' indices (i, j) such that dist(p[i], p[j]) < masking_radius. Essentially I'm creating a list of "interaction" pairs, where the pairs are within a certain distance of each other. My current implementation looks something like this:
interaction_pairs = []
# going through each unique pair (order doesn't matter)
for i in range(num_particles):
for j in range(i + 1, num_particles):
if dist(p[i], p[j]) < masking_radius:
interaction_pairs.append((i,j))
Because of the large number of particles, this process takes a long time (>1 hr per test), and it is severely limiting to what I need to do with the data. I was wondering if there was any more efficient way to structure the data such that calculating these pairs would be more efficient instead of comparing every possible combination of particles. I was looking into KDTrees, but I couldn't figure out a way to utilize them to compute this more efficiently. Any help is appreciated, thank you!
Since you are using python, sklearn has multiple implementations for nearest neighbours finding:
http://scikit-learn.org/stable/modules/neighbors.html
There is KDTree and Balltree provided.
As for KDTree the main point is to push all the particles you have into KDTree, and then for each particle ask query: "give me all particles in range X". KDtree usually do this faster than bruteforce search.
You can read more for example here: https://www.cs.cmu.edu/~ckingsf/bioinfo-lectures/kdtrees.pdf
If you are using 2D or 3D space, then other option is to just cut the space into big grid (which cell size of masking radius) and assign each particle into one grid cell. Then you can find possible candidates for interaction just by checking neighboring cells (but you also have to do a distance check, but for much fewer particle pairs).
Here's a fairly simple technique using plain Python that can reduce the number of comparisons required.
We first sort the points along either the X, Y, or Z axis (selected by axis in the code below). Let's say we choose the X axis. Then we loop over point pairs like your code does, but when we find a pair whose distance is greater than the masking_radius we test whether the difference in their X coordinates is also greater than the masking_radius. If it is, then we can bail out of the inner j loop because all points with a greater j have a greater X coordinate.
My dist2 function calculates the squared distance. This is faster than calculating the actual distance because computing the square root is relatively slow.
I've also included code that behaves similar to your code, i.e., it tests every pair of points, for speed comparison purposes; it also serves to check that the fast code is correct. ;)
from random import seed, uniform
from operator import itemgetter
seed(42)
# Make some fake data
def make_point(hi=10.0):
return [uniform(-hi, hi) for _ in range(3)]
psize = 1000
points = [make_point() for _ in range(psize)]
masking_radius = 4.0
masking_radius2 = masking_radius ** 2
def dist2(p, q):
return (p[0] - q[0])**2 + (p[1] - q[1])**2 + (p[2] - q[2])**2
pair_count = 0
test_count = 0
do_fast = 1
if do_fast:
# Sort the points on one axis
axis = 0
points.sort(key=itemgetter(axis))
# Fast
for i, p in enumerate(points):
left, right = i - 1, i + 1
for j in range(i + 1, psize):
test_count += 1
q = points[j]
if dist2(p, q) < masking_radius2:
#interaction_pairs.append((i, j))
pair_count += 1
elif q[axis] - p[axis] >= masking_radius:
break
if i % 100 == 0:
print('\r {:3} '.format(i), flush=True, end='')
total_pairs = psize * (psize - 1) // 2
print('\r {} / {} tests'.format(test_count, total_pairs))
else:
# Slow
for i, p in enumerate(points):
for j in range(i+1, psize):
q = points[j]
if dist2(p, q) < masking_radius2:
#interaction_pairs.append((i, j))
pair_count += 1
if i % 100 == 0:
print('\r {:3} '.format(i), flush=True, end='')
print('\n', pair_count, 'pairs')
output with do_fast = 1
181937 / 499500 tests
13295 pairs
output with do_fast = 0
13295 pairs
Of course, if most of the point pairs are within masking_radius of each other, there won't be much benefit in using this technique. And sorting the points adds a little bit of time, but Python's TimSort is rather efficient, especially if the data is already partially sorted, so if the masking_radius is sufficiently small you should see a noticeable improvement in the speed.

Minimum number of iterations in matrix where cell value replaced by maximum of neighbour cell value in single iteration

I have an matrix with values in each cell (minimum value=1), where the maximum value is 'max'.
At a time, I modify each cell value by the highest value of its neighboring cells i.e. all 8 neighbors, and this occurs for the whole matrix, simultaneously. I want to find after what minimum number of iterations after which value of all cells will be max.
One brute force method of doing this is by padding the matrix by zeros, and
for i in range (1,x_max+1):
for j in range(1,y_max+1):
maximum = 0
for k in range(-1,2):
for l in range(-1,2):
if matrix[i+k][j+l]>maximum:
maximum = matrix[i+k][j+l]
matrix[i][j] = maximum
But is there an intelligent and faster way of doing this?
Thanks in advance.
I think this can be solved by BFS(Breadth first Search).
Start BFS simulatneously with all the matrix cells with 'max' value.
dis[][] == infinite // min. distance of cell from nearest cell with 'max' value, initially infinite for all
Q // Queue
M[][] // matrix
for all i,j // travers the matrix, enqueue all cells with 'max'
if M[i][j] == 'max'
dis[i][j] = 0 , Q.push( cell(i,j) )
while !Q.empty:
cell Current = Q.front
for all neighbours Cell(p,q) of Current:
if dis[p][q] == infinite
dis[p][q] = dis[Current.row][Current.column] + 1
Q.push( cell(p,q))
Q.pop()
The cell with max(dis[i][j]) for all i,j will be the no. of iterations needed.
Use an array with a "border".
Testing the edge conditions is tedious and can be avoided by making the array 1-bigger around the edge, each element with the value of INT_MIN.
Additionally, consider 8 tests, rather than a double nested loop
// Data is in matrix[1...N][1...M], yet is size matrix[N+2][M+2]
for (i=1; i <= N; i++) {
for (j=1; j <= M; j++) {
maximum = matrix[i-1][j-l];
if (matrix[i-1][j+0] > maximum) maximum = matrix[i-1][j+0];
if (matrix[i-1][j+1] > maximum) maximum = matrix[i-1][j+1];
if (matrix[i+0][j-1] > maximum) maximum = matrix[i+0][j-1];
if (matrix[i+0][j+0] > maximum) maximum = matrix[i+0][j+0];
if (matrix[i+0][j+1] > maximum) maximum = matrix[i+0][j+1];
if (matrix[i+1][j-1] > maximum) maximum = matrix[i+1][j-1];
if (matrix[i+1][j+0] > maximum) maximum = matrix[i+1][j+0];
if (matrix[i+1][j+1] > maximum) maximum = matrix[i+1][j+1];
newmatrix[i][j] = maximum
All existing answers require examining every cell in the matrix. If you don't already know what the locations of the maximum value are, this is unavoidable, and in that case, Amit Kumar's BFS algorithm has optimal time complexity: O(wh), if the matrix has width w and height h.
OTOH, perhaps you already know the locations of the k maximum values, and k is relatively small. In that case, the following algorithm will find the answer in just O(k^2*(log(k)+log(max(w, h)))) time, which is much faster when either w or h is large. It doesn't actually look at any matrix entries; instead, it runs a binary search to look for candidate stopping times (that is, answers). For each candidate stopping time it builds the set of rectangles that would be occupied by max by that time, and checks whether any matrix cell remains uncovered by a rectangle.
To explain the idea, we first need some terms. Call the top row of a rectangle a "starting vertical event", and the row below its bottom edge an "ending vertical event". A "basic interval" is the interval of rows spanned by any pair of vertical events that does not have a third vertical event anywhere between them (the event pairs defining these intervals can be from the same or different rectangles). Notice that with k rectangles, there can never be more than 2k+1 basic intervals -- there is no dependence here on h.
The basic idea is to walk left-to-right through the columns of the matrix that correspond to horizontal events: columns in which either a new rectangle "starts" (the left vertical edge of a rectangle), or an existing rectangle "finishes" (the column to the right of the right vertical edge of a rectangle), keeping track of how many rectangles are currently covering every basic interval. If we ever detect a basic interval covered by 0 rectangles, we can stop: we have found a column containing one or more cells that are not yet covered at time t. If we get to the right edge of the matrix without this happening, then all cells are covered at time t.
Here is pseudocode for a function that checks whether any matrix cell remains uncovered by time t, given a length-k array peak, where (peak[i].x, peak[i].y) is the location of the i-th max-containing cell in the original matrix, in increasing order of x co-ordinate (so the leftmost max-containing cell is at (peak[1].x, peak[1].y)).
Function IsMatrixCovered(t, peak[]) {
# Discover all vertical events and basic intervals
Let vertEvents[] be an empty array of integers.
For i from 1 to k:
top = max(1, peak[i].y - t)
bot = min(h, peak[i].y + t)
Append top to vertEvents[]
Append bot+1 to vertEvents[]
Sort vertEvents in increasing order, and remove duplicates.
x = 1
Let horizEvents[] be an empty array of { col, type, top, bot } structures.
For i from 1 to k:
# Calculate the (clipped) rectangle that peak[i] will cover at time t:
lft = max(1, peak[i].x - t)
rgt = min(w, peak[i].x + t)
top = max(1, peak[i].y - t)
bot = min(h, peak[i].y + t)
# Convert vertical positions to vertical event indices
top = LookupIndexUsingBinarySearch(top, vertEvents[])
bot = LookupIndexUsingBinarySearch(bot+1, vertEvents[])
# Record horizontal events
Append (lft, START, top, bot) to horizEvents[]
Append (rgt+1, STOP, top, bot) to horizEvents[]
Sort horizEvents in increasing order by its first 2 fields, with START considered < STOP.
# Walk through all horizontal events, from left to right.
Let basicIntervals[] be an array of size(vertEvents[]) integers, initially all 0.
nOccupiedBasicIntervalsFirstCol = 0
For i from 1 to size(horizEvents[]):
If horizEvents[i].type = START:
d = 1
Else (if it is STOP):
d = -1
If horizEvents[i].col <= w:
For j from horizEvents[i].top to horizEvents[i].bot:
If horizEvents[i].col = 1 and basicIntervals[j] = 0:
++nOccupiedBasicIntervalsFirstCol # Must be START
basicIntervals[j] += d
If basicIntervals[j] = 0:
return FALSE
If nOccupiedBasicIntervalsFirstCol < size(basicIntervals):
return FALSE # Could have checked earlier, but the code is simpler this way
return TRUE
}
The above function can simply be called inside a binary search on t, that looks for the smallest value of t for which the function returns TRUE.
A further factor of k/log(k) could be removed by exploiting the fact that the set of basic intervals affected by any rectangle starting or ending is always an interval, through the use of Fenwick trees.

How can I check if a point is below a line or not ?

How can I check if a point is below a line or not ?
I've the following data:
Line [ {x1,y1}, {x2,y2} ]
Points {xA,yA}, {xB,yB} ...
I need to write a small algorithm in python to detect points on one side and the other side of the line.
thanks
You could try using a cross product -- http://en.wikipedia.org/wiki/Cross_product.
v1 = (x2-x1, y2-y1) # Vector 1
v2 = (x2-xA, y2-yA) # Vector 2
xp = v1[0]*v2[1] - v1[1]*v2[0] # Cross product
if xp > 0:
print('on one side')
elif xp < 0:
print('on the other')
else:
print('on the same line!')
You'd need to calibrate what each side is. If you want it to be "below" or "above" you need to ensure the points on the line are sorted horizontally.
I haven't tested this.
Edit I initially put in the dot product formula. :o
Edit 2 D'oh, I was putting the coordinates into a set instead of a tuple. Using namedtuple('point', 'x y') for the vectors is nice if you're running a reasonably modern version of Python.
Luckily I found Calculating a 2D Vector's Cross Product.
You could try using a cross product, but the trick is how to choose the point to form a vector, here I choose the closest point from points, assume I got pointA(you can fairly loop points to calculate to distance from loop point to Line):
v1 = {x2-x1, y2-y1} # Vector 1
v2 = {xA-x1, yA-y1} # Vector 2
cross_product = v1.x*v2.y - v1.y*v2.x
if cross_product > 0:
print 'pointA is on the counter-clockwise side of line'
elif cross_product < 0:
print 'pointA is on the clockwise side of line'
else:
print 'pointA is exactly on the line'
Lets say you've given 2 points A, B and you want to know in which halfplane a third point C lies. The terms "below" and "above" as criteria are very vague, so you need a reference point, for example the origin. Just be sure this reference point is not collinear with A and B.
What you have now is a triangle (A, B, C). Using the determinant you can calculate the signed area (see here, or here). The only interesting thing here is to remember the sign.
Next step: for a given point D calculate the signed area of the triangle (A, B, D). If the result has the same sign as the area of your reference triangle -> C and D are on the same side of (A, B). If the sign differs -> C and D lie on opposite sides of the line. If the area of (A, B, D) is 0 then A, B and D are collinear. Note: use the Python builtin cmp to compare the triangle areas.

Categories