Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I'm writing a simple app to help my daughter practice basic Algebra (first grade). I would like to assign a score to each response depending on the difficulty of the operation, where 2+2 is worth less than 12-7, for example.
Do you know of any existing algorithm I can look up and adapt to my needs?
EDIT
if you want to see the app https://algebro.herokuapp.com
if you want to see the code https://gitlab.com/etozzato/algebro
**EDIT ← **
trying to make the question more specific ;)
given two integers and a basic algebraic operation
algorithm input: int a,b and string operation
algorithm output: float difficulty
→ What are the factors that can help inferring a difficult coefficient?
I would surely look at the input numbers, where their distance can be
significant in determining the complexity of the operation. 10 + 1 is clearly easier than 7 + 5 because (when not memorized and instantly responded) it takes longer counting time;
As an amendment to the previous statement, common/simple arguments should decrease the complexity of the operation: 0 or 10 are a good example;
I don't know of any algorithm to find the "difficulty" of an equation but if I had more time, I might try to play around with something like this... Even though it is for reading, the concept might be adaptable to arithmetic.
Anyway here is a super silly post-midnight crack at something that might work with some tweaking for extremely basic arithmetic. You can tweak the factors/weights but this might get you started. Good luck!
function get_difficulty (eq) {
var difficulty = 0;
var settings = {
terms_factor : 3, //Multiply by the number of terms in an equation
digits_factor : 2, //Multiply by the number of digits in each term
negative_weight : 2, //Add this if subtracting two numbers in the equation yields a negative number
operations : {
"+" : 1,
"-" : 2,
"*" : 4,
"/" : 6,
"=" : 0
}
};
eq += "=";
var ptr = 0;
var terms = 0;
var prev_term = null;
var len = eq.length;
var stack = [ ];
var is_numeric = function (n) {
return /\d+/.test (n); //Not a brilliant way but works for basic arithmetic
};
while (ptr < len) {
var tok = eq [ptr];
if (tok !== " " && tok !== "(" && tok !== ")") {
if (is_numeric (tok)) {
stack.push (tok);
} else if (tok in settings.operations) {
var curr_term = parseInt (stack.join (""));
if (prev_term !== null && curr_term > prev_term && ["-", "="].indexOf (tok) !== -1) {
difficulty += settings.negative_weight;
}
difficulty += stack.length * settings.digits_factor;
prev_term = curr_term;
stack = [ ];
terms++;
difficulty += settings.operations [tok];
} else {
console.log ("Unknown token: " + tok);
}
}
ptr++;
}
difficulty += terms * settings.terms_factor;
return difficulty;
}
console.log (get_difficulty (" 2 + 2 ")); //11
console.log (get_difficulty (" 12 - 7 ")); //14
console.log (get_difficulty (" 7 - 12 ")); //16
console.log (get_difficulty (" 5 - 5 ")); //12
console.log (get_difficulty (" 5 - 1205 ")); //20
console.log (get_difficulty (" 5 - 1205 * 35 ")); //29
console.log (get_difficulty (" 5 * 40 ")); //18
console.log (get_difficulty (" 102 - 5 / 13 + 32 ")); //39
console.log (get_difficulty (" 100 - 100 ")); //20
console.log (get_difficulty (" 32 - 12 ")); //16
console.log (get_difficulty (" 12 - 32 ")); //18
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed last year.
Improve this question
I have a number of ingredients and must know the maximum number of sandwiches (Big and small sandwiches) I can make with it. If ingredients remain, the result must be false.
Big sandwich : 4 slices of tomatoes and 2 slices of cheese
Small sandwich : 2 slices of tomatoes and 1 of cheese
My code works if all ingredients can be used with only small sandwiches or maximum one big sandwich.
It also returns false if ingredients are remaining.
However, it returns false if we need more than one big sandwich in order to use all ingredients.
var result = []
var ispossible = function(tomatoes, cheese) {
/* we need in any case an even number of tomatoes slices */
if (tomatoes % 2 === 0) {
/* the easiest way is making as many small sandwiches as possible. The minimum number of big sandwiches is the number of cheese slices remaining when we devise the total number by 2 */
var bigSandwich = cheese % 2
var smallSandwichTomatoes = (tomatoes - 4 * bigSandwich) / 2
var smallSandwich = cheese - bigSandwich
console.log("we need" + smallSandwich + "small sandwiches and " + bigSandwich + "big sandwiches")
} else {
console.log("false, all the ingredients cannot be used")
}
}
ispossible(10, 3)
Assuming that this solution helps other readers with enhancing their rudimentary algorithm, programming skills:
const bigSmallSandwiches = (t = 10, c = 5) => (
t % 2 !== 0 || t / c !== 2 ?
'false, all the ingredients cannot be used' :
'we need ' + Math.floor((t - Math.floor(t / 4) * 4) / 2).toString() + ' small sandwiches and ' + Math.floor(t / 4).toString() + ' big sandwiches'
);
Explanation
If number of tomato slices is not 'even' or if number of cheese is not exactly half the number of tomato, return 'false'.
Determine number of 'bigSandwiches' as tomatoes / 4
Determine number of 'smallSandwiches' using remaining slices of tomatoes
Code-snippet:
const bigSmallSandwiches = (t = 10, c = 5) => (
t % 2 !== 0 || t / c !== 2 ?
'false, all the ingredients cannot be used' :
'we need ' + Math.floor((t - Math.floor(t / 4) * 4) / 2).toString() + ' small sandwiches and ' + Math.floor(t / 4).toString() + ' big sandwiches'
);
[
[20, 10],
[8, 4],
[4, 3],
[14, 7]
].forEach(x => console.log('tomatoes: ' + x[0] + '\tcheese slices ' + x[1] + '\n' + bigSmallSandwiches(x[0], x[1])));
I have been working to solve this problem on the HackerRank site: Fraudulent Activity Notifications.
Below is the code I have written which satisfies the three sample test cases; however, it does not satisfy the larger test cases since it seems to take longer than 10 seconds.
The 10 second constraint is taken from here: HackerRank Environment.
function activityNotifications(expenditure, d) {
let notifications = 0;
let tmp = [];
let median = 0, medianEven = 0, iOfMedian = 0;
// Begin looping thru 'expenditure'
for(let i = 0; i < expenditure.length; i++) {
// slice from 'expenditure' beginning at 'i' and ending at 'i + d' where d = number of days
// sort 'tmp' in ascending order after
tmp = expenditure.slice(i, i + d);
tmp.sort();
// edge case, make sure we do not exceed boundaries of 'expenditure'
if((i + d) < expenditure.length) {
// if length of 'tmp' is divisible by 2, then we have an even length
// compute median accordingly
if(tmp.length % 2 == 0) {
medianEven = tmp.length / 2;
median = (tmp[medianEven - 1] + tmp[medianEven]) / 2;
// test if expenditures > 2 x median
if(expenditure[i + d] >= (2 * median)) {
notifications++;
}
}
// otherwise, we have an odd length of numbers
// therefore, compute median accordingly
else {
iOfMedian = (tmp.length + 1) / 2;
// test if expenditures > 2 x median
if(expenditure[i + d] >= (2 * tmp[iOfMedian - 1])) {
notifications++;
}
}
}
}
return notifications;
}
I am familiar with O notation for computing time complexity, so initially it seems the problem is either the excessive amount of variables declared or conditional statements used. Only one for loop is being used so I don't think the loop is where I should look to optimize the code. Unless, of course, we were to include the .sort() function used on 'tmp' which would definitely add to the time it takes to compute efficiently.
Is there anything I have not realized which is causing the code to take longer than expected? Any other hints would be greatly appreciated, thanks.
I was given a code challenge to do that was related to recursion and was unable to complete it. My experience with these types of questions is very slim and this one just stumped me. Could any of you help me out just for my own education, as I've already failed the challenge?
The description:
Given a string of numbers and operators, print out all the different ways you can add parentheses to force the order of operations to be explicit, and the result for running the operations in that order.
Assume:
No weird inputs, everything is separated by one space.
Supported operators are +, *, -, = (for the = operator, if the values are the same return 1, otherwise return 0)
Print your results sorted numerically
Don't worry about the input expression size being too large
Your code should be written in javascript
Don't use eval or external libraries
Example:
node test.js "2 - 1 - 1"
((2-1)-1) = 0
(2-(1-1)) = 2
node test.js "2 * 3 - 4 * 5";
(2*(3-(4*5))) = -34
((2*3)-(4*5)) = -14
((2*(3-4))*5) = -10
(2*((3-4)*5)) = -10
(((2*3)-4)*5) = 10
node test.js "2 + 2 = 2"
((2+2)=2) = 0
(2+(2=2)) = 3
This is where I'm at so far. I'm far from getting the right output, but I feel like the logic is starting to get there. I've adapted this code from a similar, but different question.
var args = process.argv.slice(2)[0].split(" "),
numberOfOperators = 0;
args.forEach(function(val, index, array) {
if (isNaN(val)) {
++numberOfOperators;
}
});
args = args.join("");
var recurse = function(openParenCount, closeParenCount, input, pointer) {
if (openParenCount === 0 && closeParenCount === 0) {
console.log(input + "\n");
}
if (openParenCount > 0) {
input = input.slice(0, pointer) + "(" + input.slice(pointer, input.length);
recurse(openParenCount - 1, closeParenCount + 1, input, pointer+1);
}
if (closeParenCount > 0) {
input = input.slice(0, pointer+openParenCount+3) + ")" + input.slice(pointer+openParenCount+3, input.length+1);
recurse(openParenCount, closeParenCount - 1, input, pointer+3);
}
}
recurse(numberOfOperators, 0, args, 0);
a little hint:
var AP = [];
var input = process.argv.slice(2)[0];
var args = input.replace(/\s+/g, "").split(/([^\d\.]+)/g);
recurse(args, []).forEach(function(v){ console.log(v); });
function recurse(arr, into){
if(arr.length === 1){
into.push(arr[0]);
}else{
for(var i=0, j=arr.length-2; i<j; i+=2){
recurse(
AP.concat(
arr.slice(0, i),
"(" + arr.slice(i, i+3).join(" ") + ")",
arr.slice(i+3)
),
into
)
}
}
return into
}
This Implementation still has a few "bugs", and these by intent; I'm not going to do your "homework".
If you have more than 2 operators in your Equasion, the result will contain duplicates, 2nd It is not sorted, and since it is just splitting and concatenating strings, it can't compute any result.
But it shows you a way how you can implement the recursion.
I am trying to solve this question and I know a way to solve it for number of 0s, but I am unable to solve it for number of 5s
I am trying soemthing like this
function findFive(lastNumber){
var count=1,k;
if(lastNumber<5)
return 0;
else if(lastNumber===5)
return 1;
else{
for(var i=6;i<=lastNumber;i++){
k=i;
while(k>0){
if(k%5==0 && k%10!==0)
count++;
k=k/5;
}
}
return count;
}
}
but this wont work for numbers like 50, 550, 500 etc. So i wanted to know which is the best and efficient way to solve this problem.
Thanks. Any help appreciated
We can see a pattern for the total, as we keep increasing digits.
1 -- 0
5 -- 1
10 -- 0 * 9 + 10^0 = 1
59 -- 1 * 5 + 10^1
60 -- 1 *(6-1)+ 10^1
100 -- 1 * 9 + 10^1 = 19
599 -- 19* 5 + 10^2
600 -- 1 *(6-1)+ 10^2
1000 -- 19* 9 + 10^2 = 271
with this pattern we can get the results by looking at each of the digits in the number
for example:
332 -- 3*19 + 3*1 + 2*0
984 -- [(9-1)*19 + 100] + [(8-1)*1 + 10] + [4*0]
3943 -- 3*271 + ((8-1)*19 + 100) + 4*1 + 3*0
1543 -- 1*271 + (5*1 +44)
then we can write some code.
function findFive(n){
// we'll cast the value to a string, to be able to grab the Most Significant Digit easily
return _findFive(String(n))["t"]
}
// helper function. Returns the integer value of the number without
// the first digit (eg. "3948" returns 948)
function remaining(n){
return n.length > 1 ? parseInt(n.substr(1)) : 0;
}
// Recursive function. Returns the total number of 5s in the range 0 to n, and the multiplier for the next higher digit
function _findFive(n){
if(n.length == 0) return {t:0,m:0};
var result = _findFive(n.substr(1)); // get the total from the less significant digits.
// Also returns the multiplier for the MSD
var msd = n[0]; // Most significant digit
if(msd < 5) total = msd * result["m"] + result["t"];
else if(msd == 5) total = msd * result["m"] + remaining(n) + 1;
else total = (msd-1) * result["m"] + Math.pow(10,n.length-1) + result["t"];
var multiplier = result["m"]* 9 + Math.pow(10,n.length-1); // calculate multiplier for next higher digit
return {t:total,m:multiplier}
}
This code will solve the problem in log(n) time. It's not necessary to process each of the numbers in the range (O(n) time) to get the answer.
To count the number of integers containing a 5, in a range from 0...lastNumber, try something like this:
function findFive(lastNumber){
var count = 0,
str = lastNumber + '';
for(var i = 0; i <= lastNumber; i++){
if((i+'').indexOf('5') !== -1){
count++;
}
}
return count;
}
Results:
findFive(60) // 15
findFive(550) // 146
findFive(550746) // 255502
Just keep in mind that the larger this number gets, the more time it's going to take to calculate the result.
You could make it a string and search on that. Something like,
function findFive(upperBound) {
var count = 0;
for (var i = 0; i < upperBound; ++i) {
if (i.toString().match(/5/)) {
++count;
}
}
return count;
}
To see if this is more efficient than a number parsing approach you should try and benchmark them both.
I'd like to write an algorithm in Javascript for the following problem.
Given the following array [1,2,3,4,6], provide the number of subsets that equal any other element in the array.
For instance:
1+2 = 3
1+3 = 4
2+4 = 6
1+2+3 = 6
Answer: 4 subsets
I can calculate the sum of pairs of numbers that equal any other element in the array; however, I cannot find the sum of 2 or more elements (1+2+3) that equal any other element in the array.
How would I write an algorithm for this? Thanks!
Here's a very simple solution that should be easy to grasp. Note that this is not a very fast algorithm, but for shorter arrays it works well.
The idea is to generate a bit mask for every combination, and then for each mask add the numbers in the array indicated by a 1 in the bit mask string:
console.log("Number of subsets: " + getNumberOfSubsets([1, 2, 3, 4, 6], 2));
function getNumberOfSubsets(numbers, minimumNumbersInSubset) {
var numberOfBits = Math.pow(2, numbers.length);
var numOfSubsets = 0;
for (var i=0;i<numberOfBits;i++) {
var bitField = i.toString(2);
while(bitField.length < numbers.length) {
bitField = "0" + bitField;
}
var sum = 0;
var addedNumbers = [];
for (j=0;j<bitField.length;j++) {
if (bitField.charAt(j) == "1") {
sum += numbers[j];
addedNumbers.push(numbers[j]);
}
}
if (addedNumbers.length >= minimumNumbersInSubset && numbers.indexOf(sum) !== -1) {
numOfSubsets += 1;
console.log("Iteration " + i + ": " +
bitField+", " + (addedNumbers.join("+") + "=" + sum));
}
}
return numOfSubsets;
}
Outputs the following in the console to show the successful combinations:
Iteration 10: 01010, 2+4=6
Iteration 20: 10100, 1+3=4
Iteration 24: 11000, 1+2=3
Iteration 28: 11100, 1+2+3=6
Number of subsets: 4
Here's a jsfiddle: http://jsfiddle.net/9HhSs/