HiveBrain v1.2.0
Get Started
← Back to all entries
debugpythonMinor

Checking for intersection points

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
pointscheckingforintersection

Problem

The aim of the program is to find those points which comes under the intersection of at least 2 circles.(space is a 1000x1000 matrix)

n=input()
mat=[[0 for i in range(1005)] for i in range(1005)]
circles=[]

for i in range(n):
    circles.append(map(int,raw_input().split()))

ans=0 
for circle in circles:
    minx=circle[0]-circle[2]
    maxx=circle[0]+circle[2]
    miny=circle[1]-circle[2]
    maxy=circle[1]+circle[2]
    for i in range(minx,maxx+1):
        for j in range(miny,maxy+1):
            if mat[i][j]1:
                        ans+=1
print ans


n denoted the number of circle circles contain circle center and radius in the format [x,y,r]. For example, let circles = [[3,2,4],[2,5,2]]. Then it contains two circles centered at (3,2) and (2,5) with radius 4 and 2 respectively.

Is the logic correct? Will it trigger any exceptions?

Solution

Bad things will happen if any part of any circle strays outside the 0-to-1005 bounds. It's up to you to decide whether error handling for straying out of bounds is essential.

Mild rewrite

Representing each circle as a list is not quite appropriate. Using indexes circle[0], circle[1], and circle.[2] to mean x, y, and r, respectively, is awkward. As a remedy, I strongly recommend namedtuple.

from collections import namedtuple

Circle = namedtuple('Circle', ['x', 'y', 'r'])
n = int(raw_input())
circles = []
for i in range(n):
    circles.append(Circle(*map(int, raw_input().split())))


Initialization of a 1005 × 1005 grid is better written as:

mat = [[0] * 1005] * 1005


The rest of the program is straightforward. You should avoid switching nomenclature from x, y to i, j. To reduce nesting, you can eliminate one nested if by using and.

ans = 0 
for circle in circles:
    minx, maxx = circle.x - circle.r, circle.x + circle.r
    miny, maxy = circle.y - circle.r, circle.y + circle.r
    for x in range(minx, maxx+1):
        for y in range(miny, maxy+1):
            if mat[x][y] <= 1 and (x-circle.x)**2 + (y-circle.y)**2 <= circle.r**2:
                mat[x][y] += 1
                if mat[x][y] == 2:
                    ans += 1
print ans


Going further

The nesting of for: for: for: if: if is still rather overwhelming. I think it would be beneficial to split out some of that complexity.

class Circle (namedtuple('Circle', ['x', 'y', 'r'])):
    def contains(self, x, y):
        return (x - self.x)**2 + (y - self.y)**2 <= self.r**2

    def grid_points(self):
        for x in xrange(self.x - self.r, self.x + self.r + 1):
            for y in xrange(self.y - self.r, self.y + self.r + 1):
                if self.contains(x, y):
                    yield x, y

def read_ints():
    return map(int, raw_input().split())

n = int(raw_input())
circles = [Circle(*read_ints()) for _ in xrange(n)]

mat = [[0] * 1005] * 1005
ans = 0 
for circle in circles:
    for x, y in circle.grid_points():
        mat[x][y] += 1
        if mat[x][y] == 2:
            ans += 1
print ans


The way I've written it, I've removed the optimization of skipping grid points that are already known to be in the intersection of previously analyzed circles. I think it's probably a worthwhile tradeoff in favour of readability.

Code Snippets

from collections import namedtuple

Circle = namedtuple('Circle', ['x', 'y', 'r'])
n = int(raw_input())
circles = []
for i in range(n):
    circles.append(Circle(*map(int, raw_input().split())))
mat = [[0] * 1005] * 1005
ans = 0 
for circle in circles:
    minx, maxx = circle.x - circle.r, circle.x + circle.r
    miny, maxy = circle.y - circle.r, circle.y + circle.r
    for x in range(minx, maxx+1):
        for y in range(miny, maxy+1):
            if mat[x][y] <= 1 and (x-circle.x)**2 + (y-circle.y)**2 <= circle.r**2:
                mat[x][y] += 1
                if mat[x][y] == 2:
                    ans += 1
print ans
class Circle (namedtuple('Circle', ['x', 'y', 'r'])):
    def contains(self, x, y):
        return (x - self.x)**2 + (y - self.y)**2 <= self.r**2

    def grid_points(self):
        for x in xrange(self.x - self.r, self.x + self.r + 1):
            for y in xrange(self.y - self.r, self.y + self.r + 1):
                if self.contains(x, y):
                    yield x, y

def read_ints():
    return map(int, raw_input().split())

n = int(raw_input())
circles = [Circle(*read_ints()) for _ in xrange(n)]

mat = [[0] * 1005] * 1005
ans = 0 
for circle in circles:
    for x, y in circle.grid_points():
        mat[x][y] += 1
        if mat[x][y] == 2:
            ans += 1
print ans

Context

StackExchange Code Review Q#73804, answer score: 6

Revisions (0)

No revisions yet.