Logic to find the nearest possible sum of array values to target - javascript

This is a simpler version of knapsack, which I am having trouble wrapping my head around.
In my version I don't care how valuable the items are. I just want to get as close to the weight capacity as possible, and order doesn't matter because I'm doing it multiple times and shuffling in between.
So to be clear:
I have an array of values like: weights = [{44, 52, 100, 33, 33, 22, 25, 4, 6, 77, 88, 45}] and a capacity of, for example:capacity: 204
I want the closest combination of array values to that capacity number without repeating any, I'm not super great at math, and the wikipedia article has completely lost me.
Can someone explain how to get this?

Naive approach: cycle through all subsets of N numbers, and check the sum of weights. Running time is O(2^N*N)
You can try dynamic programming.
The problem can be divided into 2 subproblems, to check whether the sum of set is equal to or less than the capacity.
1) Include the current element in subset, and recur for the remaining items with remaining sum.
2) Exclude the current element from the subset, recur remaining items.
The base case of the recursion would be when no items are left. Finally, we output the items included in the subset.
Running time is O(n*capacity) in O(n)

Related

what does '&' do in this solution? [duplicate]

This question already has answers here:
How does '&' work in relation to odd and even? In JS
(3 answers)
Closed last month.
I'm working through a problem on CodeSignal and trying to understand some of the solutions that other people have submitted. One of the solutions was as follows, and I don't understand what the ampersand is doing.
(a) => a.reduce((p,v,i) => (p[i&1]+=v,p), [0,0])
The problem is:
Several people are standing in a row and need to be divided into two teams. The first person goes into team 1, the second goes into team 2, the third goes into team 1 again, the fourth into team 2, and so on.
You are given an array of positive integers - the weights of the people. Return an array of two integers, where the first element is the total weight of team 1, and the second element is the total weight of team 2 after the division is complete.
Example
For a = [50, 60, 60, 45, 70], the output should be
solution(a) = [180, 105].
In this solution, the & operator is used to perform a bitwise AND operation. In JavaScript, the & operator compares each bit of the first operand to the corresponding bit of the second operand. If both bits are 1, the corresponding result bit is set to 1. Otherwise, the corresponding result bit is set to 0.
In the given solution, the & operator is used to determine whether the index i of the current element in the array is even or odd. If i is even, the result of i & 1 will be 0. If i is odd, the result of i & 1 will be 1.

In a space where certain occupied areas are known, how can I see if a given area is unoccupied?

Let's say I have a space ranging from 0-100 and along this space certain areas are occupied. Say 20-30 and 50-70.
Now let's say someone comes along and wants fill spaces 80-90. How would I best check if those spaces are unoccupied?
I could store the free space in nested arrays (which is what I'm currently doing):
[[0, 19], [31, 49], [71, 100]
and the loop an if statement checking if 80-90 will fit in any of these free spaces. This seems very inefficient. Worst case I could be talking thousands of items to loop through.
I could also use an array 100 items long with info on if each number is free:
(100) 0: "free" 1: "free" 2: "free" 3: "free" 4: "free" ...
This way I would not have to loop through multiple items but could just run the if statement on items 80-90 and see if they return free. On the other hand this would mean populating and storing an array with billions (100 is just an example, my use case involves around 1 billion)of items just to find free space.
How would one go about doing this in a better way? Or should I be using these methods I described?
Edit: I am using 0-100 as an example. In my use case, the number is actually around 1 billion.
You could take an array of free ranges and perform a binary search.
This would result in a max iteration of 20 by having a million of items.
2 ** 20 === 1048576

I have an array of objects. I want to randomly output objects whose sum of values ​is equal to eight

const obj =
[
{noir: 1},
{croch: 0.5},
{doubleCroch: 1},
{triollet: 1.5},
{quatreDouble: 2}
];
desired output example:
2, 2, 0.5, 0.5, 1, 2
for (var i = 0 ; i < obj.length ; i++ ){
var randomItem = obj[Math.floor(Math.random()*obj.length )];
}
That brings me five random items. But I want to have elements whose sum of values ​​is equal to eight.
It looks like a condition inside the random
I think you have a couple options here:
1. The foolproof approach
You calculate and collect all the possible combinations that sum up to 8. Then you pick one combination at random. This might be computationally expensive, especially since you seem to allow for duplicates. Not trivial to implement.
2. The happy-go-lucky approach
You keep picking elements at random from your object as you're doing and keep track of the sum. If the sum hits 8, you have a winning combination. If it surpasses 8, you start over from scratch. A lot easier to implement, but might theoretically run infinitely.
3. The over-engineered approach
You start out the same as in the previous approach, but if the sum surpasses 8, you discard the last selected element and pick another one. This would require you to keep track of all the elements you've already tried for every picked element because you might be required to backtrack further than the last selected element. The would be the hardest to implement.

Picking a random item from array with equal distribution

I want to pick a random item from an array at random.
Math.floor(Math.random() * array.length);
Is the way to go, but as far as I know this will cause a Uniform distribution to occur which means that the average is (lowbound+upperbound)/2 translated to an array with 10 elements the lower bound is the first element and the upper bound is the last element causes an average of 5, which is not random
Therefore, I looked at the frequency distribution of this way of random picking an item by having 10 elements and picking one with the code above. The element represents the index and is pushed into an array. After 10000 numbers, the frequency is counted and given.
This has the following results:
Index: Frequency
0: 1083
1: 996
2: 1022
3: 966
4: 958
5: 962
6: 1044
7: 1045
8: 972
9: 952
Ofc, this is only 1 run of 10k numbers. But it shows that index 0 has a 10.8% chance and index 9 has a 9.5% chance. This difference is 1.3% which I find quite a lot.
Are there methods that can do this better? For example, get to 0.05% difference in numbers? The ideal situation would be that they are all 10% (equally distributed).
If you can precompute the result (i.e. you need a finite number of results, not an infinite stream) and the number of results is divisible by the number of items, you can get a perfect distribution:
Generate an array that repeats the items until you've got enough, i.e. [1, 2, 3, 1, 2, 3, 1, 2, 3, ...]. The array is thus guaranteed to have exactly as many instances of each item.
Shuffle the array with a fair shuffle algorithm, e.g. Fisher-Yates. The array still has exactly as many instances of each item.
If you do need an infinite stream, you could use something like an "item bag" model (which, btw, is how the blocks in Tetris are chosen):
Fill a "bag" with your items ([1, 2, 3]). Shuffle it (as above).
When you need an item, pop the first one from the shuffled bag.
If the bag is empty, re-fill it according to step 1.
The only case where this doesn't have a perfect distribution is if you stop "mid-bag".
Here another method - count number of samples already happen, select values from Categorical distribution but with probability INVERSE to the count, thus more frequent item will be less probable to be sampled next time.
Some code (in C#)
import MathNet.Numerics.Distributions;
static void Main() {
const int N = 4;
var counts = new int [N] {1, 1, 1, 1};
var weights = new double [N] {1.0, 1.0, 1.0, 1.0};
while (true) {
int v = Categorical.Sample(weights[k]); // sample one value in [0...N)
// update counts and weights
counts[v] += 1;
weights[v] = 1.0/(double)counts[v];
// use v here for something
...
}
}
Actually, any monotonically growing function of count will do, f.e.
weights[v] = 1.0/(1.0 + .5*(double)counts[v]);
might work, or
var squared => (x) => x*x;
weights[v] = 1.0/(7.0 + .25*squared((double)counts[v]));
or
weights[v] = 1.0/(3.0 + Math.Sqrt((double)counts[v]));
What you have shown in your question is simply the fact that the JavaScript random number generator is simulating not just uniformly distributed, but also independent random numbers; each chosen number behaves as though it were independent of any other choice. Because of this independence, each number "doesn't care" how often each other number was chosen, as long as with each choice, each possible outcome is as likely as any other (according to the JavaScript generator).
If you want a distribution that "feels" more uniform, you will have to adjust the chances of each outcome, so that the chances depend on previous outcomes. A previous answer showed some ways how this can be done. Here is another, which I gave as an answer to a similar question.
Give each item the same weight, specified as a positive integer. For example, give a weight of 20 to each item.
Use a weighted-choice-with-replacement algorithm. Perhaps the simplest is rejection sampling, described as follows. Assume that the highest weight is max and each weight is 0 or greater. To choose an integer in the interval [1, weights.length] using rejection sampling:
Choose a uniform random integer i in [1, weights.length].
With probability weights[i]/max, return i. Otherwise, go to step 1. (For example, if all the weights are integers greater than 0, choose a uniform random integer in [1, max] and if that number is weights[i] or less, return i, or go to step 1 otherwise.)
There are many other ways to make a weighted choice besides rejection sampling; see my note on weighted choice algorithms.
As each item is chosen, reduce its weight by 1 to make it less likely to be chosen.
If all the weights are 0, assign each item the same weight chosen in step 1 (in this example, 20).
You didn't specify the kind of application you had in mind, but I see this desire for a "more uniform" distribution come up most often in games that wish to control which random numbers appear, to make the random outcomes appear "fairer" to players. In that case, however, you should also consider whether it may be better to make an (ordinary) independent uniform random choice instead, especially if you care whether players could gain an unfair advantage by predicting the random outcomes.

Do I need to sort an array to find its median?

I need to create a code where if i for example call func([4, 8, 2, 4, 5]) the method should return the object {max: 8, mean: 4.6, median: 4, min: 2, range: 6}.
Where should I start? Do I need a code for sorting the numbers or is there a code so the computer can find the median without the numbers being sorted first?
You can find a median without sorting the numbers, but that's hard if you want to do that efficiently (for every element count the number of elements less and equal to it, do that till you find element that has correct median count, that means it's in the middle, if number of elements is even then it's even more problematic), plus you can also use sorting for other statistics (max, min etc.) so why not just sort? You can sort array with sort() method.

Categories