1: # working on making it allow negative numbers via some
2: # crazy form of look-behind and look-ahead
3:
4: # NOTE: just because you CAN use a regex to do this
5: # doesn't mean you should!
6:
7: use Carp;
8:
9: if (%results = solve_dio('5x + 7y + 4z = 50')) {
10: print map "$_ => $results{$_}\n", keys %results;
11: }
12:
13: if (solve_dio(x => 3, y => 2, z => 5, 102)) {
14: print "solution found!\n";
15: }
16:
17:
18: # solve_dio('3x + 2y + 5z = 102');
19: # solve_dio(x => 3, y => 2, z => 5, 102);
20:
21: sub solve_dio {
22: my ($sum,%args,$regex,@values);
23:
24: if (@_ > 1) {
25: $sum = pop;
26: %args = @_;
27: }
28: elsif (@_ == 1) {
29: ($sum,%args) = parseEQN(shift);
30: }
31: else {
32: croak << "USAGE";
33: not enough args to solve_dio()
34: solve_dio(EQN)
35: solve_dio(VAR => COEFF, [VAR => COEFF, ] SUM)
36: USAGE
37: }
38:
39: $regex = join " ", map "((?:@{[ 0 x $args{$_} ]})+)", keys %args;
40:
41: if (@values = (0 x $sum) =~ /^ $regex $/x) {
42: return 1 if !wantarray;
43: for (@values) {
44: my ($var) = each %args;
45: $args{$var} = length() / $args{$var};
46: }
47: return %args;
48: }
49: }
50:
51: sub parseEQN {
52: (my $EQN = shift) =~ tr/A-Za-z0-9 //cd;
53: my (@parts,$sum,%args);
54:
55: @parts = split ' ', $EQN;
56: $sum = pop @parts;
57: %args = map reverse(/(\d+)([a-z])/), @parts;
58:
59: return ($sum, %args);
60: }