<<

Stacks and Trees Subclasses and Inheritance

Oponal assignment 10 stacks, posix, 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 5

Photo credits: hp://www.city-data.com/forum/alaska/1522185- robot-ken-robodog-go-dog-sledding.html, hp://steamcommunity.com/groups/rdzgroup • CIS 210 Oponal assignment Simple posix 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 Posix Our customary notaon is infix: (3 + 5) * 7 (operators + and * between operands) Posix places operators aer operands: 3 5 + 7 * Prefix places operators before operands * + 3 5 7

Posix and prefix don’t require parentheses or operator precedence. Evaluate posix on a stack.

• CIS 210 Stack

A stack is a sequence that supports inseron and deleon at one end push(x) adds to 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 inseron and deleon at one end

5.3

s = [ ] s.append(5.3)

• CIS 210 Stack

A stack is a sequence that supports inseron and deleon 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 inseron and deleon 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 inseron and deleon 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 posix: 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

* (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 definion 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 definion 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 is a tree. (our interior nodes are expressions represenng addion, mulplicaon, 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 addion, MulOpExpr for mulplicaon, SubOpExpr for subtracon, 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: describe classes and their field_b: type relaonships. Oen 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(): the common aributes into BinOpExpr ... the specific operaons 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 represenng an arithmec 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 somemes 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 funcon, 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 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 Oponal Assignment If you do it, score replaces worst project score (pro-rated by possible score)

You’ll see trees and stacks again, many mes (oen with different classes for internal nodes and leaf nodes) Recursive data structures go with recursive algorithms!

• CIS 210