Created
September 11, 2024 01:46
-
-
Save Heliodex/a76afd2163ea2e5097f749d2cb7ade46 to your computer and use it in GitHub Desktop.
Calculates the problem where any three mathematical operators can be inserted at any position in the number 123456789, to equal 100. These programs find six possible solutions.
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
// F# version, bit of a hack because it relies on luau anyway so just use the luau version, it's faster | |
// also I'm never writing a mathematics evaluator | |
open System | |
open System.Diagnostics | |
open System.Collections.Generic | |
// digits one to ten must be in order | |
// numbers one to ten, with 3 operators placed between them | |
let sum = 100 | |
// 1, 0 -> 1 | |
// 3, 0 -> 123 | |
// 3, 1 -> 234 | |
// 5, 2 -> 34567 | |
let len2num len start = | |
let rec f n = | |
if 0 < n && n < 10 then | |
f (n - 1) * 10 + n | |
else | |
0 | |
f len + start * (f len - (f (len - 1))) | |
let rec generateNumbers sum count = | |
let rand = Random() | |
if count = 1 then | |
[ sum ] | |
else | |
let maxVal = min 9 (sum - (count - 1)) | |
let num = rand.Next(1, maxVal + 1) | |
num :: generateNumbers (sum - num) (count - 1) | |
// create a random expr, with 3 operators | |
let createExpr () = | |
let rnd = Random() | |
let rndOp () = | |
match rnd.Next(7) with | |
| 0 -> "+" | |
| 1 -> "-" | |
| 2 -> "*" | |
| 3 -> "/" | |
| 4 -> "//" | |
| 5 -> "^" | |
| _ -> "%" | |
// all integers must sum to 9 | |
let nums = generateNumbers 9 4 | |
// turn the nums into integers with the correct number of digits | |
// for example, [2; 3; 3; 1] would become [12; 345; 678; 9] | |
// and [4; 1; 1; 3] would become [1234; 5; 6; 789] | |
let ints = | |
nums | |
|> List.mapi (fun i n -> len2num n (List.sum (List.take i nums))) | |
let op1, op2, op3 = rndOp (), rndOp (), rndOp () | |
$"%d{ints[0]}%s{op1}%d{ints[1]}%s{op2}%d{ints[2]}%s{op3}%d{ints[3]}" | |
let alreadyDone = new HashSet<string>() | |
let cmd = new Process() | |
cmd.StartInfo.FileName <- "./luau" | |
cmd.StartInfo.RedirectStandardInput <- true | |
cmd.StartInfo.RedirectStandardOutput <- true | |
cmd.StartInfo.CreateNoWindow <- false | |
cmd.StartInfo.UseShellExecute <- false | |
let eval (expr: string) = | |
cmd.Start() |> ignore | |
cmd.StandardInput.Write($"{expr} == {sum}") | |
cmd.StandardInput.Close() | |
cmd.StandardOutput.ReadToEnd().Trim() | |
let mutable totalDone = 0 | |
while true do | |
let expr = createExpr () | |
if alreadyDone.Contains expr then | |
() | |
else | |
alreadyDone.Add expr |> ignore | |
let res = eval expr | |
totalDone <- totalDone + 1 | |
Console.Write($"\r%s{expr.PadRight(15)} = {sum} ({totalDone})") | |
if res = "true" then | |
Console.WriteLine() | |
else | |
() |
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
--!strict | |
-- digits one to ten must be in order | |
math.randomseed(1) | |
local sum = 100 | |
local ops = { "+", "-", "//", "^", "%" } | |
local function rndOp() | |
return ops[math.random(1, #ops)] | |
end | |
local function len2num(len: number, start: number) | |
local function f(n): number | |
return if 0 < n and n < 10 then f(n - 1) * 10 + n else 0 | |
end | |
return f(len) + start * (f(len) - f(len - 1)) | |
end | |
local function generateNumbers(s: number, count: number) | |
if count == 1 then | |
return { s } | |
end | |
local maxVal = math.min(9, s - (count - 1)) | |
local num = math.random(1, maxVal) | |
local tbl = generateNumbers(s - num, count - 1) | |
table.insert(tbl, num) | |
return tbl | |
end | |
local function createExpr() | |
-- all integers must sum to 9 | |
local nums = generateNumbers(9, 4) | |
-- turn the nums into integers with the correct number of digits | |
local ints = {} | |
local start = 0 | |
for i = 1, #nums do | |
ints[i] = len2num(nums[i], start) | |
start += nums[i] | |
end | |
-- create the expression | |
return `{ints[1]} {rndOp()} {ints[2]} {rndOp()} {ints[3]} {rndOp()} {ints[4]}` | |
end | |
-- create a random expr, with 3 operators | |
local alreadyDone = {} | |
local function doneLength() | |
local count = 0 | |
for _ in pairs(alreadyDone) do | |
count += 1 | |
end | |
return count | |
end | |
while true do | |
local expr = createExpr() | |
if alreadyDone[expr] then | |
continue | |
end | |
alreadyDone[expr] = true | |
local fn = loadstring(`return {expr} == {sum}`) | |
if not fn then | |
continue | |
elseif fn() then | |
print(expr) | |
elseif doneLength() == 7000 then | |
break | |
end | |
end | |
print("Done!", doneLength()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment