1 / 14

COMP 114 Recitation

Special agenda topics, assignment rubrics & solutions, Towers of Hanoi recursive solution, Factory design pattern, Perl code examples.

sloden
Download Presentation

COMP 114 Recitation

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. COMP 114 Recitation October 31, 2003

  2. Agenda • Special topics survey • Assignment 5(a-d) rubric • Assignment 3(d) solution • Recursive solution to the Towers of Hanoi • Factory design pattern

  3. Assignment 5 Rubric

  4. Assignment 3(d) Solution #!/usr/bin/perl -w use strict; package StringScanner; sub new { my $class = shift; my $self = bless {}, $class; $self->{"_str"} = shift; return $self; } sub hasmore { my $self = shift; die "instance method called on" ." class" unless ref $self; return ($self->{"_str"} =~ /[^\s]/); } sub nextstr { my $self = shift; die "instance method called on class" unless ref $self; $self->{"_str"} =~ /^\s*(\d+|[^\s])(.*)$/; $self->{"_str"} = $2; return $1; } package TokenScanner; sub new { my $class = shift; my $self = bless {}, $class; $self->{"_strscan"} = StringScanner->new(shift); return $self; } sub hasmore { my $self = shift; die "instance method called on class" unless ref $self; return $self->{"_strscan"}->hasmore(); } sub nexttoken { my %ops = ('+' => 'Token::Operator::Plus','-' => 'Token::Operator::Minus','*' => 'Token::Operator::Multiply','/' => 'Token::Operator::Divide'); my $self = shift; die "instance method" . " called on class" unless ref $self; my $s = $self->{"_strscan"}->nextstr(); my ($t, $c); if ($s =~ /^\d+$/) { $t = Token::Number->new(); $t->assign($s); } else { $c = $ops{$s}; $t = eval("$c->new()"); die "$@" if $@; } return $t; } package Token; sub new { my $class = shift; my $self = bless {}, $class; return $self; } sub tostr { my $self = shift; die "instance method called on class" unless ref $self; return sprintf("%s@%p(%s)", ref($self), $self, $self->decomp()); } sub decomp { return "<token>"; } package Token::Number; @Token::Number::ISA = ("Token"); sub decomp { my $self = shift; die "instance" . " method called on class" unless ref $self; return $self->{"_number"}; } sub value { my $self = shift; die "instance method called on class" unless ref $self; return $self->{"_number"}; } sub assign { my $self = shift; die "instance method called on class" unless ref $self; $self->{"_number"} = shift; } package Token::Operator; @Token::Operator::ISA = ("Token"); sub calc { die "abstract method Token::" . "Operator::calc"; } sub decomp { return "<operator>"; } package Token::Operator::Plus; @Token::Operator::Plus::ISA = ("Token::Operator"); sub calc { my $self = shift; die "instance method" . " called on class" unless ref $self; my ($l, $r) = @_; return $l + $r; } sub decomp { return "+"; } package Token::Operator::Minus; @Token::Operator::Minus::ISA = ("Token::Operator"); sub calc { my $self = shift; die "instance method called on class" unless ref $self; my ($l, $r) = @_; return $l - $r; } sub decomp { return "-"; } package Token::Operator::Multiply; @Token::Operator::Multiply::ISA = ("Token::" . "Operator"); sub calc { my $self = shift; die "instance method called on class" unless ref $self; my ($l, $r) = @_; return $l * $r; } sub decomp {return "*";} package Token::Operator::Divide; @Token::Operator::Divide::ISA = ("Token::Operator"); sub calc { my $self = shift; die "instance method" . " called on class" unless ref $self; my ($l, $r) = @_; return $l / $r; } sub decomp {return "/"; } sub new { my $class = shift; my $self = bless {}, $class; $self->{"_strscan"} = StringScanner->new(shift); return $self; } package Evaluator; sub new { my $class = shift; my $self = bless {}, $class; $self->{"_tscan"} = TokenScanner->new(shift); return $self; } sub calc { my $self = shift; die "instance" . " method called on class" unless ref $self; my (@e, $x) = (); while ($self->{"_tscan"}->hasmore()) { my $t = $self->{"_tscan"}->nexttoken(); push @e, $t; } $x = (shift @e)->value(); while (@e) { my ($o, $v); $o = shift @e; $v = shift @e; $x = $o->calc($x, $v->value()); } return $x; } package MAIN; my ($e, $c); while (1) { print "Please enter a number expression:\n"; $e = <STDIN>; chomp $e; exit if $e eq '.'; $c = Evaluator->new($e); print $c->calc() . "\n"; }

  5. Towers of Hanoi Objective: Move the discs from one tower to another. Constraint #1: Don’t put a big disc on a small one. Constraint #2: Move only one disc at a time. Constraint #3: Only topmost discs may move.

  6. The Four-Disc Solution

  7. Base Case • Move the tower to the final peg.

  8. Recursive Case • Move the body of the tower to the middle peg. • Move the base of the tower to the final peg. • Move the body of the tower to the final peg.

  9. The Final Pseudocode void Hanoi(int size, Peg source, Peg middle, Peg dest) { if (size == 1) { Move_Disc(source, dest); } else { Hanoi(size - 1, source, dest, middle); Move_Disc(source, dest); Hanoi(size - 1, middle, source, dest); } }

  10. Factories • Defer class instantiation to subclasses, and move decisions to runtime. • Provide a handy abstraction to class creation. • Rather than hardcode your class names everywhere you have a new statement, make a method call to a factory. It gets to store the hardcoded class names.

  11. public abstract class Apple { public abstract String getName(); public void eat() { System.err.println( "Core dumped."); } } public class RedDelicious extends Apple { public String getName() { return "Red Delicious(tm)"; } } public class GrannySmith extends Apple { public String getName() { return "Granny Smith(tm)"; } } public class Macintosh extends Apple { public String getName() { return "iCrap(R)"; } } public class FourMonthOld extends Apple { public String getName() { return "Who knows?"; } public void eat() { System.err.println( "Mmmm! Cafeteria fresh!"); } } Example: Derived Classes

  12. Example: Factory Class public class AppleFactory { public static Apple fromAdjective(String adj) { if (adj.equals("red")) return new RedDelicious(); if (adj.equals("green")) return new GrannySmith(); if (adj.equals("rotten")) return new Macintosh(); return new FourMonthOld(); } }

  13. Example: Main Class public static void main(String[] args) { Apple a; String s; initStdin(); System.out.println("Apple type? "); s = stdin.readLine(); a = AppleFactory.fromAdjective(s); System.out.print("Apple type: "); System.out.print(a.getName()); a.eat(); System.out.print("Yum."); }

  14. The Next Step • Instead of using a static method, why not make the “default apple” instance-dependent? • Make a factory class which creates other factories. We call this the Abstract Factory design pattern. • Don’t instantiate each time, but instead copy the object from a prototype. We’ll discuss this later.

More Related