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])));
Related
Currently, I've learned 3 different approaches to count the minimum amount of moves to solve the Tower of Hanoi.
The first approach is: 2 to the power of "discs" minus 1. All in all, very straight forward and comprehensible.
const towerHanoi = (discs) => 2**discs - 1;
console.log(towerHanoi(0)); // 0
console.log(towerHanoi(2)); // 3
console.log(towerHanoi(3)); // 7
console.log(towerHanoi(4)); // 15
console.log(towerHanoi(5)); // 31
console.log(towerHanoi(6)); // 63
The second approach is with a "for loop." On each iteration, add "count" to the result of 2 to the power of "i" Once again, very straight forward and comprehensible.
function towerHanoi(discs,count=0) {
for (let i = 0; i < discs; i++) count += 2**i;
return count;
}
In the third approach with recursion, however, I just couldn't quite grasp the concept the recursive process.
const towerHanoi = (discs) => discs === 0 ? 0 : 2 * towerHanoi(discs-1) + 1;
Let's use 5 discs as our example to illustrate the recursive process which requires a minimum of 31 moves to complete the game. I'm going to try my best to break down the recursive process as I can as followed:
2 * (5-1) + 1 === 9
2 * (4-1) + 1 === 7
2 * (3-1) + 1 === 5
2 * (2-1) + 1 === 3
2 * (1-1) + 1 === 1
9 + 7 + 5 + 3 + 1 --> 25 =/= 31
As you can see, I get 25 instead of 31. What am I missing. Can someone kindly help me understand the recursive process of the code? Thanks for reading and million thanks in advance :)
The reasoning behind this recursive formula:
const towerHanoi = (discs) => discs === 0 ? 0 : 2 * towerHanoi(discs-1) + 1;
...is as follows:
Let's assume we know how to move discs-1 discs from one pile to another. Then we can use that knowledge as follows:
Move all discs, excepts the bottom one, to the middle spot (using that knowledge). Then move the greatest disc to the final spot. Finally move the middle stack on top of that greatest disc, again apply that knowledge.
So indeed, we need to move twice a stack of discs - 1 discs, and make one other move. That gives us that recursive part of the formula.
As to your analysis for 5 discs. You didn't apply the recursion correctly. The (5-1) cannot be evaluated just like that -- it still needs to be expanded into deeper recursion levels. Here is how it should be done:
2 * (
2 * (
2 * (
2 * (
2 * (
0 = 0 (base case)
) + 1 = 1
) + 1 = 3
) + 1 = 7
) + 1 = 15
) + 1 = 31
I'm creating a little game in Javascript, and I have trees that can hold a certain amount of max experience, and each tree have a varied amount of branches that also needs to be leveled up with experience, and they should total to the tree max experience.
If it was that easy, I would just divide them equally, like max / branches, but since it's for a game, I need to make a formula where the first branch needs no experience, and then each branch experience needed steadily increase (while still totalling to the tree max experience).
Branch 1 0 XP
Branch 2 100 XP
Branch 3 200 XP
Branch 4 300 XP
Total Tree Experience Capacity: 600 XP
The amount of branches can be anything from 2 to 10, to 20 and so on, so it must therefor scale with the tree max experience capacity, I believe. How much I want each level to increase with must also depend on how many branches there are, but there should be some kind of pattern across all trees, I think (correct me if it's a bad idea).
The variables that we know are:
The amount of branches we have per tree
Max experience capacity for each tree
The rest is unknown.
How can a formula solve this issue? I also do not mind any functional formulas for specifically JS.
What you seem to want is arithmetic progression. It's a sequence of numbers where there is a common difference between each, for example 1, 4, 7, 10 would be an arithmetic progression where the difference is 3 between each subsequent members.
The more generalised view of arithmetic progression is
a, a + d, a + 2d, a + 3d, ..., a + nd`
Where a is your initial member, d is the difference, and n is the length of the series.
The formula for a sum of arithmetic series is as follows:
S = (n/2) * (2*a + (n - 1)*d)
Which looks complex let's just see it in action. Let's say we want to sum the series 1, 2, 3, 4, 5, 6, 7, 8, 9, 10. Or integers from 1 to 10. Substituting in the formula, we have a = 1, d = 1, n = 10 and we get
S = (10/2) * (2*1 + (10 - 1)*1)
= 5 * (2 + 9*1)
= 5 * (2 + 9)
= 5 * 11
= 55
And we can just write code to verify:
const sum = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10;
console.log(sum);
So, the formula works.
Now, we want to shuffle things - we have S, for the total tree experience capacity, we also have n the number of branches, and we have a which would be zero for the initial branch. We just need to find d in order to get all the things we need. So, here it goes:
S = (n/2) * (2*a + (n - 1)*d)
S / (n/2) = 2*a + (n - 1)*d
(S / (n/2)) - 2*a = (n - 1)*d
((S / (n/2)) - 2*a) / (n - 1) = d
We can actually eliminate 2*a since we know a = 0, so we can slightly simplify the formula:
(S / (n/2)) / (n - 1) = d
And done. We can just encode it in a function now:
// S = totalExperience
// n = branches
function findArithmeticStep(totalExperience, branches) {
return (totalExperience / (branches/2)) / (branches - 1);
}
console.log(findArithmeticStep(600, 4));
You can even use a generator function that will supply you the next XP value:
// S = totalExperience
// n = branches
function findArithmeticStep(totalExperience, branches) {
return (totalExperience / (branches/2)) / (branches - 1);
}
function* nextXPCost(totalExperience, branches) {
const step = findArithmeticStep(totalExperience, branches);
let currentXPCost = 0;
for(let i = 0; i < branches; i++) {
yield currentXPCost;
currentXPCost += step;
}
}
const gen = nextXPCost(600, 4);
//1 - 0
let next = gen.next();
console.log(next.value, next.done);
//2 - 100
next = gen.next();
console.log(next.value, next.done);
//3 - 200
next = gen.next();
console.log(next.value, next.done);
//4 - 300
next = gen.next();
console.log(next.value, next.done);
//5 - getting after the end
next = gen.next();
console.log(next.value, next.done);
//generate an array of all costs
const allCostsTree1 = [...nextXPCost(600, 4)];
console.log(allCostsTree1);
//generate a different tree with higher total cost
const allCostsTree2 = [...nextXPCost(2000, 5)];
console.log(allCostsTree2)
This is what you seek.
Your "rate" increment for each level is based on the summation of all the numbers between "1" and the BRANCH_COUNT-1. There's probably a name in mathematics for this summatation, but I forget it....
It's easily computed with a simple function that takes the total number of branches and the total XP.
// A function that determines the rate by which each branch reward should increment by
function getRate(branch_count, total_xp) {
if (branch_count <= 1) {
return 0;
}
let R = 0;
for (let i = 1; i < branch_count; i++) {
R += i;
}
return total_xp / R;
}
And by recalling some high school match as explained here. The above is can be simplified to just this:
function getRate(branch_count, total_xp) {
if (branch_count <= 1) {
return 0;
}
let R = ((branch_count-1) * (branch_count))/2;
return total_xp / R;
}
And then some sample code using that function to print out the reward structure for each branch
// sample function to print the reward count for each branch
function dumpBranches(branch_count, total_xp) {
let rate = getRate(branch_count, total_xp);
let reward = 0;
for (let i = 0; i < branch_count; i++) {
console.log("Branch ", i, reward);
reward += rate;
}
}
Example:
> dumpBranches(4, 600)
Branch 0 0
Branch 1 100
Branch 2 200
Branch 3 300
> dumpBranches(9, 2700)
Branch 0 0
Branch 1 75
Branch 2 150
Branch 3 225
Branch 4 300
Branch 5 375
Branch 6 450
Branch 7 525
Branch 8 600
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 was wondering to get a random number with two decimal places based on probability for example:
40% to get number from 1-10
20% to get number from 11-20
30% to get number from 21-30
10% to get number from 31-35
function Prob(){
var rnd = Math.random(),
rnd2 = Math.random();
if(rnd<0.4) return (1 + Math.floor(1000 * rnd2)/100);
else if(rnd<0.6) return (11 + Math.floor(1000 * rnd2)/100);
else if(rnd<0.9) return (21 + Math.floor(1000 * rnd2)/100);
else return (31 + Math.floor(500 * rnd2)/100);
}
You need two random numbers, so I calculate them at the start. I then use the if-else loops to cycle through your 40%, 20%, 30% and 10% (adding them up as I go). Note: Math.random returns a number between 0 and 1. Then for each catagory I use the SECOND random number to get in the range you have said - floor it to make sure it is an integer and add the starting number of each range. Note: the range of your last one is just 5.
I should explain, you must use two random numbers, otherwise the range of the second number would be dependent on which category you are in.
I have to do the 1000 * rnd2 in the floor and then divide by 100 outside to get the 2 decimal place you ask for.
Rewind's solution is great and specifically tailored to OP's quesiton. A more re-usable solution might be:
function getNumber(probabilities){
var rnd = Math.random();
var total = 0;
var hit;
for(var i = 0; i < probabilities.length; i++){
if(rnd > total && rnd < total + probabilities[i][0]){
hit = probabilities[i]
}
total += probabilities[i][0];
}
return Number((hit[1] + (Math.random() * (hit[2] - hit[1]))).toFixed(2));
}
var number = getNumber(
[
//chance, min, max
[0.4, 1, 10],
[0.2,11,20],
[0.3,21,30],
[0.1,31,35]
]
);
console.log(number);
The function will take an array with the probabilities, for each probability you specify the chance, the minimum value for that chance, the maximum value for that chance. It will return a number with two decimals.
https://jsfiddle.net/x237w5gv/
I guess this
var get1120 = _ => ~~(Math.random()*10)+11,
get2130 = _ => ~~(Math.random()*10)+21,
get3135 = _ => ~~(Math.random()*5)+31,
a = [get3135,get1120,get1120,get2130,get2130,get2130],
fun;
result = (fun = a[~~(Math.random()*10)]) ? fun() : ~~(Math.random()*10)+1;
console.log(result);
might do it;
Given X=[1,2,3,4,5,6,7,8,9,10] -- but X could be any length(N).
I want to achieve the following:
I want to give the 1st value X[0], the highest probability.
I want to give the 2nd value X[1], a lesser probability than X[0].
I want to give the 3rd value X[2], a lesser probability than X[1].
...
I want to give the Last value X[N], a lesser probability than X[N-1]
All probabilities should sum up to 1.
For clarity with uniform probability distribution(1/(X.length)) looks like this:
{1:0.1, 2:0.1, 3:0.1, 4:0.1, 5:0.1, 6:0.1, 7:0.1, 8:0.1, 9:0.1, 10:0.1,}
If possible solution in javascript would be Great.
You could sum the indices (all values increased by one) and use the sum for calculation the probability.
For a reverse distribution, reverse the probability array.
var add = (a, b) => a + b,
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
sum = data.length * (data.length + 1) / 2,
probability = data.map((_, i) => (i + 1) / sum),
sumProbability = probability.reduce(add, 0);
console.log(probability);
console.log(sumProbability);
Let's probability for the last element is q, for previous element is 2*q, for previous is 3*q ... and for the first one is N*q
q + 2 * q + 3 * q +...+(N-1)*q + N * q = 1
q * Sum(1...N) = 1
q * N * (N + 1) / 2 = 1
q = 2 / (N * (N + 1))
So you can find q for any sequence length and get probabilities for every element.
Example for N = 3
q = 2 / (3 * 4) = 1/6
probabilities:
3/6, 2/6, 1/6 Sum = 1
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