# working on making it allow negative numbers via some # crazy form of look-behind and look-ahead # NOTE: just because you CAN use a regex to do this # doesn't mean you should! use Carp; if (%results = solve_dio('5x + 7y + 4z = 50')) { print map "$_ => $results{$_}\n", keys %results; } if (solve_dio(x => 3, y => 2, z => 5, 102)) { print "solution found!\n"; } # solve_dio('3x + 2y + 5z = 102'); # solve_dio(x => 3, y => 2, z => 5, 102); sub solve_dio { my ($sum,%args,$regex,@values); if (@_ > 1) { $sum = pop; %args = @_; } elsif (@_ == 1) { ($sum,%args) = parseEQN(shift); } else { croak << "USAGE"; not enough args to solve_dio() solve_dio(EQN) solve_dio(VAR => COEFF, [VAR => COEFF, ] SUM) USAGE } $regex = join " ", map "((?:@{[ 0 x $args{$_} ]})+)", keys %args; if (@values = (0 x $sum) =~ /^ $regex $/x) { return 1 if !wantarray; for (@values) { my ($var) = each %args; $args{$var} = length() / $args{$var}; } return %args; } } sub parseEQN { (my $EQN = shift) =~ tr/A-Za-z0-9 //cd; my (@parts,$sum,%args); @parts = split ' ', $EQN; $sum = pop @parts; %args = map reverse(/(\d+)([a-z])/), @parts; return ($sum, %args); }