I have this example to solve, its quite easy but there is a lots of obstracles:
/**
* Write a JavaScript function to check
* whether it is possible to replace $
* in a given expression x $ y = z
* with one of the four signs +, -, * or /
* to obtain a correct expression.
*/
/**
* If we replace $ in input with one of + - * /
* do we get a valid mathematical expression?
* @param {string} input String that is tested
* @returns {boolean} Whether it could be valid expression
*/
const isReplacable = input => {
/**
* Please fill in your code here
*/
return false;
};
const TEST_STRINGS = [
'3 $ 5 = 8',
'2 $ 6 = 3',
'5$5=25',
'2 $ 1 = 2',
'3 $ 4 = 5',
'6 $ 4 = 3',
'3 $ 2 = 1',
'4 $6= 24',
'3$ 2= 6',
'30$ 15 =2',
];
export const runChecks = () => {
TEST_STRINGS.forEach(expression => {
console.log(`${expression}: ${isReplacable(expression) ? 'VALID' : 'INVALID'}`);
});
};
I tried to finish it like this:
1, make parser
function countIt(test) {
const numbers = test.split('');
const target = ' ';
var i = 0;
while (i < numbers.length) {
if (numbers[i] === target) {
numbers.splice(i, 1);
} else {
++i;
}
}
newNumbers = numbers;
console.log(numbers);
const newTarget = '$';
var i = 0;
while (i < newNumbers.length) {
if (newNumbers[i] === newTarget) {
newNumbers.splice(i, 1);
} else {
++i;
}
}
console.log(newNumbers);
finalNumbers = newNumbers;
const finalTarget = '=';
var i = 0;
while (i < finalNumbers.length) {
if (finalNumbers[i] === finalTarget) {
finalNumbers.splice(i, 1);
} else {
++i;
}
}
console.log(finalNumbers);
if (finalNumbers.length)
firstNumber = finalNumbers[0];
secondNumber = finalNumbers[2];
resultNumber = finalNumbers[4];
const result = parseInt(firstNumber) + parseInt(finalNumbers[1])
if (parseInt(firstNumber) + parseInt(secondNumber ) == resultNumber) {
console.log('+');
}
else if (parseInt(firstNumber) - parseInt(secondNumber ) == resultNumber) {
console.log('-');
}
else if (parseInt(firstNumber) * parseInt(secondNumber ) == resultNumber) {
console.log('*');
}
else if (parseInt(firstNumber) / parseInt(secondNumber ) == resultNumber) {
console.log('/');
}
else {
console.log('false');
}
}
But there is so many problems to solve like 2-digits, or missing white-space after expression so i think my solution it too overenginered and isnt working correctly anyway
Do u have any better solutions ? Thanks for your tips ;)
One way to sidestep the whitespace problem would be to (ab)use the fact that parseInt() is lenient and ignores whitespace. This is of course a hack and not how you should generally write programs, but in this case it makes for a fairly elegant solution.
const isReplaceable = (input) => {
const [a, b, c] = input.split(/\$|=/).map(item => parseInt(item, 10));
return (
a * b === c ||
a / b === c ||
a + b === c ||
a - b === c
);
}
const isReplaceable = (input) => {
const [a, b, c] = input.split(/\$|=/).map(item => parseInt(item, 10));
return (
a * b === c ||
a / b === c ||
a + b === c ||
a - b === c
);
}
const TEST_STRINGS = [
'3 $ 5 = 8',
'2 $ 6 = 3',
'5$5=25',
'2 $ 1 = 2',
'3 $ 4 = 5',
'6 $ 4 = 3',
'3 $ 2 = 1',
'4 $6= 24',
'3$ 2= 6',
'30$ 15 =2',
];
TEST_STRINGS.forEach(item => console.log(isReplaceable(item)));
You can do with regex:
Fetch out the three numbers and ignore any whitespaces. If the teststring is in an invalid format (for instance contains invalid characters, no operators, to many or to few numbers, ...) it will return false immediately, because the regex can't match.
Otherwise just check if any of the four operations on the first two numbers results in the third number ...
const isReplaceable = (input) => {
let match = /^\s*(\d+)\s*\$\s*(\d+)\s*=\s*(\d+)\s*$/.exec(input);
if (!match) return false;
return +match[1] + +match[2] == +match[3] ||
+match[1] - +match[2] == +match[3] ||
+match[1] * +match[2] == +match[3] ||
+match[1] / +match[2] == +match[3]
}
const TEST_STRINGS = [
'3 $ 5 = 8',
'2 $ 6 = 3',
'5$5=25',
'2 $ 1 = 2',
'3 $ 4 = 5',
'6 $ 4 = 3',
'3 $ 2 = 1',
'4 $6= 24',
'3$ 2= 6',
'30$ 15 =2',
];
for (let t of TEST_STRINGS)
console.log(t, isReplaceable(t));
let evalBySign = (first, second, answer, sign) => eval(`(${first}) ${sign} (${second})==${answer}`);
let operation = {
'+': function(first, second, answer) {
//Way 1
return Number(first) + Number(second) == answer;
},
'-': function(first, second, answer) {
//Way 2
return eval(`(${first}) - (${second})==${answer}`);
},
'*': function(first, second, answer) {
//Way 2 as function
return evalBySign(first, second, answer, '*');
}
};
['/', '%'].forEach(sign => {
operation[sign] = function(first, second, answer) {
return evalBySign(first, second, answer, sign);
}
});
function isReplacable(input) {
input = input.replace(/\s+/g, '');
let validEq = /\d+\$\d+=\d+/.test(input);
if(!validEq)
return false;
let numbers = input.split(/[\$=]/);
if(numbers.length != 3)
return false;
let [first, second, answer] = numbers;
let operationEntries = Object.entries(operation);
let isReplacelable = false;
for (let entry of operationEntries) {
if(entry[1](first, second, answer)) {
console.log(`${input} equation matched using '${entry[0]}' sign`);
isReplacelable = true;
break;
}
}
return isReplacelable;
}
const TEST_STRINGS = [
'3 $ 5 = 8',
'2 $ 6 = 3',
'5$5=25',
'2 $ 1 = 2',
'3 $ 4 = 5',
'6 $ 4 = 3',
'3 $ 2 = 1',
'4 $6= 24',
'3$ 2= 6',
'30$ 15 =2',
'3 $ = 1 4',
'2 3 5'
];
const runChecks = () => {
TEST_STRINGS.forEach(expression => {
console.log(`${expression}: ${isReplacable(expression) ? 'VALID' : 'INVALID'}`);
});
};
runChecks();