Re: Perl 'Medium' Quiz-of-the-Whatever for 2009-08-11 : Plusified Equations

Ronald J Kimball <[email protected]> Wed, 07 Oct 2009 12:55:00 -0400
Newsgroups gmane.comp.lang.perl.qotw.discuss
Message-ID <[email protected]>
Yay, the list is back.  Here's my solution.  I generate the plusified
expressions iteratively by doing repeated increments, treating the
expression itself as a binary string with '+' and '' representing 1 and 0:

  s/(.*\d)(\d.*)/my $x = $2; $x =~ tr!+!!d; "$1+$x"/e

To be more efficient, I don't store both sets of results.  First, I
calculate and store the results for the second expression only.  Then, I
generate results one at a time for the first expression, print any matches
immediately, and throw away the result.  This gives the correct order of
output without any sorting.

#!perl

use strict;
use warnings;

@ARGV == 2
  or die usage();

foreach (@ARGV) {
  /^\d+\z/
    or die usage();
}

my %p2;

my ($p1, $p2) = @ARGV;

do {
  push @{ $p2{do_eval($p2)} }, $p2;
} while ($p2 = next_plusify($p2));

do {
  if (my $match = $p2{do_eval($p1)}) {
    print "$p1 = $_\n" for @$match;
  }
} while ($p1 = next_plusify($p1));

sub next_plusify {
  my ($exp) = @_;
  $exp =~ s/(.*\d)(\d.*)/my $x = $2; $x =~ tr!+!!d; "$1+$x"/e
    or return;
  return $exp;
}

sub do_eval {
  my ($exp) = @_;
  $exp =~ s/\+0+(?=\d)/\+/g;
  eval $exp;
}

sub usage {
  return "$0 <int> <int>\n";
}

__END__

Ronald