ZIO 2013: Dolls - algorithm

Your shop sells several different types of dolls. Each doll has a suggested price, and no
two types of doll have the same price. You would like to fix an actual selling price for
each doll so that dolls of different types are as different in price as possible. Due to
some government regulations, you can only modify the suggested price within a fixed
band of ±K—in other words, if the suggested price is p, you can pick any selling price
in the range {p− K, p− K + 1, . . . , p+ K −1, p+ K}. Of course, the selling price must
always be non-negative.
For instance, suppose there are four types of dolls with suggested prices 130, 210, 70
and 90 and you are allowed to modify prices within a band of 20. Then, you can adjust
the prices to 150, 210, 50 and 100, respectively, so that the minimum difference in price
between any two types of dolls is 50. (For the second doll, you could have picked any
price between 200 and 230.) You can check that this is the largest separation that you
can achieve given the constraint.
In each of the cases below, you are given a sequence of prices and the value of K. You
have to determine the maximum separation that you can achieve between all pairs in
the sequence if you are allowed to modify each price by upto ±K.
(a) K = 13. Sequence: 144, 152, 214, 72, 256, 3, 39, 117, 238, 280.
(b) K = 10. Sequence: 10, 48, 57, 32, 61, 74, 33, 45, 99, 81, 19, 24, 101.
(c) K = 20. Sequence: 10, 19, 154, 67, 83, 39, 54, 110, 124, 99, 139, 170
So basically, I just need to find the value of maximum separation without coding. I tried to devise an algorithm, but failed miserably, so I just started brute forcing it, by basically increasing/decreasing each of the prices by a certain value, but the bruteforcing applied here is just too tough due to the value of K. (It would have been simple for any K<6).
Can someone define a function or recurrence relation to calculate it? The solutions are up online, but they only give the answer as an integer and don't explain how to reach the solution. I am a beginner in programming, so try explaining using pseudocode/ little bit of C++, please. Thank you.
Source: http://www.iarcs.org.in/inoi/2013/zio2013/zio2013-qpaper.pdf
Solution: http://www.iarcs.org.in/inoi/2013/zio2013/zio2013-solutions.pdf

Here is a O(nlogn) algorithm.
To illustrate I will use the second example: 10, 48, 57, 32, 61, 74, 33, 45, 99, 81, 19, 24, 101 with K=10
Sort the list (10, 19, 24, 32, 33, 45, 48, 57, 61, 74, 81, 99, 101)
Use bisection to find the minimum separation x
For a trial value of x, assign the final values greedily placing them as small as possible while satisfying the conditions (non-negative, within K of original value, at least x greater than previous).
So let us start with x=10.
We will move as follows:
10->0 (can't go negative so this is smallest allowed)
19->10 (can't go within K=10 of the previous value)
24->20
32->30
33->40
45->50
48 becomes impossible. We can only assign values between 38 and 58, but none of these are more than 10 away from the previous 50.
We conclude that x=10 is too high a separation and we need to move lower.
You might try x=7 and find it is possible, x=9 find it is impossible, then try x=8:
10->0
19->9 (can only move to values 9->29)
24->17
32->25
33->33
45->41
48->49
57->56
61->64
74->72
81->80
99->89
101->97
And so we have found that x=8 is possible, x=9 is impossible and therefore x=8 is the maximum possible separation.

Related

Exact orthogonalization of vectors in Wolfram

What I have is a matrix, I need to orthogonolize its eigen vectors.
That is basically all I need, but in exact form.
So here is my wolfram input
(orthogonolize(eigenvectors({{146, 112, 78, 17, 122}, {112, 86, 60, 13, 94}, {78, 60, 42 , 9, 66}, {17, 13, 9, 2, 14}, {122, 94, 66, 14, 104}})))
That gives me float numbers, while I need the exact forms.
Any ways to fix this?
Wolfram Mathematica, not WolframAlpha which is a completely different product with different rules and gives different results, given this
FullSimplify[Orthogonalize[Eigenvectors[{
{146, 112, 78, 17, 122}, {112, 86, 60, 13, 94}, {78, 60, 42 , 9, 66},
{17, 13, 9, 2, 14}, {122, 94, 66, 14, 104}}]]]
returns this exact form
{{Sqrt[121/342 + 52/(9*Sqrt[35587])], Sqrt[5/38 + 18/Sqrt[35587]],
Sqrt[25/342 + 64/(9*Sqrt[35587])], Sqrt[7/38 - 26/Sqrt[35587]]/3,
2*Sqrt[2/19 - 7/Sqrt[35587]]},
{-1/3*Sqrt[121/38 - 52/Sqrt[35587]], -Sqrt[5/38 - 18/Sqrt[35587]],
Sqrt[25/38 - 64/Sqrt[35587]]/3, -1/3*Sqrt[7/38 + 26/Sqrt[35587]],
Sqrt[8/19 + 28/Sqrt[35587]]},
{3/Sqrt[35], -Sqrt[5/7], 0, 0, 1/Sqrt[35]},
{-11/Sqrt[5110], -Sqrt[5/1022], 0, Sqrt[70/73], 4*Sqrt[2/2555]},
{-17/(3*Sqrt[2774]), -7/Sqrt[2774], Sqrt[146/19]/3, Sqrt[2/1387]/3, -9*Sqrt[2/1387]}}
Think of at least two different ways you can check that for correctness before you depend on that.
The last three of those can be simplified somewhat
1/Sqrt[35]*{3,-5,0,0,1},
1/Sqrt[5110]*{-11,-5,0,70,8},
1/(3*Sqrt[2774])*{-17,-21,146,2,-54}
but I cannot yet see a way to simplify the first two to a third of their current size. Can anyone else see a way to do that? Please check these results very carefully.

Search algorithm with best Time Complexity [duplicate]

This question already has answers here:
How do I search for a number in a 2d array sorted left to right and top to bottom?
(21 answers)
Closed 4 years ago.
Given the following data:
[4]
[5, 8]
[9, 12, 20]
[10, 15, 23, 28]
[14, 19, 31, 36, 48]
[15, 22, 34, 41, 53, 60]
[19, 26, 42, 49, 65, 72, 88]
[20, 29, 45, 54, 70, 79, 95, 104]
[24, 33, 53, 62, 82, 91, 111, 120, 140]
[25, 36, 56, 67, 87, 98, 118, 129, 149, 160]
[29, 40, 64, 75, 99, 110, 134, 145, 169, 180, 204]
[30, 43, 67, 80, 104, 117, 141, 154, 178, 191, 215, 228]
[34, 47, 75, 88, 116, 129, 157, 170, 198, 211, 239, 252, 280]
[35, 50, 78, 93, 121, 136, 164, 179, 207, 222, 250, 265, 293, 308]
[Etc.]
What could be the best searching algorithm with the most optimal Time Complexity for finding a given number?
The rows are sorted
The columns are sorted
A number may occur more than once
Extra info:
Suppose we are looking for the number 26:
Due to order, this means we can eliminate the first 3 rows and the remaining columns to the right.
Due to order, this also means we can ignore every row after row=11.
Which results to this:
[10, 15, 23]
[14, 19, 31]
[15, 22, 34]
[19, 26, 42]
[20, 29, 45]
[24, 33, 53]
[25, 36, 56]
[29, 40, 64]
My current algorithm has a time complexity of O(x log(y)) where x is the amount of columns and y is the size for the Binary Search algorithm for each column.
I'm looking for something faster because I'm dealing with huge amount of data.
Currently I'm using BST on every column, but could I use BST on rows aswell? maybe achieving a O(log(x) log(y))?
It can be done in O(x)
Let's call the element we are trying to find n
Start with the bottom left element.
For each element we search through (let's call it e):
if e == n: we found it
if e < n: move to the right
Justification:
All elements to the left of e, including the column that e is in, are less than e. Those elements cannot == n and can be eliminated.
if e > n: move up
Justification:
All elements below e are greater than e and can be eliminated. What about the values less than e to the left of e? Can't those be == n? No. For e to make those moves to the right and have values to it's left, those values would have been already eliminated in step 2
Repeat until n found or index out of bounds in which case such an element does not exist.
Time complexity:
The worst case scenario is if the element isn't in the array and we have an index out of bounds. This occurs at the main diagonal and the total distance to the right and total distance up to any element on the long diagonal always sums to x.
You can find the bottom left of your trimmed array with a binary search of the first column, and the top right with a binary search of the last column of each row.
From there, the problem degenerates to How do I search for a number in a 2d array sorted left to right and top to bottom? which is well-studied in the linked question. The best algorithm is dependent on the shape of the result.

introduction to algorithms CLRS insertion sort nonincreasing

I am currently on the second chapter of Introduction to algorithms by CLRS, and I've come across a strange exercise. It asks me to sort the insertion sort so that is nonincreasing instead of nondecreasing.
So I presume that for a given array A = { 91, 23, 24 ,54, 23} this would turn out as this { 23, 23, 24, 54, 91} for nondecreasing.
However, if it is nonincreasing does that mean it would turn out like this? { 91, 54, 24, 23, 23}? I searched around on the internet and am asking this out of curiosity and for clarification. Thanks in advance.
An array is sorted in non-increasing order if every element (starting from the second one) is less than or equal to the previous one.
So the array {91, 23, 24 ,54, 23} sorted in non-increasing order is indeed {91, 54, 24, 23, 23}.
yes, nonincreasing array is an order that doesn't increase, but it may or may not decrease (Just not increase).

Efficient way to figure out which bit is set in a 64 bit quantity

This is effectively log base 2, but I do not have access to this functionality in the environment I'm in. Manually walking through the bits to verify them is unacceptably slow. If it were just 4 bits, I could probably index it and waste some space in an array, but with 64 bits it is not viable.
Any clever constant time method to find which bit is set ? (The quantity is a 64-bit number).
EDIT: To clarify, there is a single bit set in the number.
I assume you want the position of the most significant bit that is set. Do a binary search. If the entire value is 0, no bits are set. If the top 32 bits are 0, then the bit is in the bottom 32 bits; else it is in the high half. Then recurse on the two 16-bit halves of the appropriate 32 bits. Recurse until you are down to a 4-bit value and use your look-up table. (Or recurse down to a 1-bit value.) You just need to keep track of which half you used at each recursion level.
The fastest method I know of uses a DeBruijn Sequence.
Find the log base 2 of an N-bit integer in O(lg(N)) operations with multiply and lookup
Note that in lg(N), N is the number of bits, not the number of the highest set bit. So it's constant time for any N-bit number.
If you know that the number is an exact power of 2 (i.e. there is only 1 bit set), there is an even faster method just below that.
That hack is for 32 bits. I seem to recall seeing a 64 bit example somewhere, but can't track it down at the moment. Worst case, you run it twice: once for the high 32 bits and once for the low 32 bits.
If your numbers are powers of 2 and you have a bit count instruction you could do:
bitcount(x-1)
e.g.
x x-1 bitcount(x-1)
b100 b011 2
b001 b000 0
Note this will not work if the numbers are not powers of 2.
EDIT
Here is a 64bit version of the De Brujin method:
static const int log2_table[64] = {0, 1, 2, 7, 3, 13, 8, 19, 4, 25, 14, 28, 9, 34,
20, 40, 5, 17, 26, 38, 15, 46, 29, 48, 10, 31,
35, 54, 21, 50, 41, 57, 63, 6, 12, 18, 24, 27,
33, 39, 16, 37, 45, 47, 30, 53, 49, 56, 62, 11,
23, 32, 36, 44, 52, 55, 61, 22, 43, 51, 60, 42, 59, 58};
int fastlog2(unsigned long long x) {
return log2_table[ ( x * 0x218a392cd3d5dbfULL ) >> 58 ];
}
Test code:
int main(int argc,char *argv[])
{
int i;
for(i=0;i<64;i++) {
unsigned long long x=1ULL<<i;
printf("0x%llu -> %d\n",x,fastlog2(x));
}
return 0;
}
The magic 64bit number is an order 6 binary De Brujin sequence.
Multiplying by a power of 2 is equivalent to shifting this number up by a certain number of places.
This means that the top 6 bits of the multiplication result correspond to a different subsequence of 6 digits for each input number. The De Brujin sequence has the property that each subsequence is unique, so we can construct an appropriate lookup table to turn back from subsequence to position of the set bit.
If you use some modern Intel CPU, you can use hardware
supported "POPulation CouNT" assembly instruction:
http://en.wikipedia.org/wiki/SSE4#POPCNT_and_LZCNT
for Unix/gcc, you can use macro:
#include <smmintrin.h>
uint64_t x;
int c = _mm_popcnt_u64(x);

Quicksort - Trouble identifying pivot

I'm trying to understand quicksort and I get the general idea, but I'm having trouble with the below question. Is there an easy way to identify which pivot is being used based on the array after each iteration?
Consider the following array and its state after iterations of QuickSort on the array:
Initial Array: 32, 12, 17, 73, 40, 88, 16, 75
After Iter 1: 32, 12, 17, 40, 16, 73, 88, 75
After Iter 2: 12, 16, 17, 40, 32, 73, 88, 75
After Iter 3: 12, 16, 17, 40, 32, 73, 88, 75
After Iter 4: 12, 16, 17, 32, 40, 73, 88, 75
After Iter 5: 12, 16, 17, 32, 40, 73, 75, 88
Name the pivot selection strategy used in this QuickSort execution.
Hint: Examine what value is being selected as the pivot at each stage. Remember
that QuickSort first sorts the left sub-array and its left-sub-array recursively before
sorting the right sub-arrays.
Any element is chosen as pivot and then in first iteration, all elements smaller than pivot are placed to the left of pivot and greater to the right, if they are already not. This means swapping pivot ahead in the array as well if needed. Knowing this and looking at the iteration should help identify the pivot.
For e.g. in your above case, i believe the middle element is being chosen as pivot i.e. 73. After first iteration, all elements lesser than it are moved to left and greater than it are moved to it's right.

Resources