0

I am trying to tweak the main file of my python program but it is giving be an "Unbound local Error: local variable 'sider' referenced before assignment". I am not sure how this is occurring since the variable "angle" is in the same location yet it works. Any help is appreciated!

from getdata import *
from trifun import *


def main():
    outfile = open("SFout.txt", "w")
    myList = getData()
    # print(myList)

    names = myList[0]
    vertices = myList[1]

    for i in range(len(names)):
        x1 = vertices[i][0][0]
        y1 = vertices[i][0][1]
        x2 = vertices[i][1][0]
        y2 = vertices[i][1][1]
        x3 = vertices[i][2][0]
        y3 = vertices[i][2][1]
        print((names[i]), (x1, y1), ",", (x2, y2), ",", (x3, y3))
        print((names[i]), (x1, y1), ",", (x2, y2), ",", (x3, y3), file = outfile)



        if duplicatePts(vertices[i]):
            print("You have duplicate points, not a triangle")
            outfile.write("You have duplicate points, not a triangle \n \n")
            print("\n")
            continue

        if collinear(vertices[i]):
            print("The points are collinear, not a triangle")
            outfile.write("\nThe points are collinear, not a triangle \n \n")
            print("\n")
            continue

        v = findAllSides(vertices[i])
        pm = str("%.1f" % (perimeter(vertices[i])))
        print("Perimeter: ", pm.ljust(25), end="")
        print("Perimeter: ", pm.ljust(25), end="", file = outfile)

        s = ("Sidelengths %0.2f, %0.2f, %0.2f" % (v[0], v[1], v[2]))
        sidelength1 = str("%.1f" % (v[0]))
        sidelength2 = str("%.1f" % (v[1]))
        sidelength3 = str("%.1f" % (v[2]))
        side = sidelength1 + "," + sidelength2 + "," + sidelength3
        print("Side lengths: ", side)
        print("Side lengths: ", side, file=outfile)
        #outfile.write("Side length:" + side + '\n')

        if acute(vertices[i]):
            angle = "Acute"
            # print("Acute")
            #           outfile.write("\nAcute")
        elif right(vertices[i]):
            angle = "Right"
        #            print("Right")
        #            outfile.write("\nRight")
        elif obtuse(vertices[i]):
            angle = "Obtuse"
        #            print("Obtuse")
        #            outfile.write("\nObtuse")
        if Scalene(vertices[i]):
            side = "Scalene"
        #            print("Scalene")
        #            outfile.write("\nScalene")
        elif Equilateral(vertices[i]):
            side = "Equilateral"
        #            print("Equilateral")
        #            outfile.write("\nEquilateral")
        elif Isosceles(vertices[i]):
            side = "Isosceles"
        #            print("Isosceles")
        #            outfile.write("\nIsosceles")
        # f.close()
        print((angle + " & " + side).ljust(37), end="")
        print((angle + " & " + side).ljust(37), end="", file=outfile)

        #outfile.write( angle + " & " + side+"\n")
        print("Area is: %0.2f" % area(vertices[i]))
        print("Area is: %0.2f" % area(vertices[i]), "\n", file=outfile)

        #outfile.write("Area is: %0.2f" % area(vertices[i])+"\n")
        print("\n")
    outfile.close()


main()

getData

def getData():
    names = []
    vertices = []
    myList = [names,vertices]
    with open("test.txt") as f:
        for line in f:
            x = line.split()
            names.append(x[0])
            x1 = float(x[1])
            y1 = float(x[2])
            x2 = float(x[3])
            y2 = float(x[4])
            x3 = float(x[5])
            y3 = float(x[6])

            vertices.append([[x1,y1],[x2,y2],[x3,y3]])

        return myList

Trifun

# The text file contains vertices of three points of a triangle, separated by a space.

# Import Math for calculations.
import math


# This function checks if there are any duplicate points in te vertices of the triangle.
# If there are, it s not a triangle.
def duplicatePts(vertices):
    #vertices looks like this : [[x1,y1],[x2,y2],[x3,y3]]
    x1 = vertices[0][0]
    y1 = vertices[0][1]
    x2 = vertices[1][0]
    y2 = vertices[1][1]
    x3 = vertices[2][0]
    y3 = vertices[2][1]

    if (x1,y1)==(x2,y2) or (x2, y2) == (x3, y3) or (x1, y1) == (x3, y3):
        return True
    else:
        return False


# This function checks if the points of the triangle are collinear.
# Triangle points cannot be in the same line. They have to be in different positions on the lane.
def collinear(vertices):


    x1 = vertices[0][0]
    y1 = vertices[0][1]
    x2 = vertices[1][0]
    y2 = vertices[1][1]
    x3 = vertices[2][0]
    y3 = vertices[2][1]

    if (x2 - x1) == 0: 
        # As discussed in class, set it to a high number, to assume it is vertical
        slope1 = 9999
    else:
        slope1 = (y2 - y1) / (x2 - x1)
    if (x3 - x2) == 0:
        # As discussed in class, set it to a high number, to assume it is vertical
        slope2 = 9999
    else:
        slope2 = (y3 - y2) / (x3 - x2)

    if slope1 == slope2:
        return True
    else:
        return False


# To find the perimeter, we need to find the sides first.
# Perimeter = Sum of all three sides
def perimeter(vertices):

    x1 = vertices[0][0]
    y1 = vertices[0][1]
    x2 = vertices[1][0]
    y2 = vertices[1][1]
    x3 = vertices[2][0]
    y3 = vertices[2][1]

    sideAB = sideLength(x1, y1, x2, y2)
    sideBC = sideLength(x2, y2, x3, y3)
    sideAC = sideLength(x3, y3, x1, y1)
    perimeter = sideAB + sideAC + sideBC
    return perimeter

# Finding the length of the side using the distance formula.
def sideLength(x1, y1, x2, y2):

    length = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
    return length


# Using the min function to find out the shortest side.
def findAllSides(vertices):

    x1 = vertices[0][0]
    y1 = vertices[0][1]
    x2 = vertices[1][0]
    y2 = vertices[1][1]
    x3 = vertices[2][0]
    y3 = vertices[2][1]

    sideAB = sideLength(x1, y1, x2, y2)
    sideBC = sideLength(x2, y2, x3, y3)
    sideAC = sideLength(x3, y3, x1, y1)
    lst=[sideAB, sideAC, sideBC]

    return lst




# We know how to find the sides now.

# We determine if the triangle is a right triangle by using Pythagoras theorem.
# Pythagoras theorem states that a triangle is a right triangle when
# Square of Hypotenus is equal to the sum of other two sides.
def typeObtuseRightAcute(vertices):
    #no idea if this is a good value but works for example
    #and should be low enough to give right answers for all but crazy close triangles
    epsilon=10**-8
    x1 = vertices[0][0]
    y1 = vertices[0][1]
    x2 = vertices[1][0]
    y2 = vertices[1][1]
    x3 = vertices[2][0]
    y3 = vertices[2][1]
    # Using Pythagoras theorem
    sideAB = sideLength(x1, y1, x2, y2)
    sideBC = sideLength(x2, y2, x3, y3)
    sideAC = sideLength(x3, y3, x1, y1)

    #use this instead
    [var1,var2,largest] = sorted([sideAB, sideBC, sideAC])



    if abs((largest) ** 2-((var1 ** 2 + (var2) ** 2)))<epsilon:
        return "right"
    elif (largest) ** 2 > ((var1 ** 2 + (var2) ** 2)):
        return "obtuse"
    else:
        return "acute"

def acute(vertices):
    return typeObtuseRightAcute(vertices)=="acute"

def right(vertices):
    return typeObtuseRightAcute(vertices)=="right"

def obtuse(vertices):
    return typeObtuseRightAcute(vertices)=="obtuse"

# A triangle is a scalene triangle, when all three sides are not equal to each other.
def Scalene(vertices):
    EPSILON = 0.000001
    x1 = vertices[0][0]
    y1 = vertices[0][1]
    x2 = vertices[1][0]
    y2 = vertices[1][1]
    x3 = vertices[2][0]
    y3 = vertices[2][1]

    sideAB = sideLength(x1, y1, x2, y2)
    sideBC = sideLength(x2, y2, x3, y3)
    sideAC = sideLength(x3, y3, x1, y1)
    if (abs(sideAB-sideBC)>=EPSILON and abs(sideBC-sideAC)>=EPSILON and abs(sideAB-sideAC)>=EPSILON):
        return True


# A triangle is an isosceles triangle when 2 of the sides are equal.
def Isosceles(vertices):
    EPSILON = 0.000001
    x1 = vertices[0][0]
    y1 = vertices[0][1]
    x2 = vertices[1][0]
    y2 = vertices[1][1]
    x3 = vertices[2][0]
    y3 = vertices[2][1]

    sideAB = sideLength(x1, y1, x2, y2)
    sideBC = sideLength(x2, y2, x3, y3)
    sideAC = sideLength(x3, y3, x1, y1)
    if (abs(sideAB-sideBC)<EPSILON or abs(sideBC-sideAC)<EPSILON or abs(sideAB-sideAC)<EPSILON) and not (abs(sideAB-sideBC)<EPSILON and abs(sideBC-sideAC)<EPSILON and abs(sideAB-sideAC)<EPSILON):
        return True  # or True
    else:
        return False


# A triangle is an equilateral triangle when all three sides are equal to each other.
def Equilateral(vertices):
    EPSILON = 0.000001
    x1 = vertices[0][0]
    y1 = vertices[0][1]
    x2 = vertices[1][0]
    y2 = vertices[1][1]
    x3 = vertices[2][0]
    y3 = vertices[2][1]

    sideAB = sideLength(x1, y1, x2, y2)
    sideBC = sideLength(x2, y2, x3, y3)
    sideAC = sideLength(x3, y3, x1, y1)

    if (abs(sideAB-sideBC)<EPSILON and abs(sideBC-sideAC)<EPSILON and abs(sideAB-sideAC)<EPSILON):
        return True
    else:
        return False

# To find the area, we need to find the semi perimeter first.
# We find the area of triangle using Heron's formula.
def area(vertices):

    x1 = vertices[0][0]
    y1 = vertices[0][1]
    x2 = vertices[1][0]
    y2 = vertices[1][1]
    x3 = vertices[2][0]
    y3 = vertices[2][1]

    sideAB = sideLength(x1, y1, x2, y2)
    sideBC = sideLength(x2, y2, x3, y3)
    sideAC = sideLength(x3, y3, x1, y1)
    semiPerimeter = (sideAB + sideBC + sideAC) / 2

    area = (semiPerimeter * (semiPerimeter - sideAB) * (semiPerimeter - sideBC) * (semiPerimeter - sideAC)) ** 0.5

    return area

Text file

Alpha -4 0 4 0 0 6.9282
Bravo -2.161 -3.366 2.161 3.366 -5.83 3.743
Charlie 3.54 5.46 -4.54 5.557 3.1 -2.1
Delta 0 4 0 2 0 2
Echo -4 3 1 3 6 3
Foxtrot 0 0 5 1 10 0
Golf 0 4 0 0 4 0
Jake Meyer
  • 43
  • 2
  • 9
  • Maybe there is some point where the conditional statement for `sider` is not executed while the conditional statement of `angle` is executed. You may try using the shorthand if, refer to this link: http://stackoverflow.com/questions/14029245/python-putting-an-if-elif-else-statement-on-one-line or another option is to declare an initialized local variable at the top something like `sider=''` before using it in other parts of the method – Chisskarzz Mar 19 '16 at 02:14
  • I dont think else would work here as we are calling three functions from another file. Is there a way to keep this format and still make sider work? – Jake Meyer Mar 19 '16 at 02:17
  • That's going to happen when none of three conditions to set it is true. – Klaus D. Mar 19 '16 at 02:19
  • Can you please make edits in my program? – Jake Meyer Mar 19 '16 at 02:20

2 Answers2

0

I'm not sure if this can make you satisfied but this can prevent from getting an Unbound Local Error:

sider = ("Scalene"
         if scalene(vertices[i])
         else ("Equilateral"
               if equilateral(vertices[i])
               else ("Isosceles"
                     if isosceles(vertices[i])
                     else "None of the above")
               )
         )

or if you want to maintain the format and just to be safe just make an initialization of the local variable sider:

def main():
    outfile = open("SFout.txt", "w")
    myList = getData()

    names = myList[0]
    vertices = myList[1]
    sider = '' # declare this one
    angle = '' # and this one

    for i in range(len(names)):
        x1 = vertices[i][0][0]
        y1 = vertices[i][0][1]
        x2 = vertices[i][1][0]
        y2 = vertices[i][1][1]
        x3 = vertices[i][2][0]
        y3 = vertices[i][2][1]
        print((names[i]), (x1, y1), ",", (x2, y2), ",", (x3, y3))
        print((names[i]), (x1, y1), ",", (x2, y2), ",", (x3, y3), file=outfile)

....
Chisskarzz
  • 171
  • 2
  • 16
  • The first one should be angle and not sider and I tried the second one and it gave me a ValueError – Jake Meyer Mar 19 '16 at 02:46
  • Already made some corrections. Does the first one successfully execute? In what line does the ValueError occur? Can you give the exact message of the ValueError? – Chisskarzz Mar 19 '16 at 02:56
  • No and still not. I have uploaded my entire program now and you can see how I am going about it. It has 3 files. One main file and 2 other python file. I am having problem with the triangles being determined as scalene equilateral and isosceles. There is a text file from which python program reads. – Jake Meyer Mar 19 '16 at 02:58
0

It would help to provide the traceback with your question. I presume the error is occurring at the print((angle ...) statement. All of the functions scalene(), equilateral(), or isosceles() must be returning False. To find the failing triangle, add an else block like this to print the vertices.

if scalene(vertices[i]):
    sider = "Scalene"

elif equilateral(vertices[i]):
    sider = "Equilateral"

elif isosceles(vertices[i]):
    sider = "Isosceles"

else:
    # this should never happen
    print("Something's wrong!")
    print(vertices[i])

EDIT Here's the problem: typeEquilateralIsoscelesScalene(vertices) returns "Equilateral", but in equilateral() you compare it to "equilateral". Same with scalene() and isosceles().

RootTwo
  • 4,288
  • 1
  • 11
  • 15
  • This did not work but I have uploaded my entire program now and you can see how I am going about it. It has 3 files. One main file and 2 other python file. I am having problem with the triangles being determined as scalene equilateral and isosceles. There is a text file from which python program reads. – Jake Meyer Mar 19 '16 at 03:00
  • What did it print? – RootTwo Mar 19 '16 at 03:03
  • UnboundLocalError: local variable 'sider' referenced before assignment – Jake Meyer Mar 19 '16 at 03:04
  • Your function is returning words with capital letters, but the individual function check lower case words. See edit above. – RootTwo Mar 19 '16 at 03:22
  • Did it run on your end? Mine still has an error File "/Users/admin/Desktop/Program 5/main.py", line 21, in main Bravo (-2.161, -3.366) , (2.161, 3.366) , (-5.83, 3.743) print((names[i]), (x1, y1), ",", (x2, y2), ",", (x3, y3), file=outfile) ValueError: I/O operation on closed file. – Jake Meyer Mar 19 '16 at 03:30
  • Because `outfile.close()` is inside the for loop. – RootTwo Mar 19 '16 at 03:34
  • STill not working. This is the error now Traceback (most recent call last): File "/Users/admin/Desktop/Trial/main.py", line 88, in main() File "/Users/admin/Desktop/Trial/main.py", line 75, in main vvf = str((angle, " & ", sider).ljust(37), end="") AttributeError: 'tuple' object has no attribute 'ljust' – Jake Meyer Mar 19 '16 at 03:43
  • I made some changes in my original program. It runs but it still does not give the correct values for scalene, isosceles and equilateral. Can you please check my logic there? – Jake Meyer Mar 19 '16 at 03:49