#!/usr/bin/perl -w # # Copyright (C) 2002 Likai Liu # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # Advertisement: # # BU/GNU Linux Users Group meets every Wednesday in room MCS 148 at 6pm. # Visit http://pks.bu.edu:8080 for our website and join our mailing list! # # CS320 Assignment 1, Exercise 1 # Likai Liu use strict; use vars qw( @RESULTS ); # this section is to avoid duplicate output. O(N) function. sub insert_result { my $expr = shift; foreach my $line (@RESULTS) { return if $line eq $expr; } push @RESULTS, $expr; } sub list_result { print $_, "\n" foreach @RESULTS; } # pick an element from the list to combine with quad_iter sub quad_iter_2 { my $excl = shift; splice @_, $excl, 1; foreach my $i (0 .. $#_) { quad_iter( $_[$i], $i, @_ ); } } # before calling quad_iter, you must pick a "choice" for the first operand. # this function will pick a second operand and an operation, appends this # combined expression back to the array of elements, and the calls quad_iter_2 # which picks another source operand to pass to another quad_iter call. in a # way, it is recursion, indirectly. # # when this function is called, it must eliminate the "choice" from the array # element that is passed as the argument. the caller does not delete this # element there so the caller's copy of list of elements remains intact. # # the second parameter (excl) tells quad_iter which element has been picked # by the caller, so to eliminate that from its list of second operand choices. sub quad_iter { my $choice = shift; my $excl = shift; splice @_, $excl, 1; if ($#_ == -1) { # one great thing about perl is that I can eval expressions on the # last stage, so when I get the result i'm looking for, I'm not that # far away from the expression that came up with the result. # # if there is no more elements to choose from the array, then the # choice must be ready to evaluate. it would look something like # "(8 / (3 - (8 / 3)))" as a string. my $result = eval( $choice ); # note that floating point operations are not precise. if we try to # compare precise numbers, we'll miss the expressions that evaluate # to 24.000000000000014285714285714... thankfully when perl compares # a number with a string, the number is converted to the most-likely # representation in string. the "eq" operator is a string comparison, # as opposed to "==" as a numeric comparison. if (defined( $result ) and $result eq "24" ) { insert_result "$choice = 24"; } # it's a large recursion. thankfully we get to return. return; } # otherwise, now the first operand is in $choice, choose a second operand # from the splice'd list of elements. foreach my $i (0 .. $#_) { # and then choose an operation. foreach my $op ( "+", "-", "*", "/" ) { my $r = "($choice $op $_[$i])"; # form "(oprand1 op oprand2)" # tell next generation to skip the chosen element, in the $i'th # index. also put "(oprand1 op oprand2)" back to the raffle. quad_iter_2( $i, @_, $r ); } } } # firestarter ... one who initiates a whole chaos of recursion. sub quad { foreach my $i (0 .. $#_) { quad_iter( $_[$i], $i, @_ ); } } # main() starts here ... if (scalar @ARGV == 4) { quad @ARGV; list_result; } else { print <