Hi all, this is my first post.

A couple days ago, in preparation for a math final, I attempted to code a program which would allow me to solve triangles (law of cosines, sines, etc.). Now that the test is over, I am now interested in getting it working.

#This is TRIANGLE SOLVER!!!
#solves triangles, in SSS, ASA, SSA, AAS, SAS
#Written by Jared Miller, 2013, AAST, June 1 2010

import math

#functions

def askyesno():
	if input("\nAgain?")==("y" or "Y" or "yes" or "Yes" or "YES"):
		return True
	else:
		return False
#math constants

PI=math.pi

#math functions

sq=lambda x: math.sqrt(x)
p2=lambda x: x**2

#trig functions

sin=lambda x: math.sin(rad(x))
cos=lambda x: math.cos(rad(x))

#trig inverses

asin=lambda x: deg(math.asin(x))
acos=lambda x: deg(math.acos(x))

#trig measurements

deg=lambda x: math.degrees(x)
rad=lambda x: math.radians(x)

#laws of cosines and sines

#law of cosines, for angle and side

def lawcosside(a,b,C):
	"""Law of cosines, solving side C"""
	return sq(p2(a)+p2(b)-2*a*b*cos(C))

def lawcosangle(a,b,c):
	"""Law of cosines, solving for angle C"""
	return acos((p2(a)+p2(b)-p2(c))/(2*a*b))

#law of sines, for missing angle and side:

def lawsinside(A,a,B):
	"""Law of sines, solving for side b"""
	return (a*sin(B))/sin(A)

def lawsinangle(a,A,b):
	"""Law of sines, solving for angle B"""
	return asin((b*sin(A))/a)

#Solving triangles

#Single solution, regular cases

def SSS(a,b,c):
	"""Finds angles A, B, C"""
	A=lawcosangle(b,c,a)
	B=lawcosangle(c,a,b)
	C=180-A-B
	assert  not A+B+C>182
	return {"sides":(a,b,c),"angles":(A,B,C)}

def ASA(A,c,B):
	"""Finds sides a, b; and angle C"""
	C=180-A-B
	a=lawsinside(C,c,A)
	b=lawsinside(C,c,B)

	assert  not A+B+C>182
	return {"sides":(a,b,c),"angles":(A,B,C)}

def SAS(a,B,c):
	"""Finds side b and angles A and C"""
	b=lawcosside(a,c,B)
	A=lawsinangle(b,B,a)
	C=180-A-B
	assert  not A+B+C>182
	return {"sides":(a,b,c),"angles":(A,B,C)}

def AAS(A,B,a):
	"""Finds sides b, c; and angle C"""
	b=lawsinside(A,a,B)
	C=180-A-B
	c=lawsinside(A,a,C)
	assert not  A+B+C>182
	return {"sides":(a,b,c),"angles":(A,B,C)}

#Holy...multiple possible triangles

def SSA(c,a,A):
	"""Returns 0,1,or 2 triangles, depending upon the case"""

	#height declaration
	A=rad(A)
	h=c*sin(A)

	#case 1:
	#h>a
	#0 triangles

	if h>a:
		return []

	#case 2:
	#h=a
	#1 triangle

	elif h==a:
		C=90
		B=180-A-C
		b=lawsinside(A,a,B)
		assert not A+B+C>182
		return [{"sides":(a,b,c),"angles":(A,B,C)}]

	#case 3:
	#h<a<c
	#2 triangles

	elif h<a and a<c:
		C1a=lawsinangle(a,A,c)
		C2a=180-C1a
		if C1a>C2a:
			C1,C2=C1a,C2a
		else:
			C1,C2=C2a,C1a
		B1=180-A-C1
		B2=180-A-C2

		assert  not A1+B1+C1>182
		assert  not A2+B2+C2>182

		b1=lawsinside(A,a,B1)
		b2=lawsinside(A,a,B2)

		return [{"sides triangle 1":(a,b1,c),"angles traingle 1":(A,B1,C1)}, {"sides triangle 2":(a,b2,c),"angles triangle 2":(A,B2,C2)}]


	#case 4:
	#a>=c
	#1 triangle

	else:
		C=lawsinangle(a,A,c)
		B=180-A-C
		b=lawsinside(A,a,B)
		assert not A+B+C>182
		return [{"sides":(a,b,c),"angles":(A,B,C)}]


#main program
def main():
	"""Start the program"""
	again=True
	print("""Welcome to the Triangle Solver!

Here, you will be able to solve a triangle in SSS, ASA, SSA, AAS, SAS forms.

Type in a form, and press enter to begin.
""")
	while again:
		type=input("Form:\t")

		#SSS

		if type=="SSS":
			print("\nYou picked SSS. Type in each number, seperated by a space\n")
			nums=input("Numbers:\t").split()
			nums=[float(eval(i)) for i in nums]
			resultdict=SSS(nums[0],nums[1],nums[2])
			resultdict["angles"]=[deg(ang) for ang in resultdict["angles"]]
			print("\nsides:\t ", resultdict["sides"], " \nangles:\t ", resultdict["angles"])
		#ASA

		elif type=="ASA":
			print("\nYou picked ASA. Type in each number, seperated by a space\n")
			nums=input("Numbers:\t").split()
			nums=[float(eval(i)) for i in nums]
			resultdict=ASA(nums[0],nums[1],nums[2])
			resultdict["angles"]=[deg(ang) for ang in resultdict["angles"]]
			print("\nsides:\t ", resultdict["sides"], " \nangles:\t ", resultdict["angles"])

		#SSA

		elif type=="SSA":
			print("\nYou picked SSA. Type in each number, seperated by a space\n")
			nums=input("Numbers:\t").split()
			nums=[float(eval(i)) for i in nums]
			resultlist=SSA(nums[0],nums[1],nums[2])

			if len(resultlist)==0:
				print("\nThere are no triangles that fit these specifications")
			elif len(resultlist)==1:
				resultdict=resultlist[0]
				resultdict["angles"]=[deg(ang) for ang in resultdict["angles"]]
				print("\nsides:\t ", resultdict["sides"], " \nangles:\t ", resultdict["angles"])
			else:
				resultdict1=resultlist[0]
				resultdict1["angles"]=[deg(ang) for ang in resultdict1["angles"]]
				resultdict2=resultlist[1]
				resultdict2["angles"]=[deg(ang) for ang in resultdict2["angles"]]
				print("\nsides:\t ", resultdict1["sides"], " \nangles:\t ", resultdict1["angles"])
				print("sides:\t ", resultdict2["sides"], " \nangles:\t ", resultdict2["angles"])
		#AAS

		elif type=="AAS":
			print("\nYou picked AAS. Type in each number, seperated by a space\n")
			nums=input("Numbers:\t").split()
			nums=[float(eval(i)) for i in nums]
			resultdict=AAS(nums[0],nums[1],nums[2])
			resultdict["angles"]=[deg(ang) for ang in resultdict["angles"]]
			print("\nsides:\t ", resultdict["sides"], " \nangles:\t ", resultdict["angles"])

		#SAS

		elif type=="SAS":
			print("\nYou picked SAS. Type in each number, seperated by a space\n")
			nums=input("Numbers:\t").split()
			nums=[float(eval(i)) for i in nums]
			resultdict=SAS(nums[0],nums[1],nums[2])
			resultdict["angles"]=[deg(ang) for ang in resultdict["angles"]]
			print("\nsides:\t ", resultdict["sides"], " \nangles:\t ", resultdict["angles"])

		#Catch-all for bugs

		else:
			print("I could not recognize this request.\n")

		again=askyesno()

#start of program
main()

When run, the angle measurements return outrageous values in the high 2-4 thousands, and the assert statements are failing. I'm pretty sure there is a more efficient method for parsing and synthesizing the input, but the method I have now works.

Thanks in advance,

Jared

Recommended Answers

All 4 Replies

The problem is that you convert twice the angles to degrees. For example the part if type == "SSS" should look like

if type=="SSS":
			print("\nYou picked SSS. Type in each number, seperated by a space\n")
			nums=input("Numbers:\t").split()
			nums=[float(eval(i)) for i in nums]
			resultdict=SSS(nums[0],nums[1],nums[2])
			# LINE SUPPRESSED
			print("\nsides:\t ", resultdict["sides"], " \nangles:\t ", resultdict["angles"])

Another problem is that you are indenting your code with tab characters instead of spaces. It's a bad habit in python, so PLEASE, configure your editor to insert 4 spaces instead of a tab when you hit the tab key.

Thanks so much!

I fixed the command line bug, and it works perfectly. I've tried upgrading the program to tkinter, and it seems to be riddled with bugs.

#triangle solver GUI

from tkinter import *
from math import *

#law of cosines, for angle and side

def lawcosside(a,b,C):
    """Law of cosines, solving side C"""
    return (a**2+b**2-2*a*b*cos(C))**.5

def lawcosangle(a,b,c):
    """Law of cosines, solving for angle C"""
    return acos((a**2+b**2-c**2)/(2*a*b))

#law of sines, for missing angle and side:

def lawsinside(A,a,B):
    """Law of sines, solving for side b"""
    return (a*sin(B))/sin(A)

def lawsinangle(a,A,b):
    """Law of sines, solving for angle B"""
    return asin((b*sin(A))/a)

#class for GUI
class Application(Frame):
    """GUI Application for solving triangles"""
    def __init__(self,master):
        """Creates Frame as master, forces grid, and holds everything together"""
        super(Application, self).__init__(master)
        self.grid()
        self.create_widgets()

    def create_widgets(self):
        """Creates widgets"""
        Label(self,
              text="Choose type of triangle"
              ).grid(row=0, column=0, columnspan=6)

        #Radio buttons SSS, SAS, ASA, AAS, SSA

        self.tri_form=StringVar()
        self.tri_form.set(None)

        counter=0
        tri_list=["SSS","SAS","ASA","AAS","SSA"]
        
        for a in tri_list:
            Radiobutton(self,
                        text=a,
                        variable=self.tri_form,
                        value=a,
                        command=self.change_labels
                        ).grid(row=1, column=counter, columnspan=1)
            counter+=1

        #Entry Inputs

        Label(self,
              text="Insert inputs:"
              ).grid(row=2, column=0, columnspan=6)

        self.input_1_lbl=Label(self,
                      text="Side A"
                      ).grid(row=3, column=0, columnspan=1)

        self.input_1_entry=Entry(self)
        self.input_1_entry.grid(row=3, column=1, columnspan=1)

        self.input_2_lbl=Label(self,
                      text="Side B"
                      ).grid(row=3, column=2, columnspan=1)

        self.input_2_entry=Entry(self)
        self.input_2_entry.grid(row=3, column=3, columnspan=1)

        self.input_3_lbl=Label(self,
                      text="Side C"
                      ).grid(row=3, column=4, columnspan=1)

        self.input_3_entry=Entry(self)
        self.input_3_entry.grid(row=3, column=5, columnspan=1)

        #Angle type radio buttons

        self.ang_type=StringVar()
        self.ang_type.set(None)

        Radiobutton(self,
                    text="Radians",
                    variable=self.ang_type,
                    value="Radians",
                    command=self.calculate_output
                    ).grid(row=4, column=0, columnspan=3)

        Radiobutton(self,
                    text="Degrees",
                    variable=self.ang_type,
                    value="Degrees",
                    command=self.calculate_output
                    ).grid(row=4, column=3, columnspan=3)

        #Triangle 1:

        self.output_1_tri_1_lbl=Label(self,
                                      text="Angle A"
                                      ).grid(row=5, column=0, columnspan=1)

        self.output1_tri_1_entry=Entry(self)
        self.output1_tri_1_entry.grid(row=5, column=1, columnspan=1)

        self.output2_tri_1_lbl=Label(self,
                                     text="Angle B"
                                     ).grid(row=5, column=2, columnspan=1)
        
        self.output2_tri_1_entry=Entry(self)
        self.output2_tri_1_entry.grid(row=5, column=3, columnspan=1)

        self.output3_tri_1_lbl=Label(self,
                                     text="Angle C"
                                     ).grid(row=5, column=4, columnspan=1)

        self.output3_tri_1_entry=Entry(self)
        self.output3_tri_1_entry.grid(row=5, column=5, columnspan=1)

        #Triangle 2:

        self.output_1_tri_2_lbl=Label(self,
                                      text="Nonexistent"
                                      ).grid(row=6, column=0, columnspan=1)

        self.output1_tri_2_entry=Entry(self)
        self.output1_tri_2_entry.grid(row=6, column=1, columnspan=1)

        self.output2_tri_2_lbl=Label(self,
                                     text="Nonexistent"
                                     ).grid(row=6, column=2, columnspan=1)
        
        self.output2_tri_2_entry=Entry(self)
        self.output2_tri_2_entry.grid(row=6, column=3, columnspan=1)

        self.output3_tri_2_lbl=Label(self,
                                     text="Nonexistent"
                                     ).grid(row=6, column=4, columnspan=1)

        self.output3_tri_2_entry=Entry(self)
        self.output3_tri_2_entry.grid(row=6, column=5, columnspan=1)

    """
Key for later

Variables

self.tri_form: form of triangle
self.ang_type: angles in radians or degrees

Input:

self.input_x_lbl x is from 1-3: label for input
self.input_x_entry x if from 1-3: entry for input

Output:

self.outputx_tri_y_lbl x is from 1-3, outputs, y is from 1-2, triangles: label
self.outputx_tri_y_entry x is from 1-3, outputs, y is from 1-2, triangles: entry

"""
    def change_labels(self):
        """Changes labels of input and output boxes"""
        form=self.tri_form.get()

        if form=="SSS":
            inputlist=["Side a", "Side b", "Side c"]
            outputlist=["Angle A", "Angle B", "Angle C"]

        elif form=="SAS":
            inputlist=["Side a", "Angle B", "Side c"]
            outputlist=["Angle A", "Side b", "Angle C"]

        elif form=="AAS":
            inputlist=["Angle A", "Angle B", "Side a"]
            outputlist=["Side c", "Side b", "Angle C"]

        elif form=="ASA":
            inputlist=["Angle A", "Side c", "Angle B"]
            outputlist=["Side a", "Angle C", "Side b"]

        elif form=="SSA":
            inputlist=["Side c", "Side a", "Angle A"]
            outputlist=["Angle C", "Angle B", "Side b"]

        
        self.input_1_lbl.config(text=inputlist[0])
        self.input_2_lbl.config(text=inputlist[1])
        self.input_3_lbl.config(text=inputlist[2])        
        self.output_1_tri_1_lbl.config(text=outputlist[0])
        self.output_2_tri_1_lbl.config(text=outputlist[1])
        self.output_3_tri_1_lbl.config(text=outputlist[2])
        self.output_1_tri_2_lbl.config(text="Nonexistent")
        self.output_2_tri_2_lbl.config(text="Nonexistent")
        self.output_3_tri_2_lbl.config(text="Nonexistent")

        counter=1
        while counter<=3:
            eval("self.input_{0}_entry".format(repr(counter))).delete(0.0, END)
            eval("self.output"+repr(counter)+"_tri_1_entry" ).delete(0.0, END)
            eval("self.output"+repr(counter)+"_tri_2_entry").delete(0.0, END)
            counter+=1

        counter=1
        if form=="SSA":
            while counter<=3:
                eval("self.output"+repr(counter)+"_tri_2_lbl").config(text=eval("self.output"+repr(counter)+"_tri_1_lbl")['text'])
                counter+=1
            
    def calculate_output(self):
        """Calculates output, using mathematical formulae"""
        form=self.tri_form.get()
        ang_type=self.ang_type.get()

        input_1=float(self.input_1_entry.get())
        input_2=float(self.input_2_entry.get())
        input_3=float(self.input_3_entry.get())
        
        if form=="SSS":
            a,b,c=input_1, input_2, input_3
            A,B=lawcosangle(b,c,a),lawcosangle(c,a,b)
            C=pi-A-B
            if ang_type=="Degrees":
                A,B,C=degrees(A),degrees(B),degrees(C)
            output_1,output_2,output_3=A,B,C
            output_1a,output_2a,output_3a=None,None,None
            
        elif form=="SAS":
            a,B,c=input_1,input_2,input_3
            if ang_type=="Degrees":
                B=radians(B)
            b,A=lawcosside(a,c,B),lawsinside(b,B,a)
            C=pi-A-B
            if ang_type=="Degrees":
                A,B,C=degrees(A),degrees(B),degrees(C)
            output_1,output_2,output_3=A,b,C
            output_1a,output_2a,output_3a=None,None,None
            
        elif form=="AAS":
            A,B,a=input_1,input_2,input_3
            if ang_type=="Degrees":
                A,B=radians(A),radians(B)
            b,c=lawsinside(A,a,B),lawsinside(A,a,C)
            C=pi-A-B
            if ang_type=="Degrees":
                A,B,C=degrees(A),degrees(B),degrees(C)
            output_1,output_2,output_3=c, b, C
            output_1a,output_2a,output_3a=None,None,None
            
        elif form=="ASA":
            A,c,B=input_1,input_2, input_3
            if ang_type=="Degrees":
                A,B=radians(A),(B)
            a,b,C=lawsinside(C,c,A),lawsinside(C,c,B),(pi-A-B)
            if ang_type=="Degrees":
                A,B,C=degrees(A),degrees(B),degrees(C)
            output_1,output_2,output_3=a,C,b
            output_1a,output_2a,output_3a=None,None,None

        elif form=="SSA":
            c,a,A=input_1,input_2,input_3
            if ang_type=="Degrees":
                A=radians(A)
            h=c*sin(A)
            
            #case 1
            #h>a
            #0 triangles
            if h<a:
                output_1,output_2,output_3=None,None,None
                output_1a,output_2a,output_3a=None,None,None
            
            #case 2
            #h=a
            #1 triangle
            elif h==a:
                C=pi
                B=pi-A-C
                b=lawsinside(A,a,B)
                if ang_type=="Degrees":
                    C,B=degrees(C),degrees(B)
                output_1,output_2,output_3=C,B,b
                output_1a,output_2a,output_3a=None,None,None
            
            #case 3
            #h<a<c
            #2 triangles
            elif h<a and a<c:
                C1a=lawsinangle(a,A,c)
                C2a=pi-C1a
                if C1a>C2a:
                    C1,C2=C1a,C2a
                else:
                    C1,C2=C2a,C1a
                B1=pi-A-C1
                B2=pi-A-C2
                b1=lawsinside(A,a,B1)
                b2=lawsinside(A,a,B2)
                if ang_type=="Degrees":
                    B1,B2,C1,C2=degrees(B1),degrees(B2),degrees(C1),degrees(C2)
                output_1,output_2,output_3=C1,B1,b1
                output_1a,output_2a,output_3a=C2,B2,b2
            
            #case 4
            #a>=c
            #1 triangle
            elif a>=c:
                C=lawsinangle(a,A,c)
                B=pi-A-C
                b=lawsinside(A,a,B)
                if ang_type=="Degrees":
                    C,B=degrees(C),degrees(B)
                output_1,output_2,output_3=C,B,b
                output_1a,output_2a,output_3a=None,None,None    
            
        self.output_1,self.output_2,self.output_3,self.output_1a,self.output_2a,self.output_3a=output_1,output_2,output_3,output_1a,output_2a,output_3a
        self.display_output()

    def display_output(self):
        """Displays output, based on calculations from calculate_output"""

        for a in [self.output_1,self.output_2,self.output_3,self.output_1a,self.output_2a,self.output_3a]:
            if a==None:
                a="Nonexistent"
        self.output1_tri1_entry.insert(0.0,self.output_1)
        self.output2_tri1_entry.insert(0.0,self.output_2)
        self.output3_tri1_entry.insert(0.0,self.output_3)
        self.output1_tri2_entry.insert(0.0,self.output_1a)
        self.output2_tri2_entry.insert(0.0,self.output_2a)
        self.output3_tri2_entry.insert(0.0,self.output_3a)

#Starts Gui
    
root=Tk()       
root.title=("Triangle solver 2.0")
app=Application(root)
root.mainloop()

At least you should store label before doing .grid:

self.input_1_lbl=Label(self,
                      text="Side A"
                      ).grid(row=3, column=0, columnspan=1)
        print('Created', self.input_1_lbl)

Output

Created None
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.