Public
Edited
Apr 16, 2023
Paused
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
steps
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
Insert cell
Insert cell
// format input string
puzzle = {
const splitString = userInputString.split("=")
const numbers = splitString[0].split(",").map(d => Number(d.trim()))
const target = Number(splitString[1].trim())

return {numbers, target}
}
Insert cell
// find the steps to get the digits puzzle answer
steps = {
const result = [[["start", [], null, puzzle.numbers]]]
const steps = solveDigits(puzzle.numbers, puzzle.target)
if (steps) {
result.push(steps.reverse())
return result.flat()
} else {
result.push([["error", [], puzzle.target, `Couldn't find target`]])
return result.flat()
}
}
Insert cell
// go through and solve a Digits puzzle recursively
function solveDigits(
numbers,
target,
operations = []
) {
// check if the target is in the array
if (numbers.includes(target)) return true;

// get the pairs, randomize their order
const pairs = fisherYatesShuffle(getPermutationPairs(numbers));

// randomize order using the math functions
const mathOperations = fisherYatesShuffle(mathFunctions)

// go through pairs and apply math operations
for (let i = 0; i < pairs.length; i++) {
const pair = pairs[i];
for (let j = 0; j < mathOperations.length; j++) {
const f = mathOperations[j];
const result = applyOperation(pair, f.func);
if (result) {
// update numbers
const newNumberArray = removeFirstInstances(numbers, pair);
newNumberArray.push(result);
// keep going
const solution = solveDigits(newNumberArray, target, operations);
// if a solution is found, return operation steps
if (solution) {
operations.push([f.name, pair, result, newNumberArray.sort((a,b) => a-b)]);
return operations
}
}
}
}

// no solution
return undefined
}
Insert cell
// get all of the pair permutations for a set of numbers
function getPermutationPairs(arr) {
return arr.flatMap((num1, index) => {
return arr.slice(index + 1).map((num2) => [[num1, num2], [num2, num1]]);
}).flat();
}
Insert cell
// math operations
mathFunctions = [
{name: "add", func: (a, b) => a + b},
{name: "subtract", func: (a, b) => a - b},
{name: "multiply", func: (a, b) => a * b},
{name: "divide", func: (a, b) => a / b}
];
Insert cell
// apply operation to pair, check for bad results
function applyOperation(pair, operationFunc) {
// apply the operation
const result = operationFunc(pair[0], pair[1])
// check result
if (
!isFinite(result) |
result < 0 |
result % 1 !== 0
) return undefined
return result
}
Insert cell
// remove items from an array and return (just first instances)
// for adding in result
function removeFirstInstances(originalArray, itemsToRemove) {
const newArray = [...originalArray]; // create a copy of the original array

itemsToRemove.forEach(item => {
const index = newArray.indexOf(item);
if (index !== -1) {
newArray.splice(index, 1);
}
});

return newArray;
}
Insert cell
// shuffle array items
function fisherYatesShuffle(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more