sub P { # Returns strings! my ( $m, $n ) = @_; if ( $m == 1 or $n == 1 ) { return 1; } if ( $m < $n ) { return "P($m,$m)"; } if ( $m == $n ) { return sprintf( "1 + P(%i,%i)", $m, $m - 1 ); } if ( $m > $n ) { return sprintf( "P(%i,%i) + P(%i,%i)", $m, $n - 1, $m - $n, $n ); } die "impossible!"; } MAIN: { local $_ = "P($m,$n)"; print; while ( /\D/ ) { # Put ints up front 1 while s/^(.+\)) \+ (\d+)/$2 + $1/; # Add the ints 1 while s/(\d+) \+ (\d+)/$1 + $2/eg; # Evaluate *one* level at a time s/(P\(\d+,\d+\))/$1/eeg; printf( "\n = %s", $_ ); } }