Tam211
Tam211

Reputation: 733

Why my list is not changing the way it's supposed to?

I'm trying to build a method in my class Circle which gets a matrix (represented by a list of lists, each sublist represents a row) as an input.

The matrix has zero in every cell, and I'm supposed to place my circle in the center of the matrix and check if the (i,j) cell which represents the (i,j) point is contained in the circle, but for some reason I get a different output.

Here is an example:

mat = [[0 for j in range(5)] for i in range(7)] 
Circle(40, 10, 1).draw(mat) 

The output I expect is:

[[0, 0, 0, 0, 0], 
 [0, 0, 0, 0, 0], 
 [0, 0, 1, 0, 0], 
 [0, 1, 1, 1, 0], 
 [0, 0, 1, 0, 0], 
 [0, 0, 0, 0, 0], 
 [0, 0, 0, 0, 0]]

But the output I get is:

[[0, 0, 0, 0, 0], 
 [0, 0, 0, 0, 0], 
 [0, 0, 0, 0, 1], 
 [0, 0, 0, 1, 1], 
 [0, 0, 0, 0, 1], 
 [0, 0, 0, 0, 0], 
 [0, 0, 0, 0, 0]]

Here's my code:

class Point():
    """ Holds data on a point (x,y) in the plane """

    def __init__(self, x=0, y=0):
        assert isinstance(x,(int, float)) and isinstance(y,(int, float)) 
        self.x = x
        self.y = y

class Circle():
    """ Holds data on a circle in the plane """

    def __init__(self,*args):
        if len(args)==2:
            if isinstance(args[0],Point) and isinstance(args[1],(float,int)):
                assert args[1]>0
                self.center= args[0]
                self.radius= args[1]

        if len(args)==3:
            assert args[2]>0
            self.a=args[0]
            self.b=args[1]
            self.center= Point(self.a,self.b)
            self.radius= args[2]
    def contains(self,check): 

        if isinstance(check,(Point)):
            if math.sqrt((self.center.x-check.x)**2 + (self.center.y-check.y)**2) <= self.radius:
                return True
        if isinstance(check,Circle): 
            test= math.sqrt((self.center.x-check.center.x)**2 + (self.center.x-check.center.x)**2)
            if test < (abs((self.radius)-(check.radius))):
                return True

        else:
            return False

    def draw(self,mat):
        n=len(mat)
        m=len(mat[0])

        newcircle=Circle((int(m/2)+1),(int(n/2)+1),self.radius)
        for i,lst in enumerate(mat):
            for j,val in enumerate(lst):
                if  newcircle.contains(Point(i,j)):


                    mat[i][j]=1

Upvotes: 1

Views: 70

Answers (2)

Taha
Taha

Reputation: 778

To draw a circle, you create a new circle in the center of the matrix, you check the cells that are inside and then you turn the value to 1 for those inside.

1) First, there is a problem with the function contains :

def contains(...):
    if (cond1):
        if (cond11)
            return True
    if (cond2):
        if (cond21)
            return True
    else:
        return False

If cond2 is true and cond21 is false, you will get a None. To be more Pythonic, try:

def contains(...):
    if (cond1) and (cond11):
        return True
    elif (cond2) and (cond21):
        return True
    else:
        return False

You are sure in this case to have a True or a False.

2) Copy / Paste mistake

There is a copy / paste mistake in the function contains when instance is Circle. You have forgotten to turn y into x.

3) Function draw

All you need for this function is the radius. Be careful with the use of integers and floats; we have:

(int(5 / 2)) == (5 / 2) != (5 / 2.)

To be sure to have a float, write the divisor as a float 2. instead of 2

Your circle is created on a matrix which rows and columns indices start with 1 if you define the center using int(len(mat) / 2.) + 1. Don't forget that enumerate indices starts at 0, not 1. So, int((len(mat) - 1) / 2.) + 1 (which is the same as len(mat) / 2) would be more accurate.

Seriously, Taha!

Upvotes: 0

M4rtini
M4rtini

Reputation: 13539

You're not placing your circle in the middle of the matrix.

newcircle=Circle((int(m/2)+1),(int(n/2)+1),self.radius)

should be

newcircle=Circle((int(n/2)),(int(m/2)),self.radius)

or possibly, since there is no need to use just integers here.

newcircle=Circle((n-1)/2.0,(m-1)/2.0,self.radius)

Upvotes: 1

Related Questions