In message <[EMAIL PROTECTED]>,
Rick Klement writes:
: most straightforward (ducks...)
:
: [...]
:
: It prints 20 results.
Using Jonathan's RPN evaluator (code below), I get 16 results:
5 7 + 2 / 4 * = 24
7 5 + 2 / 4 * = 24
5 7 + 4 2 - * = 24
5 7 + 4 * 2 / = 24
5 7 + 4 2 / * = 24
7 5 + 4 2 - * = 24
7 5 + 4 * 2 / = 24
7 5 + 4 2 / * = 24
4 5 7 + * 2 / = 24
4 5 7 + 2 / * = 24
4 7 5 + * 2 / = 24
4 7 5 + 2 / * = 24
4 2 - 5 7 + * = 24
4 2 / 5 7 + * = 24
4 2 - 7 5 + * = 24
4 2 / 7 5 + * = 24
When I disable the integer pragma, I get 20 results with the four
extra being:
5 7 + 2 4 / / = 24
7 5 + 2 4 / / = 24
4 2 5 7 + / / = 24
4 2 7 5 + / / = 24
These are using intermediate results that are real numbers.
Greg
#! /usr/local/bin/perl -w
use strict;
use integer;
sub usage { "Usage: $0 target number_1 number_2 [ ... number_n ]\n" }
my @stack;
# Setup function table and pattern
my %ops = ( '+' => sub { $stack[-2] += pop @stack },
'-' => sub { $stack[-2] -= pop @stack },
'*' => sub { $stack[-2] *= pop @stack },
'/' => sub { $stack[-2] /= pop @stack },
'^' => sub { $stack[-2] ^= pop @stack },
# '!' => sub { $stack[-1] = fact($stack[-1]) },
'd' => sub { pop @stack },
'p' => sub { print $stack[-1] },
'P' => sub { print pop @stack },
'r' => sub { return $stack[-1] },
's' => sub { @stack[-2,-1] = @stack[-1,-2] },
'c' => sub { @stack = () }
);
# Create re patterns
my $ops = join("|", map { quotemeta } keys %ops);
my $num = qr/\d+(?:\.\d+)?/;
# RPN Expression Evaluator
sub eval_RPN {
$_=shift;
while (/($ops|$num|\s+|.+)/go) {
my $token = $1;
if (exists $ops{$token}) {
$ops{$token}->();
}
elsif ($token =~ /\s+/) {
# Do nothing
}
elsif ($token =~ /^$num$/) {
push @stack, $token;
}
else {
die "Don't know what to do with: $_";
}
}
return pop @stack;
}
sub permute {
my @items = @{ $_[0] };
my @perms = @{ $_[1] || [] };
unless (@items) {
return [ @perms ];
}
else {
my(@newitems,@newperms,$i);
my @result;
foreach $i (0 .. $#items) {
@newitems = @items;
@newperms = @perms;
unshift @newperms, splice @newitems, $i, 1;
push @result, permute([@newitems], [@newperms]);
}
@result;
}
}
my %seen;
sub arrange {
my $t = shift;
my $n = shift;
my $o = shift;
my @f = @_;
if (@$n == 0) {
push @f, @$o;
# print "[@f]\n";
local $@;
my $result = eval { eval_RPN "c @f r" };
if (!$@ && $result == $t) {
print "@f = $result\n";
}
return;
}
if (@f == 0) {
push @f, splice @$n, 0, 2;
arrange($t, $n, $o, @f);
}
else {
return unless @$o;
my $num = shift @$n;
arrange($t, $n, $o, @f, $num);
unshift @$n, $num;
if (@$o > @$n) {
my $op = shift @$o;
arrange($t, $n, $o, @f, $op);
unshift @$o, $op;
}
}
}
sub find_formula {
my $targ = shift;
my $nums = shift;
my @toke = @_;
if (@toke < @$nums) {
foreach my $perm (permute $nums) {
find_formula($targ, $nums, @$perm);
}
}
elsif (@toke < @$nums + @$nums - 1) {
foreach my $op (qw[ + - * / ]) {
find_formula($targ, $nums, @toke, $op);
}
}
else {
my @n = splice @toke, 0, @$nums;
arrange $targ, \@n, \@toke;
}
}
## main
if (@ARGV < 3) {
die usage;
}
my $target = shift;
my $nums = [ @ARGV ];
find_formula $target, $nums;