Stacks and Trees Subclasses and Inheritance
Total Page:16
File Type:pdf, Size:1020Kb
Stacks and Trees Subclasses and Inheritance Op5onal assignment 10 stacks, pos<ix, recursive traversal • CIS 210 Idutorob: The Incredible Duck Tournament of Robots (Actually Sudoku, but Sudoku is kind of like duck-sled racing. ) REMINDER: TOURNAMENT ENTRIES DUE TODAY AT 5 Photo credits: hAp://www.city-data.com/forum/alaska/1522185- robot-ken-robodog-go-dog-sledding.html, hp://steamcommunity.com/groups/rdzgroup • CIS 210 Op5onal assignment Simple pos<ix calculator ... with a twist $ python3 symcalc.py - 3 5 + 7 * 4 5 * Stack: ((3+5)*7); (4*5); # Stack: ((3+5)*7); 20; + Stack: (((3+5)*7)+20); # Stack: 76; quit Thank you for your paence. Sorry for any bugs. • CIS 210 Pos<ix Our customary notaon is infix: (3 + 5) * 7 (operators + and * between operands) Pos(ix places operators aer operands: 3 5 + 7 * Prefix places operators before operands * + 3 5 7 Pos<ix and prefix don’t require parentheses or operator precedence. Evaluate pos<ix on a stack. • CIS 210 Stack A stack is a sequence that supports inser5on and dele5on at one end push(x) adds to top pop( ) takes element from top [ ] Python lists can be stacks: stack.append(x) is push(x) stack.pop() is pop() • CIS 210 Stack A stack is a sequence that supports inser5on and dele5on at one end 5.3 s = [ ] s.append(5.3) • CIS 210 Stack A stack is a sequence that supports inser5on and dele5on at one end top 3.7 5.3 s = [ ] s.append(5.3) s.append(3.7) • CIS 210 Stack A stack is a sequence that supports inser5on and dele5on at one end top 4.0 3.7 5.3 s = [ ] s.append(5.3) s.append(3.7) s.append(4.0) • CIS 210 Stack A stack is a sequence that supports inser5on and dele5on at one end top 3.7 5.3 x = s.pop( ) x: 4.0 • CIS 210 Calculang with a Stack to calculate 5.3 * ( 3.7 + 4.0) rearrange as pos<ix: 5.3 3.7 4.0 + * • CIS 210 Stack for Calculaon 5.3 * ( 3.7 + 4.0) (posix) 5.3 3.7 4.0 + * (pop,pop, (pop,pop, (push) (push) (push) add, push) multiply, push) 4.0 3.7 3.7 7.7 5.3 5.3 5.3 5.3 40.81 • CIS 210 Expression represented as tree * (internal)form) + 5.3 3.7 4.0 3 5 + 7 x + * (pos%ix;)calculator)input) ((3 + 5) *( 7 + x)) (infix;'printed'form) • CIS 210 From stack to tree ... 5.3 3.7 4.0 + * stack = [ ] stack.append(5.3) stack.append(3.7) stack.append(4.0) 4.0 3.7 5.3 • CIS 210 From stack to tree ... 5.3 3.7 4.0 + * stack = [ ] stack.append(ConstExpr(5.3)) stack.append(ConstExpr(3.7)) stack.append(ConstExpr(4.0)) 4.0 We’ll actually use objects 3.7 to hold these values. ConstExpr is for “constant 5.3 expression” • CIS 210 From stack to tree ... 5.3 3.7 4.0 + * right = stack.pop(); le` = stack.pop(); stack.append(AddOpExpr(‘+’, le`, right)); The AddOpExpr object represents 4.0 addion + 3.7 5.3 • CIS 210 Recursive defini5on of an expression: An expression can be a constant like 3.7. An expression can be an operaon applied to a le` operand and a right operand. (base case) (recursive case) ConstExpr AddOpExpr 3.7 + • CIS 210 Recursive defini5on of a (binary) tree: A tree can be a single leaf node. (our leaves are constants and variables) A tree can be an interior node with two children, each of which is a tree. (our interior nodes are expressions represenFng addiFon, mulFplicaFon, etc) • CIS 210 Recursive evaluaon To evaluate an expression: If it’s a leaf, just return the value If it has le` and right operands, evaluate the le` operand evaluate the right operand if le` and right are both numbers apply the operaon to get a number otherwise construct internal node( op, le`, right ) • CIS 210 recursion in evaluaon * + 5.3 evaluate ➞ 3.7 evaluate ➞ 4.0 3.7 4.0 • CIS 210 When le` and right children are numbers, we apply an operaon * Apply ‘+’ to 3.7 and 4.0 + 5.3 3.7 4.0 • CIS 210 recursion in evaluaon * evaluate ➞ 7.7 + 5.3 evaluate ➞ 3.7 evaluate ➞ 4.0 3.7 4.0 • CIS 210 recursion in evaluaon * evaluate ➞ 7.7 evaluate ➞ 5.3 + 5.3 evaluate ➞ 3.7 evaluate ➞ 4.0 3.7 4.0 • CIS 210 recursion in evaluaon evaluate ➞ 40.81 * evaluate ➞ 7.7 evaluate ➞ 5.3 + 5.3 evaluate ➞ 3.7 evaluate ➞ 4.0 3.7 4.0 • CIS 210 Expressions can contain variables 3 5 + 7 x + * Stack: ((3+5)*(7+x)); # Stack: (8*(7+x)); * evaluate ➞ 8 evaluates to itself + + 3 5 7 x • CIS 210 About that expression tree ... We’ll need objects to represent numbers (constants) ... call them ConstExpr. They store a value. If we evaluate them, they just return themselves. class ConstExpr(): which we might draw as ... ConstExpr def eval(self): val : number eval(): ConstExpr (This notaon is called UML) ... We’ll need objects to represent internal nodes ... call them AddOpExpr for addi5on, MulOpExpr for mul5plicaon, SubOpExpr for subtrac5on, etc. They have two children. If we evaluate them, they evaluate their children, and then possibly apply their operaon. class AddOpExpr(): class MulOpExpr(): ... ... def eval(self): def eval(self): ... ... ... • CIS 210 UML class diagram notaon ClassName A convenient way to draw and field_a: type describe classes and their field_b: type relaonships. OHen used to method_name(arg1, arg2): result_type document class structures in Java, another_method(arg): result_type C++, Python, and other languages with classes and objects. describes class ClassName(): def __init__(field_a, field_b): self.field_a = field_a self.field_b = field_b def method_name(self, arg1, arg2): ... def another_method(self, arg): ... • CIS 210 So many classes ... do I have to repeat everything? AddOpExpr MulOpExpr SubOpExpr DivOpExpr token: str token: str token: str token: str left: Expr left: Expr left: Expr left: Expr right: Expr right: Expr right: Expr right: Expr eval(): Expr eval(): Expr eval(): Expr eval(): Expr __str__(): str __str__(): str __str__(): str __str__(): str I could build one “superclass” that contains much of what they have in common ... BinOpExpr token: str if I could just reuse that in each of the specific classes left: Expr right: Expr eval(): Expr (and I can) __str__(): str • CIS 210 Inheritance class BinOpExpr(): Factor the common aMributes into BinOpExpr ... Make the specific operaFons subclasses that inherit the common parts. class MulOpExpr(BinOpExpr): ... BinOpExpr A SubOpExpr object will have token: str the fields and methods of the left: Expr right: Expr superclass BinOpExpr, as well eval(): Expr as the new method apply_op __str__(): str MulOpExpr AddOpExpr SubOpExpr apply_op(left, right): Expr apply_op(left, right): Expr apply_op(left, right): Expr • CIS 210 The node classes form a hierarchy Expr __str__: str eval(): Expr BinOpExpr token: str ConstExpr left: Expr VarExpr val : number right: Expr val : str eval(): ConstExpr eval(): Expr eval(): VarExpr __str__(): str MulOpExpr AddOpExpr SubOpExpr DivOpExpr apply_op(left, right): Expr apply_op(left, right): Expr apply_op(left, right): Expr apply_op(left, right): Expr (don’t confuse this with the tree represenFng an arithmeFc expression) • CIS 210 Overriding an abstract method Expr class Expr(object): __str__: str def eval(self): eval(): Expr “””This method must be overridden””” raise NotImplementedError(" ... ") class ConstExpr(Expr): ConstExpr val : number def eval(self): eval(): ConstExpr """The evaluated version of a constant is itself""" return self Each subclass of Expr (VarExpr, ConstExpr, and BinOpExpr) provides its own definion of “eval”. “eval” is an abstract method in Expr, and Expr is an abstract class. We never create Expr objects, only ConstExpr, VarExpr, AddOpExpr, etc. • CIS 210 Base case and progress case As always, we have base case and progress case for recursion, but they are now in different places Base case is in evaluaon of leaves (ConstExpr, VarExpr) (and we know we will eventually reach them) Progress (recursive) case in in evaluaon of internal nodes Trees are some5mes called “recursive data structures” • CIS 210 A twist on recursion Expr __str__: str eval(): Expr BinOpExpr token: str ConstExpr left: Expr val : number right: Expr eval(): ConstExpr eval(): Expr __str__(): str This eval() method This eval() method defines a recursive defines a base case (progress) case All the same parts as a recursive func5on, but it’s not all in the same place. The check for a base case is now in calling the right eval method, which depends on the class of the object • CIS 210 What you need to do I will provide most of eval; you will add __str__ with similar recursive structure I will provide most node classes; you will add MulOpExpr and SubOpExpr following the same paern (just to make you read the code) • CIS 210 Op5onal Assignment If you do it, score replaces worst project score (pro-rated by possible score) You’ll see trees and stacks again, many 5mes (oHen with different classes for internal nodes and leaf nodes) Recursive data structures go with recursive algorithms! • CIS 210 .