i=1
while i <= n do:
j=0
k=i
while k%3 == 0 do:
k = k/3
j++
end
print i, j
i++
end
What is Big-O of given algorithm (How do we show my work)? And what does this algorithm output // ?
My answer and approach
O(nlogn). Because the outer loop runs linear time as O(n) while the inner loop is dependent as O(logn).
But I'm not sure if it's logn.
When n = 10,
ij
00
10
20
31
40
50
61
70
80
92
100 ( 10, 0)
When n = 30
i j
1 0
2 0
3 1
4 0
5 0
6 1
7 0
8 0
9 2
10 0
11 0
12 1
13 0
14 0
15 1
16 0
17 0
18 2
19 0
20 0
21 1
22 0
23 0
24 1
25 0
26 0
27 3
28 0
29 0
30 1
Appreciate that every third number in the series from 1 to n will be divisible by 3. In the worst case, such a number would end up being divided by 3 in the k loop log_3(i) times. So the sequence will behave like O(n) two thirds of the time, and like O(n*log3(n)) one third of the time. We can therefore claim that your code is upper bounded by O(n*log3(n)), although there is a bound which is tighter than this.
The code will print each value i in the series along with the "three depth" of that number. By "three depth" I mean how many times we were able to divide i by 3. Obviously, for i values which are not multiples of 3, the depth is 0.
Related
I have a greedy solution for the following problem. I want to know how to prove it?
The problem is as follows: Given an n x n 2D matrix of non-negative integers, find three cells such that the sum of those cells and adjacent cells are as much as possible. If two chosen cells have common adjacent cells, the adjacent cells only participate once in the sum and two cells are considered adjacent if they share a common edge.
The naive brute force solutions runs in O(n6). I have written a greedy solution that runs in O(n4). The greedy solution uses this idea that the cell with maximum total sum of itself and its adjacent cells is always a part of the answer. I have tested both solutions on several test cases and the results are identical.
In greedy algorithm, first I choose the cell with maximum total sum of itself and adjacent cells and then iterate through all possible pair of cells.
Now my question is that, why this greedy strategy works? I want the proof. Thanks!
It doesn't work. Sorry,
20 1 40 1 40 1 20
20 2 40 3 40 2 20
20 1 40 1 40 1 20
1 1 20 20 20 1 1
1 1 20 2 20 1 1
1 1 20 20 20 1 1
The 3 has the highest sum of itself and all adjacent cells. However picking the 3 cells of value 2 is actually best.
Edit
Apparently you meant something different from me by "adjacent". So try this example:
1 1 1 1 1 1 1
20 2 40 3 40 2 20
1 1 1 20 1 1 1
1 1 20 2 20 1 1
1 1 1 20 1 1 1
1 1 1 1 1 1 1
I have the struct Trajectories with field uniqueDate, dateAll, label: I want to compare the fields uniqueDate and dateAll and, if there is a correspondence, I will save in label a value from an other struct.
I have written this code:
for k=1:nCols
for j=1:size(Trajectories(1,k).dateAll,1)
for i=1:size(Trajectories(1,k).uniqueDate,1)
if (~isempty(s(1,k).places))&&(Trajectories(1,k).dateAll(j,1)==Trajectories(1,k).uniqueDate(i,1))&&(Trajectories(1,k).dateAll(j,2)==Trajectories(1,k).uniqueDate(i,2))&&(Trajectories(1,k).dateAll(j,3)==Trajectories(1,k).uniqueDate(i,3))
for z=1:24
if(Trajectories(1,k).dateAll(j,4)==z)&&(size(s(1,k).places.all,2)>=size(Trajectories(1,k).uniqueDate,1))
Trajectories(1,k).label(j)=s(1,k).places.all(z,i);
else if(Trajectories(1,k).dateAll(j,4)==z)&&(size(s(1,k).places.all,2)<size(Trajectories(1,k).uniqueDate,1))
for l=1:size(s(1,k).places.all,2)
Trajectories(1,k).label(l)=s(1,k).places.all(z,l);
end
end
end
end
end
end
end
end
E.g
Trajectories(1,4).dateAll=[1 2004 8 1 14 1 15 0 0 0 1 42 13 2;596 2004 8 1 16 20 14 0 0 0 1 29 12 NaN;674 2004 8 1 18 26 11 0 0 0 1 20 38 1;674 2004 8 2 10 7 40 0 0 0 14 26 5 3;674 2004 8 2 11 3 29 0 0 0 1 54 3 3;631 2004 8 2 11 57 56 0 0 0 0 30 8 2;1 2004 8 2 12 4 35 0 0 0 1 53 21 2;631 2004 8 2 12 52 58 0 0 0 0 20 36 2;631 2004 8 2 13 5 3 0 0 0 1 49 40 2;631 2004 8 2 14 0 20 0 0 0 1 56 12 2;631 2004 8 2 15 2 0 0 0 0 1 57 39 2;631 2004 8 2 16 1 4 0 0 0 1 55 53 2;1 2004 8 2 17 9 15 0 0 0 1 48 41 2];
Trajectories(1,4).uniqueDate= [2004 8 1;2004 8 2;2004 8 3;2004 8 4];
it runs but it's very very slow. How can I modify it to speed up?
Let's work from the inside out and see where it gets us.
Step 1: Simplify your comparison condition:
if (~isempty(s(1,k).places))&&(Trajectories(1,k).dateAll(j,1)==Trajectories(1,k).uniqueDate(i,1))&&(Trajectories(1,k).dateAll(j,2)==Trajectories(1,k).uniqueDate(i,2))&&(Trajectories(1,k).dateAll(j,3)==Trajectories(1,k).uniqueDate(i,3))
becomes
if (~isempty(s(1,k).places)) && all( Trajectories(1,k).dateAll(j,1:3)==Trajectories(1,k).uniqueDate(i,1:3) )
Then we want to remove this from a for-loop. The "intersect" function is useful here:
[ia i1 i2]=intersect(Trajectories(1,k).dateAll(:,1:3),Trajectories(1,k).uniqueDate(:,1:3),'rows');
We now have a vector i1 of all rows in dateAll that intersect with uniqueDate.
Now we can remove the loop comparing z using a similar approach:
[iz iz1 iz2] = intersect(Trajectories(1,k).dateAll(i1,4),1:24);
We have to be careful about our indices here, using a subset of a subset.
This simplifies the code to:
for k=1:nCols
if isempty(s(1,k).places)
continue; % skip to the next value of k, no need to do the rest of the comparison
end
[ia i1 i2]=intersect(Trajectories(1,k).dateAll(:,1:3),Trajectories(1,k).uniqueDate(:,1:3),'rows');
[iz iz1 iz2] = intersect(Trajectories(1,k).dateAll(i1,4),1:24);
usescalarlabel = (size(s(1,k).places.all,2)>=size(Trajectories(1,k).uniqueDate,1);
if (usescalarlabel)
Trajectories(1,k).label(i1(iz1)) = s(1,k).places.all(iz,i2(iz1));
else
% you will need to check this: I think here you were needlessly repeating this step for every match
Trajectories(1,k).label(i1(iz1)) = s(1,k).places.all(iz,:);
end
end
But wait! That z loop is exactly the same as using indexing. So we don't need that second intersect after all:
for k=1:nCols
if isempty(s(1,k).places)
continue; % skip to the next value of k, no need to do the rest of the comparison
end
[ia i1 i2]=intersect(Trajectories(1,k).dateAll(:,1:3),Trajectories(1,k).uniqueDate(:,1:3),'rows');
usescalarlabel = (size(s(1,k).places.all,2)>=size(Trajectories(1,k).uniqueDate,1);
label_indices = Trajectories(1,k).dateAll(i1,4);
if (usescalarlabel)
Trajectories(1,k).label(label_indices) = s(1,k).places.all(label_indices,i2);
else
% you will need to check this: I think here you were needlessly repeating this step for every match
Trajectories(1,k).label(label_indices) = s(1,k).places.all(label_indices,:);
end
end
You'll need to check the indexing in this - I'm sure I've made a mistake somewhere without having data to test against, but that should give you an idea on how to proceed removing the loops and using vector expressions instead. Without seeing the data that's as far as I can optimise. You may be able to go further if you can reformat your data into a set of 3d matrices / cells instead of using structs.
I am suspicious of your condition which I have called "usescalarlabel" - it seems like you are mixing two data types. Also I would strongly recommend separating the dateAll matrices into separate "date" and "data" matrices as the row indices 4 onwards don't seem to be dates. Also the example you copy/pasted in seems to have an extra value at row index 1? In that case you'll need to compare Trajectories(1,k).dateAll(:,2:4) instead of Trajectories(1,k).dateAll(:,1:3).
Good luck.
I'd like to create a function where for an arbitrary integer input value (let's say unsigned 32 bit) and a given number of d digits the return value will be a d digit B base number, B being the smallest base that can be used to represent the given input on d digits.
Here is a sample input - output of what I have in mind for 3 digits:
Input Output
0 0 0 0
1 0 0 1
2 0 1 0
3 0 1 1
4 1 0 0
5 1 0 1
6 1 1 0
7 1 1 1
8 0 0 2
9 0 1 2
10 1 0 2
11 1 1 2
12 0 2 0
13 0 2 1
14 1 2 0
15 1 2 1
16 2 0 0
17 2 0 1
18 2 1 0
19 2 1 1
20 0 2 2
21 1 2 2
22 2 0 2
23 2 1 2
24 2 2 0
25 2 2 1
26 2 2 2
27 0 0 3
28 0 1 3
29 1 0 3
30 1 1 3
.. .....
The assignment should be 1:1, for each input value there should be exactly one, unique output value. Think of it as if the function should return the nth value from the list of strangely sorted B base numbers.
Actually this is the only approach I could come up so far with - given an input value, generate all the numbers in the smallest possible B base to represent the input on d digits, then apply a custom sorting to the results ('penalizing' the higher digit values and putting them further back in the sort), and return the nth value from the sorted array. This would work, but is a spectacularly inefficient implementation - I'd like to do this without generating all the numbers up to the input value.
What would be an efficient approach for implementing this function? Any language or pseudocode is fine.
MBo's answer shows how to find the smallest base that will represent an integer number with a given number of digits.
I'm not quite sure about the ordering in your example. My answer is based on a different ordering: Create all possible n-digit numbers up to base b (e.g. all numbers up to 999 for max. base 10 and 3 digits). Sort them according to their maximum digit first. Numbers are sorted normalls within a group with the same maximum digit. This retains the characteristic that all values from 8 to 26 must be base 3, but the internal ordering is different:
8 0 0 2
9 0 1 2
10 0 2 0
11 0 2 1
12 0 2 2
13 1 0 2
14 1 1 2
15 1 2 0
16 1 2 1
17 1 2 2
18 2 0 0
19 2 0 1
20 2 0 2
21 2 1 0
22 2 1 1
23 2 1 2
24 2 2 0
25 2 2 1
26 2 2 2
When your base is two, life is easy: Just generate the appropriate binary number.
For other bases, let's look at the first digit. In the example above, five numbers start with 0, five start with 1 and nine start with 2. When the first digit is 2, the maximum digit is assured to be 2. Therefore, we can combine 2 with a 9 2-digit numbers of base 3.
When the first digit is smaller than the maximum digit in the group, we can combine it with the 9 2-digit numbers of base 3, but we must not use the 4 2-digit numbers that are ambiguous with the 4 2-digit numbers of base 2. That gives us five possibilites for the digits 0 and 1. These possibilities – 02, 12, 20, 21 and 22 – can be described as the unique numbers with two digits according to the same scheme, but with an offset:
4 0 2
5 1 2
6 2 0
7 2 1
8 2 2
That leads to a recursive solution:
for one digit, just return the number itself;
for base two, return the straightforward representation in base 2;
if the first number is the maximum digit for the determined base, combine it with a straighforward representations in that base;
otherwise combine it with a recursively determined representation of the same algorithm with one fewer digit.
Here's an example in Python. The representation is returned as list of numbers, so that you can represent 2^32 − 1 as [307, 1290, 990].
import math
def repres(x, ndigit, base):
"""Straightforward representation of x in given base"""
s = []
while ndigit:
s += [x % base]
x /= base
ndigit -= 1
return s
def encode(x, ndigit):
"""Encode according to min-base, fixed-digit order"""
if ndigit <= 1:
return [x]
base = int(x ** (1.0 / ndigit)) + 1
if base <= 2:
return repres(x, ndigit, 2)
x0 = (base - 1) ** ndigit
nprev = (base - 1) ** (ndigit - 1)
ncurr = base ** (ndigit - 1)
ndiff = ncurr - nprev
area = (x - x0) / ndiff
if area < base - 1:
xx = x0 / (base - 1) + x - x0 - area * ndiff
return [area] + encode(xx, ndigit - 1)
xx0 = x0 + (base - 1) * ndiff
return [base - 1] + repres(x - xx0, ndigit - 1, base)
for x in range(32):
r = encode(x, 3)
print x, r
Assuming that all values are positive, let's make simple math:
d-digit B-based number can hold value N if
Bd > N
so
B > N1/d
So calculate N1/d value, round it up (increment if integer), and you will get the smallest base B.
(note that numerical errors might occur)
Examples:
d=2, N=99 => 9.95 => B=10
d=2, N=100 => 10 => B=11
d=2, N=57 => 7.55 => B=8
d=2, N=33 => 5.74 => B=6
Delphi code
function GetInSmallestBase(N, d: UInt32): string;
const
Digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var
Base, i: Byte;
begin
Base := Ceil(Power(N, 1/d) + 1.0E-12);
if Base > 36 then
Exit('Big number, few digits...');
SetLength(Result, d);
for i := d downto 1 do begin
Result[i] := Digits[1 + N mod Base]; //Delphi string is 1-based
N := N div Base;
end;
Result := Result + Format(' : base [%d]', [Base]);
end;
begin
Memo1.Lines.Add(GetInSmallestBase(99, 2));
Memo1.Lines.Add(GetInSmallestBase(100, 2));
Memo1.Lines.Add(GetInSmallestBase(987, 2));
Memo1.Lines.Add(GetInSmallestBase(1987, 2));
Memo1.Lines.Add(GetInSmallestBase(87654321, 6));
Memo1.Lines.Add(GetInSmallestBase(57, 2));
Memo1.Lines.Add(GetInSmallestBase(33, 2));
99 : base [10]
91 : base [11]
UR : base [32]
Big number, few digits...
H03LL7 : base [22]
71 : base [8]
53 : base [6]
I am trying to solve the MARTIAN problem on SPOJ
My algorithm is as follows:
Define dp[i][j]=max amount of minerals that can be mined in the rectangle form 0,0 to i,j.
Use the recurrence
dp[i][j] = max(dp[i-1][j] + total amount of yeyenum
in the i-th row up to the j-th column,
dp[i][j-1] + total amount of bloggium
in the j-th column up to the cell i-th row)
However such an approach yields a WA (Wrong Answer). Can someone please provide me with a test case where such and approach will not work?
I am not looking for the correct algorithm just a test case where this approach fails as. I've been unable to find the bug myself.
Try this on your code(modified from the example given):
4 4
0 0 10 60
1 3 10 0
4 2 1 3
1 1 20 0
10 0 0 0
1 1 1 10
0 0 5 3
5 10 10 10
0 0
If you start by looking at [4][4], you'll choose Bloggium, because you can get 23 bloggium by going up, and only 22 Yeyenum from going left. However, you're going to miss a huge amount of Yeyenum.
Using your algorithm, you'll get 23 + 22 + 7 + 14 + 10 = 76.
If you choose the large Yeyenum, you'll get 70 + 14 + 10 + 22 = 116(all Yeyenum, since the bloggium gets blocked).
I want to assign values to a 3-D table in GAMS. But it seems it doesn't work as in Matlab.....Any luck ? Code is as followed and the problem is at the last few lines:
Sets
n nodes / Sto , Lon , Par , Ber , War , Mad , Rom /
i scenarios / 1 * 4 /
k capacity level / L, N, H / ;
alias(n,m);
Table balance(n,i) traffic balance for different nodes
1 2 3 4
Sto 50 50 -50 -50
Lon -40 40 -40 40
Par 0 0 0 0
Ber 0 0 0 0
War 40 -40 40 -40
Mad 0 0 0 0
Rom -50 -50 50 50 ;
Scalar r fluctuation rate of the capacity level
/0.15/;
Parameter p(k) probability of each level
/ L 0.25
N 0.5
H 0.25 / ;
Table nor_cap(n,m) Normal capacity level from n to m
Sto Lon Par Ber War Mad Rom
Sto 0 11 14 25 30 0 0
Lon 11 0 21 0 0 14 0
Par 14 21 0 22 0 31 19
Ber 25 0 22 0 26 0 18
War 30 0 0 26 0 18 22
Mad 0 14 31 0 18 0 15
Rom 0 0 19 18 22 15 0 ;
Table max_cap(n,m,k) capacity level under each k
max_cap(n,m,'N')=nor_cap(n,m)
max_cap(n,m,'L')=nor_cap(n,m)*(1-r)
max_cap(n,m,'H')=nor_cap(n,m)*(1+r);
The final assignment to a 3-D matrix should be done with PARAMETER as opposed to TABLE. In general I would also note that TABLE is very restrictive (2 dimensional, text input inside the code). You might want to consider $GDXIN (or EXECUTE_LOAD) and some of the GAMS utilities for loading xls or csv files.
As a user of both MATLAB and GAMS I would note that GAMS depends on "indices" for every array, but otherwise they can be quite similar. In your case max_cap(n,m,k) would be something like the maximum capacity between from_city and to_city under each capacity level scenario. Your matrix needs to be declared as a PARAMETER which can be any n-dimensional (indexed) matrix, including even a SCALAR.
Also, try the GAMS mailing list if you really need an answer quickly, the number of proficient GAMS users globally can't be more than a few thousand, so it might be hard to find a quick answer on StackOverflow - awesome as it is for the more common languages.