in reply to Happy 2006

Perl Mouse,
After finishing my solution, I realized that I must have intepreted the puzzle wrong. I thought each term was evaluated left to right in succession not as 1 entire expression. *shrug*

Here is the (likely incorrect) code I came up with intentionally avoiding eval $string;

#!/usr/bin/perl use strict; use warnings; use Algorithm::Loops qw{NestedLoops MapCar}; my $year = $ARGV[0] || 2006; my @digit = reverse 1..9; my $next = NestedLoops( [ ['+', '-'], ([qw{+ - / *}, '']) x $#digit ] +); while ( my @perm = $next->() ) { my $expr = join '', MapCar { @_ } \@perm, \@digit; print "$expr\n" if evaluate($expr) == $year; } sub evaluate { my ($expr, $tot) = (shift, 0); my %math = ( '+' => sub { $_[0] + $_[1] }, '-' => sub { $_[0] - $_[1] }, '/' => sub { $_[0] / $_[1] }, '*' => sub { $_[0] * $_[1] }, ); for my $term ( $expr =~ m|([/*+-]?\d+)|g ) { if ( $term =~ m|^([/*+-])(\d+)$| ) { $tot = $math{$1}->($tot, $2); } } return $tot; } __END__ +9*8*7-6+5*4-3-2-1 +98/7+654*3+2/1 +98/7+654*3+2*1

Cheers - L~R

Replies are listed 'Best First'.
Re^2: Happy 2006
by Perl Mouse (Chaplain) on Jan 11, 2006 at 00:13 UTC
    I don't quite understand how your program is supposed to work, but the results are indeed incorrect. It seems all your operators have the same precedence?
    +9*8*7-6+5*4-3-2-1 == 512 +98/7+654*3+2/1 == 1978 +98/7+654*3+2*1 == 1978
    Perl --((8:>*
      Perl Mouse,
      No, just each term in the expression is evaluated independently. This is how we did similar puzzles in school. The program works as follows:

      Algorithm::Loops generates all the permutation of operators needed and then the numbers are zipped forming a single string. This is the point where eval $string would produce the same results as your code. Instead, I break each term apart and keep a running total of the value which is returned.

      In my opinion, what would make the puzzle much more interesting would be to require single expression evaluation as your solution does but prohibit the use of eval $string. Here is my original solution modified accordingly though it is quite slow and a bit obfu now. Thanks for the puzzle.

      Cheers - L~R

        In my opinion, what would make the puzzle much more interesting would be to require single expression evaluation as your solution does but prohibit the use of eval $string.
        You went to a school where you didn't have to program a calculator in your first year? I have a different opinion - writing an expression evaluator is boring, and it would be a reimplementation of functionality that perl already provides.

        I like string eval. I wish every programming language had such functionality.

        Perl --((8:>*