Why didn't the complement's formula work? - algorithm

I have just learnt that to get the formula to find the 1st Complement is
-x = 2^n - x - 1
I have managed to apply it on a binary case:
-00001100 (base 2) = 2^8 - 12 - 1
= 243
= 11110011 (1s)
However, when I try to apply the same formula to a base 5 number,
-1042 (base 4) = 5^4 - 1042 - 1
= 625 - 1042 - 1
= - 400 (which is not the answer)
Can some one help me out here? Thanks

you cannot calculate any formula with numbers in 2 different bases, you have to use their decimal representation (or an other representation you can handle)
I'll give it a try in dec:
1042 (base 5) = 1* 5^3 + 4* 5^1 + 2 = 125 + 20 + 2 = 147 dec
5^4 - 147 - 1 = 477 dec
477 = 3* 5^3 + 4* 5^2 + 2 = 3402 (base 5)
in base 5:
5^4 - 1042 - 1 = 10000 - 1043 = 3402

Related

How to write a function f("123")=123+12+23+1+2+3 as a recurrence relationship

I'm wondering if someone can help me try to figure this out.
I want f(str) to take a string str of digits and return the sum of all substrings as numbers, and I want to write f as a function of itself so that I can try to solve this with memoization.
It's not jumping out at me as I stare at
Solve("1") = 1
Solve("2") = 2
Solve("12") = 12 + 1 + 2
Solve("29") = 29 + 2 + 9
Solve("129") = 129 + 12 + 29 + 1 + 2 + 9
Solve("293") = 293 + 29 + 93 + 2 + 9 + 3
Solve("1293") = 1293 + 129 + 293 + 12 + 29 + 93 + 1 + 2 + 9 + 3
Solve("2395") = 2395 + 239 + 395 + 23 + 39 + 95 + 2 + 3 + 9 + 5
Solve("12395") = 12395 + 1239 + 2395 + 123 + 239 + 395 + 12 + 23 + 39 + 95 + 1 + 2 + 3 + 9 + 5
You have to break f down into two functions.
Let N[i] be the ith digit of the input. Let T[i] be the sum of substrings of the first i-1 characters of the input. Let B[i] be the sum of suffixes of the first i characters of the input.
So if the input is "12395", then B[3] = 9+39+239+1239, and T[3] = 123+12+23+1+2+3.
The recurrence relations are:
T[0] = B[0] = 0
T[i+1] = T[i] + B[i]
B[i+1] = B[i]*10 + (i+1)*N[i]
The last line needs some explanation: the suffixes of the first i+2 characters are the suffixes of the first i+1 characters with the N[i] appended on the end, as well as the single-character string N[i]. The sum of these is (B[i]*10+N[i]*i) + N[i] which is the same as B[i]*10+N[i]*(i+1).
Also f(N) = T[len(N)] + B[len(N)].
This gives a short, linear-time, iterative solution, which you could consider to be a dynamic program:
def solve(n):
rt, rb = 0, 0
for i in xrange(len(n)):
rt, rb = rt+rb, rb*10+(i+1)*int(n[i])
return rt+rb
print solve("12395")
One way to look at this problem is to consider the contribution of each digit to the final sum.
For example, consider the digit Di at position i (from the end) in the number xn-1…xi+1Diyi-1…y0. (I used x, D, and y just to be able to talk about the digit positions.) If we look at all the substrings which contain D and sort them by the position of D from the end of the number, we'll see the following:
D
xD
xxD
…
xx…xD
Dy
xDy
xxDy
…
xx…xDy
Dyy
xDyy
xxDyy
…
xx…xDyy
and so on.
In other words, D appears in every position from 0 to i once for each prefix length from 0 to n-i-1 (inclusive), or a total of n-i times in each digit position. That means that its total contribution to the sum is D*(n-i) times the sum of the powers of 10 from 100 to 10i. (As it happens, that sum is exactly (10i+1−1)⁄9.)
That leads to a slightly simpler version of the iteration proposed by Paul Hankin:
def solve(n):
ones = 0
accum = 0
for m in range(len(n),0,-1):
ones = 10 * ones + 1
accum += m * ones * int(n[m-1])
return accum
By rearranging the sums in a different way, you can come up with this simple recursion, if you really really want a recursive solution:
# Find the sum of the digits in a number represented as a string
digitSum = lambda n: sum(map(int, n))
# Recursive solution by summing suffixes:
solve2 = lambda n: solve2(n[1:]) + (10 * int(n) - digitSum(n))/9 if n else 0
In case it's not obvious, 10*n-digitSum(n) is always divisible by 9, because:
10*n == n + 9*n == (mod 9) n mod 9 + 0
digitSum(n) mod 9 == n mod 9. (Because 10k == 1 mod n for any k.)
Therefore (10*n - digitSum(n)) mod 9 == (n - n) mod 9 == 0.
Looking at this pattern:
Solve("1") = f("1") = 1
Solve("12") = f("12") = 1 + 2 + 12 = f("1") + 2 + 12
Solve("123") = f("123") = 1 + 2 + 12 + 3 + 23 + 123 = f("12") + 3 + 23 + 123
Solve("1239") = f("1239") = 1 + 2 + 12 + 3 + 23 + 123 + 9 + 39 + 239 + 1239 = f("123") + 9 + 39 + 239 + 1239
Solve("12395") = f("12395") = 1 + 2 + 12 + 3 + 23 + 123 + 9 + 39 + 239 + 1239 + 5 + 95 + 395 + 2395 + 12395 = f("1239") + 5 + 95 + 395 + 2395 + 12395
To get the new terms, with n being the length of str, you are including the substrings made up of the 0-based index ranges of characters in str: (n-1,n-1), (n-2,n-1), (n-3,n-1), ... (n-n, n-1).
You can write a function to get the sum of the integers formed from the substring index ranges. Calling that function g(str), you can write the function recursively as f(str) = f(str.substring(0, str.length - 1)) + g(str) when str.length > 1, and the base case with str.length == 1 would just return the integer value of str. (The parameters of substring are the start index of a character in str and the length of the resulting substring.)
For the example Solve("12395"), the recursive equation f(str) = f(str.substring(0, str.length - 1)) + g(str) yields:
f("12395") =
f("1239") + g("12395") =
(f("123") + g("1239")) + g("12395") =
((f("12") + g("123")) + g("1239")) + g("12395") =
(((f("1") + g("12")) + g("123")) + g("1239")) + g("12395") =
1 + (2 + 12) + (3 + 23 + 123) + (9 + 39 + 239 + 1239) + (5 + 95 + 395 + 2395 + 12395)

How to pick only 4 set of integers from a set in polynomial time algorithm

The whole thing about this polynomial time is confusing to me for example: I want to write a program in a polynomial time algorithm that will just pick only 4 integers that sum to 0 from a set.
For instance: Let assume I have the following set of integers {8, 20, 3, -2, 3, 7, 16, -9}. How can I pick only 4 distinct integers that sum to 0 from a set in polynomial time without having needed to check through every possible length other than 4? Note in the program I don’t need to search through any other possible length than 4. My expected solution is {8, 3, -2, -9} = 0. knowing fully well that i only need 4 integers from the set {8, 20, 3, -2, 3, 7, 16, -9}.
Edit: Will I found a polynomial time solution of {8, 3, -2, -9} even if I increase only the length of the original set from 8 to 100 integers while I will still have to pick my 4 elements that sum to 0 but from the set of 100 integers will it still be polynomial fast with respect to the size of the input (i.e the number of bits used to store the input)?
The following algorithm runs in O(N^3 * logN).
#include <algorithm>
#include <iostream>
#include <tuple>
#include <vector>
using quadruple = std::tuple<int, int, int, int>;
std::vector<quadruple> find(std::vector<int> vec) {
std::sort(vec.begin(), vec.end());
vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
std::vector<quadruple> ret;
for (auto i = 0u; i + 3 < vec.size(); ++i) {
for (auto j = i + 1; j + 2 < vec.size(); ++j) {
for (auto k = j + 1; k + 1 < vec.size(); ++k) {
auto target = 0 - vec[i] - vec[j] - vec[k];
auto it = std::lower_bound(vec.begin() + k + 1,
vec.end(),
target);
if (it != vec.end() && *it == target) {
ret.push_back(std::make_tuple(
vec[i], vec[j], vec[k], target));
}
}
}
}
return ret;
}
int main() {
std::vector<int> input = {8, 20, 3, -2, 3, 7, 16, -9};
auto output = find(input);
for (auto& quad : output) {
std::cout << std::get<0>(quad) << ' '
<< std::get<1>(quad) << ' '
<< std::get<2>(quad) << ' '
<< std::get<3>(quad) << std::endl;
}
}
Try all quadruples without repetitions. This takes at most (N^4-6N³+11N²-6N)/24 attempts each made in constant time.
8 + 20 + 3 - 2 = 29
8 + 20 + 3 + 3 = 34
8 + 20 + 3 + 7 = 38
8 + 20 + 3 + 16 = 47
8 + 20 + 3 - 9 = 22
8 + 20 - 2 + 3 = 29
8 + 20 - 2 + 7 = 33
8 + 20 - 2 + 16 = 42
8 + 20 - 2 - 9 = 17
8 + 20 + 3 + 7 = 38
8 + 20 + 3 + 16 = 47
8 + 20 + 3 - 9 = 22
8 + 20 + 7 + 16 = 51
8 + 20 + 7 - 9 = 26
8 + 20 + 16 - 9 = 35
8 + 3 - 2 + 3 = 12
8 + 3 - 2 + 7 = 16
8 + 3 - 2 + 16 = 25
8 + 3 - 2 - 9 = 0 <==
8 + 3 + 3 + 7 = 21
8 + 3 + 3 + 16 = 30
8 + 3 + 3 - 9 = 5
8 + 3 + 7 + 16 = 34
8 + 3 + 7 - 9 = 9
8 + 3 + 16 - 9 = 18
8 - 2 + 3 + 7 = 16
8 - 2 + 3 + 16 = 25
8 - 2 + 3 - 9 = 0 <==
8 - 2 + 7 + 16 = 29
8 - 2 + 7 - 9 = 4
8 - 2 + 16 - 9 = 13
8 + 3 + 7 + 16 = 34
8 + 3 + 7 - 9 = 9
8 + 3 + 16 - 9 = 18
8 + 7 + 16 - 9 = 22
20 + 3 - 2 + 3 = 24
20 + 3 - 2 + 7 = 28
20 + 3 - 2 + 16 = 37
20 + 3 - 2 - 9 = 12
20 + 3 + 3 + 7 = 33
20 + 3 + 3 + 16 = 42
20 + 3 + 3 - 9 = 17
20 + 3 + 7 + 16 = 46
20 + 3 + 7 - 9 = 21
20 + 3 + 16 - 9 = 30
20 - 2 + 3 + 7 = 28
20 - 2 + 3 + 16 = 37
20 - 2 + 3 - 9 = 12
20 - 2 + 7 + 16 = 41
20 - 2 + 7 - 9 = 16
20 - 2 + 16 - 9 = 25
20 + 3 + 7 + 16 = 46
20 + 3 + 7 - 9 = 21
20 + 3 + 16 - 9 = 30
20 + 7 + 16 - 9 = 34
3 - 2 + 3 + 7 = 11
3 - 2 + 3 + 16 = 20
3 - 2 + 3 - 9 = -5
3 - 2 + 7 + 16 = 24
3 - 2 + 7 - 9 = -1
3 - 2 + 16 - 9 = 8
3 + 3 + 7 + 16 = 29
3 + 3 + 7 - 9 = 4
3 + 3 + 16 - 9 = 13
3 + 7 + 16 - 9 = 17
- 2 + 3 + 7 + 16 = 24
- 2 + 3 + 7 - 9 = -1
- 2 + 3 + 16 - 9 = 8
- 2 + 7 + 16 - 9 = 12
3 + 7 + 16 - 9 = 17
Update:
At the request of the OP, stopped when a solution is found.
8 + 20 + 3 - 2 = 29
8 + 20 + 3 + 3 = 34
8 + 20 + 3 + 7 = 38
8 + 20 + 3 + 16 = 47
8 + 20 + 3 - 9 = 22
8 + 20 - 2 + 3 = 29
8 + 20 - 2 + 7 = 33
8 + 20 - 2 + 16 = 42
8 + 20 - 2 - 9 = 17
8 + 20 + 3 + 7 = 38
8 + 20 + 3 + 16 = 47
8 + 20 + 3 - 9 = 22
8 + 20 + 7 + 16 = 51
8 + 20 + 7 - 9 = 26
8 + 20 + 16 - 9 = 35
8 + 3 - 2 + 3 = 12
8 + 3 - 2 + 7 = 16
8 + 3 - 2 + 16 = 25
8 + 3 - 2 - 9 = 0 <==

Selecting neighbours on a circle

Consider we have N points on a circle. To each point an index is assigned i = (1,2,...,N). Now, for a randomly selected point, I want to have a vector including the indices of 5 points, [two left neighbors, the point itself, two right neighbors].
See the figure below.
Some sxamples are as follows:
N = 18;
selectedPointIdx = 4;
sequence = [2 3 4 5 6];
selectedPointIdx = 1
sequence = [17 18 1 2 3]
selectedPointIdx = 17
sequence = [15 16 17 18 1];
The conventional way to code this is considering the exceptions as if-else statements, as I did:
if ii == 1
lseq = [N-1 N ii ii+1 ii+2];
elseif ii == 2
lseq = [N ii-1 ii ii+1 ii+2];
elseif ii == N-1
lseq=[ii-2 ii-1 ii N 1];
elseif ii == N
lseq=[ii-2 ii-1 ii 1 2];
else
lseq=[ii-2 ii-1 ii ii+1 ii+2];
end
where ii is selectedPointIdx.
It is not efficient if I consider for instance 7 points instead of 5. What is a more efficient way?
How about this -
off = -2:2
out = mod((off + selectedPointIdx) + 17,18) + 1
For a window size of 7, edit off to -3:3.
It uses the strategy of subtracting 1 + modding + adding back 1 as also discussed here.
Sample run -
>> off = -2:2;
for selectedPointIdx = 1:18
disp(['For selectedPointIdx =',num2str(selectedPointIdx),' :'])
disp(mod((off + selectedPointIdx) + 17,18) + 1)
end
For selectedPointIdx =1 :
17 18 1 2 3
For selectedPointIdx =2 :
18 1 2 3 4
For selectedPointIdx =3 :
1 2 3 4 5
For selectedPointIdx =4 :
2 3 4 5 6
For selectedPointIdx =5 :
3 4 5 6 7
For selectedPointIdx =6 :
4 5 6 7 8
....
For selectedPointIdx =11 :
9 10 11 12 13
For selectedPointIdx =12 :
10 11 12 13 14
For selectedPointIdx =13 :
11 12 13 14 15
For selectedPointIdx =14 :
12 13 14 15 16
For selectedPointIdx =15 :
13 14 15 16 17
For selectedPointIdx =16 :
14 15 16 17 18
For selectedPointIdx =17 :
15 16 17 18 1
For selectedPointIdx =18 :
16 17 18 1 2
You can use modular arithmetic instead: Let p be the point among N points numbered 1 to N. Say you want m neighbors on each side, you can get them as follows:
(p - m - 1) mod N + 1
...
(p - 4) mod N + 1
(p - 3) mod N + 1
(p - 2) mod N + 1
p
(p + 1) mod N + 1
(p + 2) mod N + 1
(p + 3) mod N + 1
...
(p + m - 1) mod N + 1
Code:
N = 18;
p = 2;
m = 3;
for i = p - m : p + m
nb = mod((i - 1) , N) + 1;
disp(nb);
end
Run code here
I would like you to note that you might not necessarily improve performance by avoiding a if statement. A benchmark might be necessary to figure this out. However, this will only be significant if you are treating tens of thousands of numbers.

How to reclassify images in Matlab?

I am attempting to reclassify continuous data to categorical data using Matlab. The following script takes a 4-band (Red, Green, Blue, nIR) aerial image and calculates the normalized difference vegetation index (i.e. a vegetation index showing healthy green vegetation). The script then rescales the values from (-1 to 1) to (0 - 255). This is the matrix I am trying to reclassify in the third section of the script %% Reclassify Imag1 matrix. I am attempting to use conditional statements to perform the reclassification, although this may be the wrong approach. The reclassification step in the script does not have any apparent effect.
How can I reclassify continuous values (0 - 255) to categorical values (1, 2, 3, 4) on a cell by cell basis?
file = 'F:\path\to\naip\image\4112107_ne.tif';
[Z R] = geotiffread(file);
outputdir = 'F:\temp\';
%% Make NDVI calculations
NIR = im2single(Z(:,:,4));
red = im2single(Z(:,:,3));
ndvi = (NIR - red) ./ (NIR + red);
ndvi = double(ndvi);
%% Stretch NDVI to 0-255 and convert to 8-bit unsigned integer
ndvi = floor((ndvi + 1) * 128); % [-1 1] -> [0 256]
ndvi(ndvi < 0) = 0; % not really necessary, just in case & for symmetry
ndvi(ndvi > 255) = 255; % in case the original value was exactly 1
Imag1 = uint8(ndvi);
%% Reclassify Imag1 matrix
if (150 <= Imag1)
Imag1 = 1;
elseif (150 > Imag1) & (140 < Imag1)
Imag1 = 2;
elseif (140 > Imag1) & (130 < Imag1)
Imag1 = 3;
elseif (130 >= Imag1)
Imag1 = 4;
end
%% Write the results to disk
tiffdata = geotiffinfo(file);
outfilename = [outputdir 'reclass_ndvi' '.tif'];
geotiffwrite(outfilename, Imag1, R, 'GeoKeyDirectoryTag', tiffdata.GeoTIFFTags.GeoKeyDirectoryTag)
disp('Processing complete')
Try this:
Imag1 = [ 62 41 169 118 210;
133 158 96 149 110;
211 200 84 194 29;
209 16 15 146 28;
95 144 13 249 170];
Imag1(find(Imag1 <= 130)) = 4;
Imag1(find(Imag1 >= 150)) = 1;
Imag1(find(Imag1 > 140)) = 2;
Imag1(find(Imag1 > 130)) = 3;
Result:
Imag1 =
62 41 169 118 210
133 158 96 149 110
211 200 84 194 29
209 16 15 146 28
95 144 13 249 170
Imag1 =
4 4 1 4 1
3 1 4 2 4
1 1 4 1 4
1 4 4 2 4
4 2 4 1 1
I can go into the logic in detail if you like, but I wanted to confirm that this gives your expected results first.
Some updates based on comments on the follow-up question to eliminate the unnecessary find and make the code more robust and independent of execution order.
Imag2 = zeros(size(Imag1));
Imag2(Imag1 >= 150) = 1;
Imag2((Imag1 > 140) & (Imag1 < 150)) = 2;
Imag2((Imag1 > 130) & (Imag1 < 141)) = 3;
Imag2(Imag1 <= 130) = 4;
Note that the results are now in Imag2 instead of overwriting Imag1.

Google interview, can somebody confirm this bit string algorithm, pure hypothesis

This was a Google question i didn't figure out was right or wrong but a 2nd opinion never hurt. but the question is "given an n length bit-string solve for the number of times "111" appeared in all possible combinations."
now i know to find total combinations is 2^n what took me trouble was figuring out the number of occurrences i did find a pattern in occurrences but who knows for sure what happens when n becomes vast.
My logical solution was
#Level (n length) # combos # strings with "111" in it
_________________ ________ _____________________________
0 0 0
1("1" or "0") 2 0
2("11","01" etc. 4 0
3 8 1("111")
4 16 3
5 32 8
6 64 20
------------------------------------Everything before this is confirmed
7 128 49
8 256 119
9 512 288
10 1000 696
etc.. i can post how i came up with the magical fairy dust but yeah
I can help you with a solution:
Call the function to calculate number of string with n bit contains 111 is f(n)
If the first bit of the string is 0, we have f(n) += f(n - 1)//0 + (n - 1 bits)
If the first bit of the string is 1, we have f(n) += f(n - 2) + f(n - 3) + 2^(n - 3)
More explanation for case first bit is 1
If the first bit is 1, we have three cases:
10 + (n - 2 bits) = f(n - 2)
110 + (n - 3 bits) = f(n - 3)
111 + (n - 3 bits) = 2^(n - 3) as we can take all combinations.
So in total f(n) = f(n - 1) + f(n - 2) + f(n - 3) + 2^(n - 3).
Apply to our example:
n = 4 -> f(4) = f(3) + f(2) + f(1) + 2^1 = 1 + 0 + 0 + 2 = 3;
n = 5 -> f(5) = f(4) + f(3) + f(2) + 2^2 = 3 + 1 + 0 + 4 = 8;
n = 6 -> f(6) = f(5) + f(4) + f(3) + 2^3 = 8 + 3 + 1 + 8 = 20;
n = 7 -> f(7) = f(6) + f(5) + f(4) + 2^4 = 20 + 8 + 3 + 16 = 47;
n = 8 -> f(8) = f(7) + f(6) + f(5) + 2^5 = 47 + 20 + 8 + 32 = 107;
n = 9 -> f(9) = f(8) + f(7) + f(6) + 2^6 = 107 + 47 + 20 + 64 = 238;

Resources