Adding numbers with different priorities into a total value that does not exceed the allowable - algorithm

Suppose we have an array of numbers, each number has its own priority and price, the price is the value of the number, how to calculate the sum of a set of these numbers in decreasing order of priority so that the sum does not exceed the allowable one, please tell me at least the name of the algorithm with which it is can be done. Example: there are numbers 2, 3, 9 with priorities 3, 1, 2, respectively. The constraint is 4, therefore the number 9 is cut off immediately, since 9> 4, 2 and 3 we cannot add together, since 5> 3, therefore the choice of 2 numbers is 2 and 3, but since the number 2 has a higher priority, we add only his, this algorithm should work with any number of numbers.

It seems that you are looking for a greedy algorithm:
Order By priority
Scan this ordered collection from the beginning while
Adding item if total meets the constrait(s), skipping if constraint is broken.
In your case:
2, 3, 9 with priorities 3, 1, 2 and a constraint total <= 4
After ordering we have
2, 9, 3
then we scan:
2 take (total == 2 meets the constraint)
9 skip (total == 2 + 9 == 11 > 4 doesn't meet the constraint)
3 skip (total == 2 + 3 == 5 > 4 doesn't meet the constraint)
So far we should take the only 2 item.
Edit: you've dropped 9 since 9 > 4 and that's why 9 can't be in the solution. This process (when we drop items or, on the contrary, take items which are guaranteed to be in the solution) is called Kernelization
In general case when you can skip high priority item in order to take, say, ten low priority items you have Knapsack problem

Related

How do i derive an expression for the worst case number of comparisons needed to merge two sorted arrays of length n/2

merge sort uses divide and conquer approach
The worst case number of comparisons needed to merge two sorted arrays of length 𝑛/2 is 𝑛−1.
This is because when two values have been compared with each other, one of those two values will never be used in a comparison again: it is the value that follows the sorted order... and it is no longer part of the rest of the merge process.
In the worst case, the last comparison will be between the last value of the first array and the last value of the second array. All the other (𝑛−2) values were already excluded from further comparisons, so that means we already did 𝑛−2 comparisons. Now the last one executes, which completes the comparison count to be 𝑛−1.
Example of a worst case input
𝑛 = 10
A = [0, 2, 4, 6, 8]
B = [1, 3, 5, 7, 9]
Comparisons during the merge:
0 1
2 1
2 3
4 3
4 5
6 5
6 7
8 7
8 9
Example of a best case input
Just to put this in perspective, the best case occurs when the last value of the first array is less than the first value of the second array (or vice versa). This only needs 𝑛 / 2 comparisons.
𝑛 = 10
A = [0, 1, 2, 3, 4]
B = [5, 6, 7, 8, 9]
Comparisons during the merge:
0 5
1 5
2 5
3 5
4 5
No more comparisons are now needed, because the first list has no more values; only the values of the second list remain: but they don't need to be compared with anything, and can be appended to the result in the order they currently occur.
Remark
The fact that this process is used as part of merge sort -- implementing a divide and conquer algorithm -- is just background info. Merging two sorted lists can be needed in other contexts that do not relate to merge sort.

Random triplet number generator

I would like to create code for a random number generator for predetermined sets of triplets (200 sets in total to randomize). I would like the sets of triplets to form a set of six numbers and the set of triplets to remain unique.
example triplets A = [1 2 3; 4 5 6; 7 8 9, 10 11 12, 13 14 15]; etc
I would like resulting triplet to retain their original sequence
1 2 3 + 4 5 6, 1 2 3 + 7 8 9, 1 2 3 + 10 11 12, 1 2 3 + 13 14 15
I am not a coder, so any help would be appreciated
You want to pick three triplets, keeping them in order. So your first triplet cannot be too close to the end -- there have to be at least two more triplets after it. Similarly, the second triplet you pick needs at least one unpicked triplet after it.
I assume that you have your triplets in an array or similar, numbered 0 to 199.
Pick a random number A in the range 0 to 197. That is the index of your first triplet.
Pick a second random number B in the range (A + 1) to 198. That is the index of your second triplet.
Pick a third random number C in the range (B + 1) to 199. That is the index of your third triplet.
The range of random numbers you pick from is affected by the numbers you have previously picked and the number of picks remaining.

Efficient algorithm for finding the right elements combinations

The problem is the following:
1) Total load is given as input
2) Number of steps over which the load is divided is also given as input
3) Each step can have different discrete number of elements, which is multiple of 3 for example (i.e. 3, 6, 9, 12, 15 elements ...).
4) Elements are given as input.
5) Acceptable solutions are within a certain range "EPSILON" from the total load (equal to total load or greater but within certain margin, for example up to +2)
Example:
Total load: 50
Number of steps: 4
Allowed elements that can be used are: 0.5, 1, 1.5, 2.5, 3, 4
Acceptable margin: +2 (i.e. total load between 50 and 52).
Example of solutions are:
For simplicity here, each step has uniform elements, although we can have different elements in the same step (but should be grouped into 3, i.e. we can have 3 elements of 1, and 3 other elements of 2, in the same step, so total of 9).
Solution 1: total of 51
Step 1: 3 Elements of 4 (So total of 12), (this step can be for example 3 elements of 3, and 3 elements of 1, i.e. 3 x 3 + 3 x 1).
Step 2: 3 Elements of 4 (total of 12),
Step 3: 9 Elements of 1.5 (total of 13.5),
Step 4: 9 Elements of 1.5 (total of 13.5),
Solution 2: total of 51
Step 1: 3 Elements of 4 (total of 12)
Step 2: 3 Elements of 4 (total of 12)
Step 3: 6 Elements of 2 (total of 12)
Step 4: 15 Elements of 1 (total of 15)
The code that I used takes the above input, and writes another code depending on the number of steps.
The second code basically loops over the number of steps (loops inside each other's) and checks for all the possible elements combinations.
Example of loops for 2 steps solution:
Code:
For NumberofElementsA = 3 To 18 Step 3
'''''18 here is the maximum number of elements per step, since I cannot let it go to infinity, so I need to define a maximum for elemnt
For NumberofElementsB = 3 To 18 Step 3
For AllowedElementsA = 1 To 6
For AllowedElementsB = AllowedElementsA To 6
''''Allowed elements in this example were 6: [0.5, 1, 1.5, 2.5, 3, 4]
LoadDifference = -TotalLoad + NumberofElementsA * ElementsArray(AllowedElementsA) + NumberofElementsB * ElementsArray(AllowedElementsB)
''''basically it just multiplies the number of elements (here 3, 6, 9, ... to 18) to the value of the element (0.5, 1, 1.5, 2.5, 3, 4) in each loop and subtracts the total load.
If LoadDifference <= 2 And LoadDifference >= 0
'''Solution OK
End If
Next AllowedElementsB
Next AllowedElementsA
Next NumberofElementsB
Next NumberofElementsA
So basically the code loops over all the possible number of elements and possible elements values, and checks each result.
Is there an algorithm that solves in a more efficient way the above problem ? Other than looping over all possible outcomes.
Since you're restricted to groups of 3, this transforms immediately to a problem with all weights tripled:
1.5, 3, 4.5, 7.5, 9, 12
Your range is a target value +2, or within 1 either way from the midpoint of that range (51 +- 1).
Since you've listed no requirement on balancing step loads, this is now an instance of the target sum problem -- with a little processing before and after the central solution.

Find the number of non-decreasing and non-increasing subsequences in an array

I am attempting to complete a programming challenge from Quora on HackerRank: https://www.hackerrank.com/contests/quora-haqathon/challenges/upvotes
I have designed a solution that works with some test cases, however, for many the algorithm that I am using is incorrect.
Rather than seeking a solution, I am simply asking for an explanation to how the subsequence is created and then I will implement a solution myself.
For example, with the input:
6 6
5 5 4 1 8 7
the correct output is -5, but I fail to see how -5 is the answer. The subsequence would be [5 5 4 1 8 7] and I cannot for the life of me find a means to get -5 as the output.
Problem Statement
At Quora, we have aggregate graphs that track the number of upvotes we get each day.
As we looked at patterns across windows of certain sizes, we thought about ways to track trends such as non-decreasing and non-increasing subranges as efficiently as possible.
For this problem, you are given N days of upvote count data, and a fixed window size K. For each window of K days, from left to right, find the number of non-decreasing subranges within the window minus the number of non-increasing subranges within the window.
A window of days is defined as contiguous range of days. Thus, there are exactly N−K+1 windows where this metric needs to be computed. A non-decreasing subrange is defined as a contiguous range of indices [a,b], a<b, where each element is at least as large as the previous element. A non-increasing subrange is similarly defined, except each element is at least as large as the next. There are up to K(K−1)/2 of these respective subranges within a window, so the metric is bounded by [−K(K−1)/2,K(K−1)/2].
Constraints
1≤N≤100,000 days
1≤K≤N days
Input Format
Line 1: Two integers, N and K
Line 2: N positive integers of upvote counts, each integer less than or equal to 10^9
Output Format
Line 1..: N−K+1 integers, one integer for each window's result on each line
Sample Input
5 3
1 2 3 1 1
Sample Output
3
0
-2
Explanation
For the first window of [1, 2, 3], there are 3 non-decreasing subranges and 0 non-increasing, so the answer is 3. For the second window of [2, 3, 1], there is 1 non-decreasing subrange and 1 non-increasing, so the answer is 0. For the third window of [3, 1, 1], there is 1 non-decreasing subrange and 3 non-increasing, so the answer is -2.
Given a window size of 6, and the sequence
5 5 4 1 8 7
the non-decreasing subsequences are
5 5
1 8
and the non-increasing subsequences are
5 5
5 4
4 1
8 7
5 5 4
5 4 1
5 5 4 1
So that's +2 for the non-decreasing subsequences and -7 for the non-increasing subsequences, giving -5 as the final answer.

Amount of "jumping" numbers from 101 to 10^60? [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
Let's say number is "ascending" if its digits are going in ascending order. Example: 1223469. Digits of "descending" number go in descending order. Example: 9844300. Numbers that are not "ascending" or "descending", are called "jumping". Numbers from 1 to 100 are not "jumping". How many "jumping" numbers are there from 101 to 10^60?
Here is an idea: instead of counting the jumping numbers, count the ascending and descending ones. Then subtract them from all the numbers.
Counting the ascending/descending ones should be easy - you can use a dynamic programming based on the number of digits left to generate, and the digit you have placed in the last position.
I'll describe how to count the ascending numbers, because that's easier. Going from that, you could also count the descending ones and then subtract the combined amount from the total amount of numbers, compensating for duplicates, as indicated by Ivan, or devise a more complex way to only count jumping numbers directly.
A different approach
Think about the numbers sorted by ending digit. We start with numbers that are 1 digit long, this will be our list
1 // Amount of numbers ending with 1
1 // Amount of numbers ending with 2
1 // Amount of numbers ending with 3
1 // Amount of numbers ending with 4
1 // Amount of numbers ending with 5
1 // Amount of numbers ending with 6
1 // Amount of numbers ending with 7
1 // Amount of numbers ending with 8
1 // Amount of numbers ending with 9
To construct numbers with two digits ending with 6, we can use all numbers ending with 6 or less
1 // Amount of numbers ending with 1 with 2 digits
2 // Amount of numbers ending with 2 with 2 digits
3 // Amount of numbers ending with 3 with 2 digits
4 // Amount of numbers ending with 4 with 2 digits
5 // Amount of numbers ending with 5 with 2 digits
6 // Amount of numbers ending with 6 with 2 digits
7 // Amount of numbers ending with 7 with 2 digits
8 // Amount of numbers ending with 8 with 2 digits
9 // Amount of numbers ending with 9 with 2 digits
Writing these side by side, can see how to calculate the new values very quickly:
y a // y, a, and x have been computed previously
x (a + x)
1 1 1 1
1 2 3 4
1 3 6 10
1 4 10 20
1 5 15 35
1 6 21 56
1 7 28 84
1 8 36 120
1 9 45 165
A simple Python program
Iterating over one such column, we can directly produce all values of the new column, if we always remember the last computation. The scan() function abstracts away exactly that behavior of taking one element, and do some computation with it and the last result.
def scan(f, state, it):
for x in it:
state = f(state, x)
yield state
Producing the next column is now as simple as:
new_column = list(scan(operator.add, 0, column))
To make it simple, we use single digit numbers as starting point:
first_row = [1]*9
Seeing that we always need to feed back the new row to the function, can use scan again to do just that:
def next_row(row):
return list(scan(operator.add, 0, column))
def next_row_wrapper(row, _):
return next_row(row)
>>> [list(x) for x in scan(next_row_wrapper, [1]*9, range(3))] # 3 iterations
[[1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 3, 6, 10, 15, 21, 28, 36, 45], [1, 4, 10, 20, 35, 56, 84, 120, 165]]
As you can see, this gives the first three row apart from the first one.
Since we want to know the sum, of all numbers, we can do just that. When we do 1 iteration, we get all ascending numbers until 10^2, so we need to do 59 iterations for all numbers until 10^60:
>>> sum(sum(x) for x in scan(lambda x, _: next_row(x), [1]*9, range(59))) + 10
56672074888L
For the descending numbers, it's quite similar:
>>> sum(sum(x) for x in scan(lambda x, _: next_row(x), [1]*10, range(59))) + 10 - 58
396704524157L<
Old approach
Think about how the numbers end:
From 10 to 99, we have two digits per number.
There are
1 that ends in 1
2 that end in 2
3 that end in 3
4 that end in 4
5 that end in 5
6 that end in 6
7 that end in 7
8 that end in 8
9 that end in 9
All of these numbers act as prefixes for numbers from 100 to 999.
An example, there are three numbers that end in 3:
13
23
33
For each of these three numbers, we can create seven ascending numbers:
133
134
135
136
137
138
139
It is easy to see, that this adds three numbers for each of the seven possible ending digits.
If we wanted to extend numbers ending on 4, the process would be similar: Currently, there are 4 numbers ending on 4. Thus, for each such number, we can create 6 new ascending numbers. That means, that there will be an additional 4 for all of the six possible ending digits.
If you have understood everything I've written here, it should be easy to generalize that and implement an algorithm to count all those numbers.
Non-jumping numbers:
69 choose 9 (ascending numbers of size ≤ 60)
+ 70 choose 10 - 60 (descending numbers of size ≤ 60)
- 60 * 9 (double count: all digits the same)
- 1 (double count: zero)
= 453376598563
(To get jumping numbers, subtract from total numbers: 1060)
Simple python program to compute the number:
# I know Python doesn't do tail call elimination, but it's a good habit.
def choose(n, k, num=1, denom=1):
return num/denom if k == 0 else choose(n-1, k-1, num*n, denom*k)
def f(digits, base=10):
return choose(digits+base-1, base-1) + choose(digits+base, base) - digits*base - 1
Ascending numbers: select 9 positions to increment the digit, starting with 0.
Descending numbers: pretend we have a digit 10 which is used to left-pad the number. Then select 10 positions to decrement the digit, starting with 10. Then remove all the choices where the 10 selected positions are consecutive and not at the end, which would correspond to digit sequences with a leading 0.
Since all numbers whose digits are all the same will be produced by both descending and ascending algorithms, we have to subtract them.
Note that all of these algorithms consider the number 0 to be written with no digits at all. Also, all numbers ≤ 100 are either ascending or descending (or both), so there's no need to worry about them.
Do you count 321 as descending or do you count 000000321 as jumping?
Hint for the answer: the number of ascending numbers with 59 digits will be something like (69 choose 10) because you have to choose which points in the number are between differing digits.

Resources