Brendan Gillatt
Quadratic Resolver

What It Does & Why

Given the first three terms of a simple quadratic sequence, the script will resolve its three-term polynomial.

For example, the three terms 1, 63 & 50 resolve to the equation -83n² +176n -137. A complete explanation of the algorithm is included in the source code.

Usage

The script is launched from the command line without arguments. The first, second and third terms are entered into the corresponding text boxes; calculate is then pressed.

Get The Code

Requirements:

Download TXT source

#! /usr/bin/python
# -*- coding: latin-1 -*-

# Turns the first three terms of a quadratic sequence into a function using simple algebra
# and simultaneous equations.
# 
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Thanks to Mr.Adams, my year 9 maths teacher, for the idea!
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# I'm glad I kept my book notes!
#
#
#
#
# Author:	Brendan Gillatt
#
# License:	GNU GPL version 2
#
# Future:	Extend to different terms
#
# Revisions:
#		26th Oct 2007	Version 1.3	Converted to a TK program, added error catching, used floating math, made it display properly on PPC
#		26th Oct 2007	Version 1.2	Sorted out the printing properly
#		27th Jan 2007	Version 1.1	Added algorithm explanation and comments.
#		25th Nov 2005	Version 1.0	Original program
#
# Usage:
#		* Enter first term in first box, second term in second box and third term in third box
#		* Hit 'Run'
#
#		If any entry is invalid (blank, not a suitable number, etc), the output will notify you
#
# ::METHOD:: 
# 
# Take the first second and third terms, 8, 18 and 30, of an unknown quadratic formula.
# 
# The general format for a quadratic equation is An² + Bn + C = t
# where n is the position of the term and t is the term's value.
#
#
# If we use the first term (n = 1), 8, we get:
# An² + Bn + C = 8	=	A x 1² + B x 1 + C	=	 A +  B + C
# 
# Then we take the second term (n = 2), 18, we get:
# An² + Bn + C = 18	=	A x 2² + B x 2 + C	=	4A + 2B + C
# 
# Then we take the third term (n = 3), 30, we get:
# An² + Bn + C = 30	=	A x 3² + B x 3 + C	=	9A + 3B + C
# 
# We then use simultaneous equations to subtract term 2 (18) from term 3 (30):
# 9A + 3B + C = 30
# 4A + 2B + C = 18 -
# ----------------
# 5A +  B     = 12
#
# Then we subtract term 1 (8) from term 2 (18):
# 4A + 2B + C = 18
#  A +  B + C =  8 -
# ----------------
# 3A +  B     = 10
#
# Then we subtract the '3A + B = 10' from the '5A + B = 12':
# 5A +  B     = 12
# 3A +  B     = 10 -
# ----------------
# 2A	  =  2
#
# We now know that 2A is 2 so A must equal 1.
# 
# By substituting the A back into the '3A + B = 10' we get:
# 3A + B = 10	or	3 + B = 10
# 
# Therefore B = 7.
# 
# If we substitute the A and B into the first term's equation, A + B + C = 8 we get:
# 1 + 7 + C = 8		or	8 + C = 8
# 
# So C must equal 0
#    B  "     "   7
#    A  "     "   1
# 

from Tkinter import *
from platform import platform

def clean_print ( number, extension, operator = "+" ):	
	if number == -1:
		if extension == "":
			return str ( number )
		else:
			return "-" + extension
	elif number == 0:
		return ""
	elif number == 1:
		if extension == "":
			return operator + str ( number )
		else:
			return extension
	elif number > 0:
		return operator + str ( number ) + extension
	elif number < 0:
		return str ( number ) + extension

class QuadResolver:
	
	def __init__ ( self, master ):
	
		master.title ( "Quad Resolver" )
		master.bind ( "<Return>", self.run )
		master.bind ( "<Delete>", self.clear_entry )
		
		if platform ( 1, 1 ) == 'Windows-CE': # do stuff that makes sense on windows mobile
			master.overrideredirect ( 1 ) # remove title bar
			master.state ( "zoomed" ) # make full screen
			master.bind ( "<Down>", self.focusnext ) # make arrow keys (and nav buttons) change focus
			master.bind ( "<Up>", self.focusprev )		
		
		input_frame = Frame ( master )
		input_frame.pack ( padx = 2, pady = 2 )
		controls_frame = Frame ( master )
		controls_frame.pack ( padx = 2, pady = 2 )
		output_frame = Frame ( master )
		output_frame.pack ( padx = 2, pady = 2 )
		
		first_term_label = Label ( input_frame, text="n = 1:" );
		first_term_label.grid ( column = 0, row = 0 )
		second_term_label = Label ( input_frame, text="n = 2:" );
		second_term_label.grid ( column = 0, row = 1 )
		third_term_label = Label ( input_frame, text="n = 3:" );
		third_term_label.grid ( column = 0, row = 2 )
		
		self.first_term_entry = Entry ( input_frame, width = 25, highlightthickness = 1 )
		self.first_term_entry.grid ( column = 1, row = 0 )
		self.second_term_entry = Entry ( input_frame, width = 25, highlightthickness = 1 )
		self.second_term_entry.grid ( column = 1, row = 1 )
		self.third_term_entry = Entry ( input_frame, width = 25, highlightthickness = 1 )
		self.third_term_entry.grid ( column = 1, row = 2 )
		
		self.run_button = Button ( controls_frame, text="Calculate", command=self.run )
		self.run_button.pack ( side = LEFT, padx = 1 )
		
		self.quit_button = Button ( controls_frame, text="Exit", command=master.quit )
		self.quit_button.pack ( side = LEFT, padx = 1 )
		
		self.output = StringVar ( )
		
		self.output.set ( "0" )
		
		self.output_label = Label ( output_frame, textvariable = self.output )
		self.output_label.pack ( )
		
		Label (
			master,
			text = "Quadratic Resolver v1.3\nBrendan Gillatt\n\nEnter the 1st, 2nd and 3rd terms of a\nquadratic sequence and hit calculate.",
			width = 30
		).pack ( )
		
		self.first_term_entry.focus_force ( )
		
	def run ( self, event = 0 ):
		try:
			self.output.set (
				self.resolve (
					float ( self.first_term_entry.get ( ) ),
					float ( self.second_term_entry.get ( ) ),
					float ( self.third_term_entry.get ( ) )
				)
			)
		except ValueError:
			self.output.set ( "Invalid Entry" )
		
	
	def resolve ( self, first_term, second_term, third_term ):	
		eq4 = third_term - second_term	# 5A + B =
		eq5 = second_term - first_term	# 3A + B =
		eq6 = eq4 - eq5			# 2A     =
			
		A = eq6 / 2			# 2A / 2 = A
		B = eq5 - 3 * A			# substitute back into 3A + B 
		C = first_term - ( A + B )	# substitute back into A + B + C
			
		return clean_print ( A, u"n²", "" ) + " " + clean_print ( B, "n" ) + " " + clean_print ( C, "" )
	
	def clear_entry ( self, event = 0 ):
		self.first_term_entry.delete ( 0, END )
		self.second_term_entry.delete ( 0, END )
		self.third_term_entry.delete ( 0, END )
		
		self.output.set ( "0" )
		
		self.first_term_entry.focus_force ( )
	
	# fixed code at http://astropy.scipy.org/svn/pyraf/trunk/lib/epar.py
	def focusnext ( self, event ):
		widgetname = event.widget.tk.call ( 'tk_focusNext', event.widget._w )
		event.widget._nametowidget ( str ( widgetname ) ).focus_set ( )
	
	def focusprev ( self, event ):
		widgetname = event.widget.tk.call ( 'tk_focusPrev', event.widget._w )
		event.widget._nametowidget ( str ( widgetname ) ).focus_set ( )

root = Tk ( )

quadresolver = QuadResolver ( root )

root.mainloop()