#!perl use strict; use warnings FATAL => 'uninitialized'; use lib 'lib'; # In response to mjd's comments on his blog post at # # http://blog.plover.com/math/17-puzzle.html # # I present my solution to the problem. Most entertaining. # # T. Alex Beamish / August 11, 2016 use Permute; { my @values = ( 6, 6, 5, 2 ); my @ops = qw/+ - \/ */; my $possibilities = Permute::possibilities( \@values ); foreach my $v ( @{$possibilities} ) { for my $o1 ( @ops ) { for my $o2 ( @ops ) { for my $o3 ( @ops ) { my @list = ( $v->[0], $o1, $v->[1], $o2, $v->[2], $o3, $v->[3] ); # Just try the expression as-is, without any brackets. display ( \@list ); # Now we're going to insert a pair of brackets into the # expression, making sure that a) they encompass at least # a number, an operation, and another number, and b) we # don't bother by bracketing the entire expression, as # that's redundant. for my $lb ( 0, 2, 4 ) { for my $rb ( 4, 6, 8 ) { next unless ( $lb + 2 < $rb ); # a) next if ( $lb == 0 && $rb == 8 ); # b) my @blist = @list; splice ( @blist, $lb, 0, '(', @blist[ $lb .. -1 ] ); splice ( @blist, $rb, 0, ')', @blist[ $rb .. -1 ] ); display ( \@blist ); } } } } } } } # Since we have a duplicated value, we can add a hash to catch # expressions identical to the ones we've evaluated already. # It won't catch the similarity between '2*5' and '5*2' that # evaluate to the same value. Oh well. my %tried_that; sub display { my ( $list ) = @_; my $expression = join('',@{$list}); if ( exists $tried_that{ $expression } ) { return; } $tried_that{ $expression } = 1; my $result = eval $expression; if ( defined $result ) { print "$expression = $result\n"; } else { print "$expression is undefined.\n"; } }