Last active
August 29, 2015 14:16
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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