Once we stop requiring that the algorithm produce all solutions, and demand instead that it produce one solution, we can use a greedy technique to speed up the algorithm even more. Allocate terms starting with the largest one possible. This gives a very fast algorithm that nonetheless does not miss any solutions, in the sense that if there is at least one, one solution will be found.
Here is one example.
0^2 + 0^2 + 0^2 + 0^2 + 0^2 + 0^2 + 0^2 + 0^2 + 0^2 + 10000^2 = 100000000
0^2 + 0^2 + 0^2 + 0^2 + 0^2 + 0^2 + 0^2 + 0^2 + 9600^2 + 2800^2 = 100000000
0^2 + 0^2 + 0^2 + 0^2 + 0^2 + 0^2 + 0^2 + 9984^2 + 512^2 + 240^2 = 100000000
0^2 + 0^2 + 0^2 + 0^2 + 0^2 + 0^2 + 9992^2 + 392^2 + 56^2 + 56^2 = 100000000
0^2 + 0^2 + 0^2 + 0^2 + 0^2 + 9999^2 + 141^2 + 10^2 + 3^2 + 3^2 = 100000000
0^2 + 0^2 + 0^2 + 0^2 + 9999^2 + 141^2 + 10^2 + 4^2 + 1^2 + 1^2 = 100000000
0^2 + 0^2 + 0^2 + 9999^2 + 141^2 + 10^2 + 3^2 + 2^2 + 2^2 + 1^2 = 100000000
0^2 + 0^2 + 9999^2 + 141^2 + 9^2 + 5^2 + 3^2 + 1^2 + 1^2 + 1^2 = 100000000
0^2 + 9999^2 + 141^2 + 10^2 + 2^2 + 2^2 + 2^2 + 2^2 + 1^2 + 1^2 = 100000000
9999^2 + 141^2 + 10^2 + 3^2 + 2^2 + 1^2 + 1^2 + 1^2 + 1^2 + 1^2 = 100000000
And here is another.
0^3 + 0^3 + 0^3 + 0^3 + 396^3 + 312^3 + 196^3 = 100000000
0^3 + 0^3 + 0^3 + 463^3 + 79^3 + 57^3 + 41^3 = 100000000
0^3 + 0^3 + 464^3 + 46^3 + 17^3 + 7^3 + 4^3 = 100000000
0^3 + 464^3 + 46^3 + 16^3 + 10^3 + 6^3 + 2^3 = 100000000
464^3 + 46^3 + 16^3 + 9^3 + 7^3 + 5^3 + 3^3 = 100000000
One last example.
0^5 + 39^5 + 22^5 + 21^5 + 14^5 + 3^5 + 1^5 = 100000000
37^5 + 27^5 + 27^5 + 18^5 + 8^5 + 8^5 + 5^5 = 100000000
This is the code.
#! /usr/bin/perl -w
my %memo;
my @basepows;
sub powrep {
my ($n, $k, $p) = @_;
my $key = "$n-$k";
return $memo{$key} if exists $memo{$key};
return [] if $k == 1;
my @res = ();
foreach my $bpair (@basepows){
my $bp = $bpair->[1];
next if $bp >= $n;
my $resref = powrep($n-$bp, $k-1, $p);
if(scalar(@$resref)){
push @res, [$bpair->[0], @{$resref->[0]}];
last;
}
}
$memo{$key} = \@res;
return $memo{$key};
}
MAIN: {
my $n = shift || 1729;
my $k = shift || 2;
my $p = shift || 3;
die "all parameters (n, k, p) positive please"
if $n<1 || $k<1 || $p<1;
my ($q, $val) = (1);
do {
$val = $q ** $p;
if($val<=$n){
$memo{"$val-1"} = [[$q]];
push @basepows, [$q, $val];
}
$q++;
} while($val<$n);
@basepows = reverse(@basepows);
my @allsols;
for(my $zterms = $k-1; $zterms >= 0; $zterms--){
my $resref = powrep($n, $k-$zterms, $p);
if(scalar(@$resref)){
push @allsols, [(0) x $zterms, @{$resref->[0]}];
}
}
foreach my $sol (@allsols){
my $check = 0;
foreach my $t (@$sol){
$check += $t ** $p;
}
my @terms = map { "$_^$p" } @$sol;
print join(' + ', @terms);
print " = $check\n";
}
exit 0;
}