#!/usr/bin/perl -w # Author: Chao-Kuei Hung # For more info, including license, please see doc/index.html use strict; use Getopt::Std; use lib '!!PREFIX!!/lib/perl5/site_perl/5.8.8/algotutor'; BEGIN { my ($path) = $0 =~ m#(.*/)#; $path = "." unless defined $path; push @INC, $path; } my ( %opts, # command line options $wd, # tk widgets $dfn, # data file name $mds, # main data structure ); %opts = ( a => undef, # which algorithm to run? s => undef, # start vertex (for some graph algos) i => 0, # step # of initial image d => undef, # dump ps file and exit immediately ); require "utilalgo"; require "basic.pl"; $wd->{main} = MainWindow->new(-title=>"algotutor"); getopts('a:s:i:d:', \%opts); if (grep { $opts{a} eq $_ } qw(lcs matc flwa)) { # dynamic programming my ($algo) = $opts{a}; my ($tab) = { lcs => { maxlvl => 3, run => sub { require "dp/lcs"; lcs(@ARGV[0,1], $wd->{can}{main}); }, }, matc => { maxlvl => 3, run => sub { require "dp/matrixchain"; matrixchain(\@ARGV, $wd->{can}{main}); }, }, flwa => { maxlvl => 3, run => sub { require "dp/flwa"; flwa($ARGV[0], $wd->{can}{main}); }, } }; require Board; $wd->{can}{main} = gen_can($wd->{main}, undef, -elevation=>1, -maxlevel=>$tab->{$algo}{maxlvl} ); $wd->{ctrl} = gen_ctrl($wd->{main}, $wd->{can}); $tab->{$algo}{run}(); } else { # algorithms other than dynamic programming die "need exactly one data file. Example:\n\talgotutor -a bst !!PREFIX!!/share/algotutor/data/countries.gr\n" unless $#ARGV == 0; $dfn = $ARGV[0]; die "cannot read data file '$dfn'.\nDoes it exist and do you have read permissions?\n" unless -r $dfn; die "please specify an algorithm to run using -a. Example:\n\t-a bst\n\t-a heap\n\t-a sbs\n\t-a bfs\n\t-a prim\n\t-a dijk\n\t-a flwa\n" unless defined $opts{a}; $mds = eval { do $dfn }; die "'$dfn' does not look like a valid algotutor data file\n" unless ($mds and ref $mds eq "HASH"); if (grep { $opts{a} eq $_ } qw(bst rbt heap graham dom)) { usual_algo($opts{a}); } elsif (grep { $opts{a} eq $_ } qw(bfs sbs dijk prim)) { $mds = prio_first($wd, $mds, $opts{a}); } else { die "unknown algorithm '$opts{a}'\n"; } } $wd->{ctrl}->configure(-recorder=>0); my ($steps) = $wd->{ctrl}->{"#lowest_canvas"}->total_marks( $wd->{ctrl}->{"#slevel"} ); printf "total marks: %d\n", $steps; if (defined $opts{i}) { if ($opts{i} < 0 or $opts{i} >= $steps) { print STDERR "illegal request to display step $opts{i} (out of range)\n"; } else { print "seeking to step $opts{i}...\n"; $wd->{ctrl}->timeknob_seek($opts{i}); } } if ($opts{d}) { dump_image($wd->{can}, $opts{d}); } else { Tk::MainLoop(); } exit(); # end of main program sub disp_vert_val { my ($v, $val) = @_; $v->configure(-text=>"$v\n$val"); } sub prio_first { my ($wd, $mds, $prio) = @_; require Graph; $wd->{can}{main} = gen_can($wd->{main}, undef, -elevation=>2, -maxlevel=>3); $wd->{can}{fr} = gen_can($wd->{main}, "Fringe", -elevation=>1, -maxlevel=>3); $wd->{ctrl} = gen_ctrl($wd->{main}, $wd->{can}); $mds = Graph->new(-canvas=>$wd->{can}{main}, %$mds); require "graph/pfs"; pfs($mds, $wd->{can}{fr}, -start=>$opts{s}, -priority=>$prio, -on_vertex=>\&disp_vert_val); return $mds; } sub usual_algo { my ($algo) = @_; my ($tab) = { bst => { ds => "BST", maxlvl => 2 }, rbt => { ds => "RBTree", maxlvl => 2 }, heap => { ds => "Heap", maxlvl => 3 }, graham=> { ds => "Graph", maxlvl => 2, post=> sub { require "cgeom/graham"; graham($mds); } }, dom => { ds => "Graph", maxlvl => 2, post=> sub { require "cgeom/dom"; dom($mds); } }, # dfs => { ds => "Graph", maxlvl => 2, post=> sub { # require "graph/dfs"; # dfs($mds, -start=>$opts{s}, -on_vertex=>\&disp_vert_val); # } }, flwa => { ds => "Graph", maxlvl => 2, post=> sub { require "graph/flwa"; flwa($mds); } }, }; require $tab->{$algo}{ds} . ".pm"; $wd->{can}{main} = gen_can($wd->{main}, undef, -elevation=>1, -maxlevel=>$tab->{$algo}{maxlvl} ); $wd->{ctrl} = gen_ctrl($wd->{main}, $wd->{can}); $mds = eval($tab->{$algo}{ds} . '->new(-canvas=>$wd->{can}{main}, %$mds)'); $tab->{$algo}{post}->() if ref $tab->{$algo}{post}; } __END__ =head1 NAME algotutor - an interactive program for observing the intermediate steps of algorithms. =head1 SYNOPSIS B [I