Skip to content

Instantly share code, notes, and snippets.

@masak
Last active August 29, 2015 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save masak/ed6e22bd3e6c0a4bb679 to your computer and use it in GitHub Desktop.
Save masak/ed6e22bd3e6c0a4bb679 to your computer and use it in GitHub Desktop.
Find all the ways to combine a set of integers with a set of operators to get a desired result
# see http://irclog.perlgeek.de/perl6/2015-03-11#i_10258447 for background
my @values = 5, 33, 44, 52, 66;
constant DESIRED_RESULT = 283;
for 1..Inf -> $elems {
# Three symmetry breakers:
#
# (a) Terms in sums happen in nondecreasing order of their first factor
# (b) Factors in products happen in nondecreasing order
# (c) Products with more factors happen after products with fewer
sub all-possible-sums($elems) {
return @values.map({ [$_] })
if $elems == 1;
my @sums = all-possible-sums($elems - 1);
return @values.map: -> $value {
@sums.map: -> @s {
[$value, "+", @s],
[$value, "×", @s]
}
};
}
sub canonical(@sum) {
sub terms-in-sorted-order(@terms) {
[!after] @terms
}
sub factors-in-sorted-order(@factors) {
[<=] @factors.grep(Int)
}
sub array-split(@a, $sep) {
my @result;
for @a.kv -> $i, $elem {
return [@result], array-split(@a[$i+1..*], $sep)
if $elem === $sep;
@result.push: $elem;
}
return [@result];
}
my @terms = array-split(@sum, "+");
return terms-in-sorted-order(@terms)
&& [&&](@terms.map(&factors-in-sorted-order));
}
sub result(@sum) { EVAL @sum.subst("×", "*", :g) }
for all-possible-sums($elems) -> @sum {
next unless canonical(@sum);
if result(@sum) == DESIRED_RESULT {
say "{result(@sum)} = @sum[]";
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment