A chrome extension which can solve https://www.countle.org
Follow these steps to install the Chrome extension:
-
git clone git@github.com:shivam-bhadani/Countle-Solver.git
-
cd Countle-Solver npm install
-
npm run build
-
- Open Google Chrome.
- Go to
chrome://extensions/
. - Enable Developer mode (toggle switch in the top-right corner).
- Click on "Load unpacked" and select the
dist
directory within Countle-Solver directory.
- Navigate to https://www.countle.org and start a puzzle.
- Click on the Countle Solver Chrome Extension icon in the toolbar.
- Click on Solve button to get the solution of the puzzle.
- Enjoy the solved puzzle.
The Countle Solver Chrome Extension uses a recursive algorithm to solve puzzles efficiently. Here's a breakdown of the solution approach:
The core of the solution lies in the recursion
function. This function explores all possible combinations of arithmetic operations (addition, subtraction, multiplication, and division) on the available numbers to reach the target number.
To avoid redundant computations and optimize performance, the solution employs memoization. The memo
set stores the state of each available number combination encountered during the recursive process. This ensures that the algorithm does not revisit previously explored states, thus reducing redundant computations.
The algorithm utilizes backtracking to explore different paths and backtrack when a dead-end is encountered. This allows for a systematic exploration of all possible solutions without getting stuck in infinite loops or redundant computations.
The getNextList
function is a utility function used to generate the next list of available numbers after applying an arithmetic operation. It removes the two numbers involved in the operation and adds the result of the operation to the list.
The getCountleAnswer
function serves as the entry point for solving Countle.org puzzles. It initializes the recursive process with the target number and the initial list of available numbers, and returns the solution in the form of a ICountleResultList[] array containing the sequence of operations applied to reach the target number.
Here is the code that solves the puzzle:
function getNextList(arr: number[], index1: number, index2: number): number[] {
const nextList: number[] = [];
for (let i = 0; i < arr.length; i++) {
if (i !== index1 && i !== index2) {
nextList.push(arr[i]);
}
}
return nextList;
}
export interface ICountleResultList {
firstNumber: number;
secondNumber: number;
symbol: number;
resultant: number;
}
const MAXIMUM_STEPS = 5;
let ans: ICountleResultList[] = [];
const memo: Set<string> = new Set();
function recursion(
target: number,
availableNumbers: number[],
currentAnswer: ICountleResultList[],
steps: number
): void {
availableNumbers.sort((a, b) => a - b);
if (ans.length) {
return;
}
if (steps) {
const made = currentAnswer[currentAnswer.length - 1].resultant;
if (made === target) {
ans = [...currentAnswer];
return;
}
}
if (steps > MAXIMUM_STEPS) return;
let memo_string: string = availableNumbers.join("_");
if (memo.has(memo_string)) {
return;
}
for (let i = 0; i < availableNumbers.length; i++) {
for (let j = 0; j < availableNumbers.length; j++) {
if (i !== j) {
const firstNumber = availableNumbers[i];
const secondNumber = availableNumbers[j];
// Addition Operation
currentAnswer.push({
firstNumber,
secondNumber,
symbol: 0,
resultant: firstNumber + secondNumber,
});
const additionList = getNextList(availableNumbers, i, j);
additionList.push(firstNumber + secondNumber);
recursion(target, additionList, currentAnswer, steps + 1);
currentAnswer.pop();
// Subtraction Operation
if (firstNumber >= secondNumber) {
currentAnswer.push({
firstNumber,
secondNumber,
symbol: 1,
resultant: firstNumber - secondNumber,
});
const subtractionList = getNextList(availableNumbers, i, j);
subtractionList.push(firstNumber - secondNumber);
recursion(target, subtractionList, currentAnswer, steps + 1);
currentAnswer.pop();
}
// Multiplication Operation
currentAnswer.push({
firstNumber,
secondNumber,
symbol: 2,
resultant: firstNumber * secondNumber,
});
const multiplicationList = getNextList(availableNumbers, i, j);
multiplicationList.push(firstNumber * secondNumber);
recursion(target, multiplicationList, currentAnswer, steps + 1);
currentAnswer.pop();
// Division Operation
if (firstNumber % secondNumber === 0) {
currentAnswer.push({
firstNumber,
secondNumber,
symbol: 3,
resultant: firstNumber / secondNumber,
});
const divisionList = getNextList(availableNumbers, i, j);
divisionList.push(firstNumber / secondNumber);
recursion(target, divisionList, currentAnswer, steps + 1);
currentAnswer.pop();
}
}
}
}
memo.add(memo_string);
}
function getCountleAnswer(target: number, inputArray: number[]): ICountleResultList[] {
const currentAnswer: ICountleResultList[] = [];
recursion(target, inputArray, currentAnswer, 0);
return ans;
}
export default getCountleAnswer;
The getCountleResult
function is the main function responsible for solving Countle.org puzzles. It takes the target number and the initial list of available numbers as inputs, and returns the solution in the form of a 2D array containing the sequence of operations applied to reach the target number.
- target: The target number that the puzzle aims to reach.
- Type:
number
- Type:
- inputArray: An array containing the initial available numbers for the puzzle.
- Type:
number[]
- Type:
- Result: An array of ICountleResultList[] representing the solution to the Countle.org puzzle. Each inner array is an object representing a single operation applied to reach the target number.
- firstNumber: The first number involved in the operation.
- secondNumber: The second number involved in the operation.
- symbol: The operation type (0 for addition, 1 for subtraction, 2 for multiplication, 3 for division).
- resultant: The result of the operation.
- Type:
ICountleResultList[]
If you encounter any issues or have any questions, feel free to open an issue on GitHub.