Not sure how to make the title smaller. I was reading the question A truly amazing way of making the number 2016 and some of the answers referred to programatically determining the answer set.
What I am doing is related to that in concept. Given a range of number 1 to X determine all possible mathematical expressions that can be used with those numbers and group the results together to see which whole numbers prevail.
function ConvertTo-Base
{
[CmdletBinding()]
param (
[parameter(ValueFromPipeline=$true,Mandatory=$True, HelpMessage="Base10 Integer number to convert to another base")]
[int]$Number=1000,
[parameter(Mandatory=$True)]
[ValidateRange(2,20)]
[int]$Base
)
[char[]]$alphanumerics = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
do
{
# Determine the remainder
$Remainder = ($Number % $Base)
# Get the associated character and add it to the beginning of the string.
$newBaseValue = "$($alphanumerics[$Remainder])$newBaseValue"
# Adjust the number to remove the calculated portion
$Number = ($Number - $Remainder) / $Base
# Loop until we have processed the whole number
} while ($Number -gt 0)
return $newBaseValue
}
# Variables
$maxRange = 3 #13 would make for the largest values 13!. Cap the script as 13
$lowCountThreshold = 1 # Only show group results where the match exists more than five times.
# Mathematical Operators
[char[]]$operators = "+-*/"
# Define the number range for calculations. 13 would make for the largest values 13!. Cap the script as 13
$range = 1..$maxRange
# Build the format string that will be used for invoking. Will look like 1{0}2{1}3. Acting as place holders for mathematic operators
$formatString = -join (1..($range.count - 1) | ForEach-Object{"$_{$([int]$_ - 1)}"}) + $range[-1]
# Determine the number of possible permutations of those operators inbetween the number set.
$permutations = [System.Math]::Pow($operators.Count,$range.count - 1)
# Cycle each permutation
0..($permutations - 1) | ForEach-Object{
# Convert the number to a base equal to the element count in operators. Use those values to represent the index of the operators array.
$mathString = $formatString -f @([string[]][char[]]((ConvertTo-Base -Number $_ -Base $operators.Count).PadLeft($range.count - 1,"0")) | ForEach-Object{$operators[[int]$_]})
# Build an object that contains the result and the mathematical expression
[pscustomobject]@{
Expression = $mathString
Value = Invoke-Expression $mathString
}
# Since this take a while try and give the user some semblance of progress.
Write-Progress -Activity "Performing mathematical calculations" -Status "Please wait." -PercentComplete ($_ / $permutations * 100) -CurrentOperation "$([math]::Round($_ / $permutations * 100))% Completed."
# Filter for whole number and only give group results
} | Where-Object{$_.Value -is [int32]} | Group-Object Value | Where-Object{$_.Count -ge $lowCountThreshold} | Sort-Object Count -Descending
So if you were to run this and change the $maxValue
to something smaller like 3 and change the you would
Count Name Group
----- ---- -----
2 6 {@{Expression=1+2+3; Value=6}, @{Expression=1*2*3; Value=6}}
1 0 {@{Expression=1+2-3; Value=0}}
1 7 {@{Expression=1+2*3; Value=7}}
1 2 {@{Expression=1-2+3; Value=2}}
1 -4 {@{Expression=1-2-3; Value=-4}}
1 -5 {@{Expression=1-2*3; Value=-5}}
1 5 {@{Expression=1*2+3; Value=5}}
1 -1 {@{Expression=1*2-3; Value=-1}}
So there are two operations that would get 6. 1+2+3
and 1*2*3
. Who would have thought! If you are testing this be careful of using larger numbers here. Running something like a 9 would take about 7 minutes give or take since it would have 65536 permutations to figure out and then group.
The function helps me convert each permutation number into its mathematical operator sequence. I take a number and convert it into base4. Then take that and use each number to pull an element out of the operator array. Then use the format operator to populate the string and use invoke expression to get the result.