Find optimal combination of elements from two arrays for a total of five elements - combinations

I have two arrays array_a and array_b.
Each array can have anywhere between zero and infinite number of elements, but I need to select just a total of 5 from both.
Optimal combination is 3 from array_a and 2 from array_b.
If the total in either arrays is less than its optimal number, it should be compensated from the other array (e.g. 4 from array_a and 1 from array_b) to make up a total of 5.
Given that I know total number of elements in both arrays, what's the most efficient way of calculating the optimal combination?
My pseudo-code solution in Python is the following, but I have a feeling it can be done even more efficiently:
source_a_count = array_a.len()
source_b_count = array_b.len()
if source_a_count =< 3
source_b_count = 5 - source_a_count
else if source_b_count =< 2
source_a_count = 5 - source_b_count
else
source_a_count = 3
source_b_count = 2

Surely you can reduce if-else statements.
source_a_count = 3
source_b_count = 2
if array_a.len() < 3
source_a_count = array_a.len()
source_b_count = 5 - source_a_count
else if array_b.len() < 2
source_b_count = array_b.len()
source_a_count = 5 - source_b_count

Related

What is the maximum number of comparisons to heapify an array?

Is there a general formula to calculate the maximum number of comparisons to heapify n elements?
If not, is 13 the max number of comparisons to heapify an array of 8 elements?
My reasoning is as such:
at h = 0, 1 node, 0 comparisons, 1* 0 = 0 comparisons
at h = 1, 2 nodes, 1 comparison each, 2*1 = 2 comparisons
at h = 2, 4 nodes, 2 comparisons each, 4*2 = 8 comparisons
at h = 3, 1 node, 3 comparisons each, 1*3 = 3 comparisons
Total = 0 + 2 + 8 + 3 =13
Accepted theory is that build-heap requires at most (2N - 2) comparisons. So the maximum number of comparisons required should be 14. We can confirm that easily enough by examining a heap of 8 elements:
7
/ \
3 1
/ \ / \
5 4 8 2
/
6
Here, the 4 leaf nodes will never move down. The nodes 5 and 1 can move down 1 level. 3 could move down two levels. And 7 could move down 3 levels. So the maximum number of level moves is:
(0*4)+(1*2)+(2*1)+(3*1) = 7
Every level move requires 2 comparisons, so the maximum number of comparisons would be 14.

How to count the number of permutations?

We are given array-'a' and array-'b' consisting of positive integers.
How can I count all the permutation of array 'a' which are strictly lexicographically smaller than array-'b'?
Arrays can contain as many as 10^5 integers(positive)
Example:
1 2 3 is lexicographically smaller than 3 1 2
1 2 3 is lexicographically smaller than 1 4 5.
I would like the solution to be in C++.
Input : 3
1 2 3
2 1 3
Output : 2
Only permutations 1,2,3 and 1,3,2 are lexicographically smaller than 2 1 3
Let's just tackle the algorithm. Once you get that figured out, the implementation should be pretty straightforward. Does this look like it does what you're looking for?
Pseudo code:
function get_perms(a,b)
#count the number of digits in a that are <b[0]
count = sum(a<b[0])
Nperms = (len(a)-1)! #modify this formula as needed
N = count*Nperms
if sum(a==b[0]) > 0
remove 1 b[0] from a
# repeat the process with the substring assuming a[0]==b[0]
N += sum(a==b[0])*get_perms(a,b[1:end])
return N
main()
get_perms(a,b)
Edit: I did a little searching. I believe that this is what you are looking for.

iterate over Dataframe row by index value and find max

I need to iterate over df rows based on its index. I need to find the max in the column p1 and fill it in the output dataframe (along with the max p1), the same for the column p2. In each range of my row indexes (sub_1_ica_1---> sub_1_ica_n), there must be only one 1 and one 2 and I need to fill the remaining with zeros. That's why I need to do the operation range by range.
I tried to split the index name and make a counter for each subject to be used to iterate over the rows, but I feel that I am in the wrong way!
from collections import Counter
a = df.id.tolist()
indlist = []
for x in a:
i = x.split('_')
b = int(i[1])
indlist.insert(-1,b)
c=Counter(indlist)
keyInd = c.keys()
Any ideas?
EDIT: according to Jerazel example my desired output would look like this.
First I find the max for p1 and p2 columns which will be translated in the new df into 1 and 2, and the remaining fields will be zeros
I think you need numpy.argmax with max, also if need columns names use idxmax:
idx = ['sub_1_ICA_0','sub_1_ICA_1','sub_1_ICA_2','sub_2_ICA_0','sub_2_ICA_1','sub_2_ICA_2']
df = pd.DataFrame({'p0':[7,8,9,4,2,3],
'p1':[1,3,5,7,1,0],
'p2':[5,9,6,1,2,4]}, index=idx)
print (df)
cols = ['p0','p1','p2']
df['a'] = df[cols].values.argmax(axis=1)
df['b'] = df[cols].max(axis=1)
df['c'] = df[cols].idxmax(axis=1)
print (df)
p0 p1 p2 a b c
sub_1_ICA_0 7 1 5 0 7 p0
sub_1_ICA_1 8 3 9 2 9 p2
sub_1_ICA_2 9 5 6 0 9 p0
sub_2_ICA_0 4 7 1 1 7 p1
sub_2_ICA_1 2 1 2 0 2 p0
sub_2_ICA_2 3 0 4 2 4 p2

how to write a diamond shape only with nested for loops [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Alright so I'm new to for nested loops and having a hard time understanding them.
The prompt:
Write a program that prints the shape shown below. You may use output statements that print either a single asterisk (*) or a single blank. Maximize your use of repetition (with nested for structures) and minimize the number of output statements.
*******
*********
***********
*************
***********
*********
*******
What I have so far:
for (int row = 7; row <= 13; row = row + 2){
for (int col = 1; col <= row; col++)
cout << '*';
cout << '\n';
}
for ( int row = 12; row >= 7; row = row - 2) {
for ( int col = 1; col <= row; col++ )
cout << '*';
cout << '\n';
}
I can't figure out the spacing? The spaces go down by one for the first three lines and up by one for the next three lines. How should I add them in?
You are on the right track. The hardest part with this kind of assignments is to figure out the 'rule' or the formula for the amount of blanks and amount of stars in each row based on the index of the row. Once you have that figured out translating that into a program is the easier part.
EDIT: Even though this explanation uses a specific assignment as the example it is a general approach and, if learned, it should help you and others with this kind of programming problems.
You can make it easier by marking the rows with their index
0 *******
1 *********
2 ***********
3 *************
4 ***********
5 *********
6 *******
And then make an input - output table
row blanks *s
0 6 7
1 5 9
2 4 11
3 3 13
4 4 11
5 5 9
6 6 7
This table can be expanded (generalized) to any number of rows from 1 to N (N>=1), but it's really for N>=3 that it starts to make sense. Sometimes a decision should be made how even and odd values for N are handled, but that is usually possible to figure out from the samples that you are provided.
In your example the number of rows is 7 so N=7.
By knowing your input N you can start generalizing the above table by replacing values with calculations (as functions of N)
N=7
row blanks *s
0 N-1 N+0
1 N-2 N+2
2 N-3 N+4
3 N-4 N+6
4 N-3 N+4
5 N-2 N+2
6 N-1 N+0
At this point if you can't determine a single formula for all rows yet just introduce new helper variables. We can see that in the top half of the table we see increasing correction values (+0, +2, +4, +6) and in the bottom half of the table we see decreasing correction values (+6, +4, +2, +0). So let's introduce a helper variable that will help us with the bottom half of the table (similar to how the row index helps us with the top half). I will call this variable help1.
N=7
row help1 blanks *s
0 6 N-1 N+0
1 5 N-2 N+2
2 4 N-3 N+4
3 3 N-4 N+6
4 2 N-3 N+4
5 1 N-2 N+2
6 0 N-1 N+0
At this point if the pattern is still too hard to generalize you could just split the problem in 2 cases and use an if {} else {} statement in your program. One for the top half of the table (if part) and one for the bottom half (else part). However, if you look closely at the relation between row and help1 variables and the correction values for blanks and asterisks you can see that they follow a pattern. There is a linear relation between them. You can see that you always need to subtract or add the smaller value of row and help1 to get the desired number of blanks or asterisks for a given row. So let's introduce a new helper for the smaller value also called minimum or min for short.
row help1 min blanks *s
0 6 0 N-1 N+0
1 5 1 N-2 N+2
2 4 2 N-3 N+4
3 3 3 N-4 N+6
4 2 2 N-3 N+4
5 1 1 N-2 N+2
6 0 0 N-1 N+0
And now let's use the min helper variable to update the last 2 columns of the table as well.
row help1 min blanks *s
0 6 0 N-(min+1) N+2*min
1 5 1 N-(min+1) N+2*min
2 4 2 N-(min+1) N+2*min
3 3 3 N-(min+1) N+2*min
4 2 2 N-(min+1) N+2*min
5 1 1 N-(min+1) N+2*min
6 0 0 N-(min+1) N+2*min
And the table is fully generalized.
The hint from the assignment is to use nested structures (nested loops). The general idea would be to use an outer loop to iterate over the rows from 0 to N-1 and an inner loop (or two) to print the required amount of blanks and asterisks for the current row.
Now it's up to you to figure out the loop conditions and steps/increments and the calculations of the helper variables help1 and min.

Downscale array for decimal factor

Is there efficient way to downscale number of elements in array by decimal factor?
I want to downsize elements from one array by certain factor.
Example:
If I have 10 elements and need to scale down by factor 2.
1 2 3 4 5 6 7 8 9 10
scaled to
1.5 3.5 5.5 7.5 9.5
Grouping 2 by 2 and use arithmetic mean.
My problem is what if I need to downsize array with 10 elements to 6 elements? In theory I should group 1.6 elements and find their arithmetic mean, but how to do that?
Before suggesting a solution, let's define "downsize" in a more formal way. I would suggest this definition:
Downsizing starts with an array a[N] and produces an array b[M] such that the following is true:
M <= N - otherwise it would be upsizing, not downsizing
SUM(b) = (M/N) * SUM(a) - The sum is reduced proportionally to the number of elements
Elements of a participate in computation of b in the order of their occurrence in a
Let's consider your example of downsizing 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 to six elements. The total for your array is 55, so the total for the new array would be (6/10)*55 = 33. We can achieve this total in two steps:
Walk the array a totaling its elements until we've reached the integer part of N/M fraction (it must be an improper fraction by rule 1 above)
Let's say that a[i] was the last element of a that we could take as a whole in the current iteration. Take the fraction of a[i+1] equal to the fractional part of N/M
Continue to the next number starting with the remaining fraction of a[i+1]
Once you are done, your array b would contain M numbers totaling to SUM(a). Walk the array once more, and scale the result by N/M.
Here is how it works with your example:
b[0] = a[0] + (2/3)*a[1] = 2.33333
b[1] = (1/3)*a[1] + a[2] + (1/3)*a[3] = 5
b[2] = (2/3)*a[3] + a[4] = 7.66666
b[3] = a[5] + (2/3)*a[6] = 10.6666
b[4] = (1/3)*a[6] + a[7] + (1/3)*a[8] = 13.3333
b[5] = (2/3)*a[8] + a[9] = 16
--------
Total = 55
Scaling down by 6/10 produces the final result:
1.4 3 4.6 6.4 8 9.6 (Total = 33)
Here is a simple implementation in C++:
double need = ((double)a.size()) / b.size();
double have = 0;
size_t pos = 0;
for (size_t i = 0 ; i != a.size() ; i++) {
if (need >= have+1) {
b[pos] += a[i];
have++;
} else {
double frac = (need-have); // frac is less than 1 because of the "if" condition
b[pos++] += frac * a[i]; // frac of a[i] goes to current element of b
have = 1 - frac;
b[pos] += have * a[i]; // (1-frac) of a[i] goes to the next position of b
}
}
for (size_t i = 0 ; i != b.size() ; i++) {
b[i] /= need;
}
Demo.
You will need to resort to some form of interpolation, as the number of elements to average isn't integer.
You can consider computing the prefix sum of the array, i.e.
0 1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9 10
yields by summation
0 1 2 3 4 5 6 7 8 9
1 3 6 10 15 21 28 36 45 55
Then perform linear interpolation to get the intermediate values that you are lacking, like at 0*, 10/6, 20/6, 30/5*, 40/6, 50/6, 60/6*. (Those with an asterisk are readily available).
0 1 10/6 2 3 20/6 4 5 6 40/6 7 8 50/6 9
1 3 15/3 6 10 35/3 15 21 28 100/3 36 45 145/3 55
Now you get fractional sums by subtracting values in pairs. The first average is
(15/3-1)/(10/6) = 12/5
I can't think of anything in the C++ library that will crank out something like this, all fully cooked and ready to go.
So you'll have to, pretty much, roll up your sleeves and go to work. At this point, the question of what's the "efficient" way of doing it boils down to its very basics. Which means:
1) Calculate how big the output array should be. Based on the description of the issue, you should be able to make that calculation even before looking at the values in the input array. You know the input array's size(), you can calculate the size() of the destination array.
2) So, you resize() the destination array up front. Now, you no longer need to worry about the time wasted in growing the size of the dynamic output array, incrementally, as you go through the input array, making your calculations.
3) So what's left is the actual work: iterating over the input array, and calculating the downsized values.
auto b=input_array.begin();
auto e=input_array.end();
auto p=output_array.begin();
Don't see many other options here, besides brute force iteration and calculations. Iterate from b to e, getting your samples, calculating each downsized value, and saving the resulting value into *p++.