#!/usr/bin/perl use strict; use warnings; use Getopt::Long; GetOptions 'digits=i' => \my $digits, # Number of digits. 'min=i' => \my $min, # Minimum sum. 'max=i' => \my $max, # Maximum sum. 'terms=i' => \my $terms, # Minimum number of terms in sum. ; $digits ||= 3; $min ||= 0; $max ||= 0x7FFFFFFF; $terms ||= 6; # # Return all permutations of a set. # sub perms; sub perms { @_ ? map {my $i = $_; map {[$_ [$i] => @$_]} perms @_ [0 .. $i - 1, $i + 1 .. $#_]} 0 .. $#_ : []; } # # Return the powerset of a set. # sub power_set; sub power_set { @_ ? do {my @r = power_set @_ [1 .. $#_]; [$_ [0]] => @r => map {[$_ [0] => @$_]} @r} : () } my %answers; sub try { local $" = " + "; foreach my $set (power_set @_) { my $sum = eval "@$set"; push @{$answers {$sum}} => $set; } } OUTER: foreach (("0" x $digits) .. ("9" x $digits)) { my @digits = split //; for (my $i = 1; $i < @digits; $i ++) { next OUTER if $digits [$i] < $digits [$i - 1] } my %seen; try grep {!$seen {$_} ++} map {$_ = join "" => @$_; s/^0*(?=\d)//; $_} perms @digits; } foreach my $sum (sort {$a <=> $b} keys %answers) { next unless $sum >= $min && $sum < $max; next unless @{$answers {$sum}} == 1; next unless @{$answers {$sum} [0]} >= $terms; local $" = " + "; print "$sum == @{$answers{$sum}[0]}\n"; } __END__