use v6;
# Problem 1 -- Find a way to express an integer as an expression containing four 9s
# Since there's only 125 sequences of 9's with the basic arithmetic operators
# and modulo between them, I generate all the sequences. If there were twelve
# nines (about fify million permutations), I might think about using a different
# approach.
die "Maximum index argument required." unless @*ARGS;
my $max = @*ARGS[0].Int;
die "Maximum index argument must be an integer" if $max ne @*ARGS[0];
my $max = 81;
my @operators = <+ - * / %>;
my %operation = @operators Z=> (&infix:<+>, &infix:<->, &infix:<*>, &infix:, &infix:<%>);
# Skip some of the equivalent expressions. There are more, but these are the
# only set of length two, which are going to have the most impact.
my $skip = any(<-+ /*>);
my %valid;
# List auto-flattening makes this more verbose than it should need to be. While
# I don't think that it's neccessarily a bug, it would be nice to have some way
# to have the for loop not auto-flatten my cross operation.
my $cross := infix:(|([[@operators]] xx 3));
for ^$cross.elems -> $index
{
my @ops_str = @($cross[$index]);
next if any(@ops_str Z~ @ops_str[1 .. *]) ~~ $skip;
my @ops = %operation{@ops_str};
my $result = (9, @ops).reduce: -> $so-far, $op { $op($so-far,9) };
next unless $result == $result.Int && $result > 0 && $result <= $max;
# RAKUDOBUG: Hash.push was flattening my list no matter how many sets
# of square brackets I put there.
%valid{$result} = [] unless %valid.exists($result);
my $value = [@ops_str];
%valid{$result} = [@(%valid{$result}), $value];
}
for 1 .. $max -> $num
{
print $num;
if %valid.exists: $num
{
print ":";
my $first = True;
for @(%valid{$num}) -> $expr
{
print " OR" if !$first;
$first = False;
print ' ' ~ ((9 xx $expr.elems Z $expr), 9);
}
}
print "\n";
}