How it is getting the same prefix and suffix? - algorithm

I saw this code here and I want to know how below code is working. I understood the logic but just wondering how the implementation used the nice bit logic.
I have modified the code to make it for 4 bit. I wanted to know how common prefix is detected i.e. in the below case 5? What is the mathematical reasoning behind line number 12 and 13?
1 import random
2 #suppose the range of number is 8 bits
3 #and we are working with 4bits prefix
4 #and 4bits suffix
5 data = []
6 bits = 4
7 for i in range(100000):
8 data.append(random.randint(0, 100))
9 suffix = 5
10 for i in data:
11 i = int(i)
12 s = i^(suffix<<bits)
13 if s < (1 << bits):
14 print("s is ", s, "prefix of", i, "is", s, "and suffix is ", suffix)

bits == 4
prefix == 5 == 00000101
prefix << bits == 01010000
suffix = i XOR 01010000
=> e.g. if i == 0101xxxx => suffix == 0000xxxx (correct prefix)
=> e.g. if i == 1110xxxx => suffix == 1011xxxx (wrong prefix)
1 << bits == 00010000
if (suffix < 00010000) ~ if (suffix is like 0000xxxx) ~ if (i is like 0101xxxx)
So each random number is xor's with the prefix; this is then used both to check which numbers have the right prefix (if the 4 first bits are now 0000) and to get the suffix (last 4 bits).

Related

Decimal to Binary based on the logic B[i]*(2)^i Where i=[0,2,3...N-1]

I have a function that takes a binary array and returns a decimal based on the below logic:
1 | -2 | 4 | -8 | 16 | -32 ...
1 | 0 | 0 | 1 | 1 | 1 = 1 + 0 + 0 + (-8) + 16 + (-32) = -23
def bin_to_dec(bin_array):
dec = 0
for i in range(0, len(bin_array)):
if i%2 == 0:
dec += bin_array[i] * 2**i
else:
dec += bin_array[i] * -2**i
print(dec)
return dec
I am struggling with writing the decimal to binary piece of the above logic. As in a function that takes for example -23 as input, and returns [1,0,0,1,1,1]. Any help would be highly appreciated.
You can use a few observations to solve this:
Consider a 5-bit number with the coefficient of 16 as 1. What could be the maximum value of the number? 21 = 1 + 4 + 16. Similarly, minimum value would be 6 = 16 - 2 - 8. So, for any number between [6,21], the coefficient of 16 is guaranteed to be 1.
Similarly, for a 6 bit number, if -32's bit is 1, the range of numbers will be between [-42, 11] -32 - 2 - 8 = -42 and -32 + 16 + 4 + 1 = 11
Now, each number x can be expressed in two ways for our problem:
a. (some binary number <= x) + (some positive value) (for example, 20 = 16+4)
b. (some binary number >= x) + (some negative value) (for example, 7 = 16+(-9))
Combining point #3 and #4, you can determine the most significant bit of the number. Calculate the range for the biggest binary number <= x (by binary number, I mean exponent of 2). If x is outside the upper limit of the range, we'll use method 3b to express it as a sum, or else method 3a.
Example: for 20, biggest exponent = 16 which has range [6,21], so we'll use 3a. However, for 30, we'll have to use 3b and express it as 64 + (some negative value).
Similarly, for negative numbers, you can use the lower bound of range to see which will be the biggest negative exponent. Example: for -9, biggest exponent = -8, which has range [-10,-3]. Since lower bound of -10 < -9, we can express it as -8 + (some negative value). For -14, we'll have to express it as -32 + (some positive value)
Using all of this, you can come with an implementation (either recursive or iterative, your decision). The algorithm would broadly look like:
convert(i):
x = rightmost bit/exponent for i
diff = difference between x and i
return x + convert(diff)
Using -23 as example:
Biggest exponenent <= -23 = -8. Since it is outside -8's range, we make it -32 + (9). Recursively solve for 9.
Biggest exponenent <= 9 = 4. Since it is outside 4's range, we make it 16 + (-7). Recursively solve for 7.
Biggest exponenent <= -7 = -2. Since it is outside -2's range, we make it -8 + (1). Recursively solve for 1.
For 1, we get 1.
So we get (-32)+(16)+(-8)+(1), which was the original summation.

What is << stand for in ruby with integer

What is use of << I understand in array it is used for push but here I am not clear what is purpose of this in following code. Where it is being used integer.
def array_pack(a)
a.reverse.reduce(0) { |x, b| (x << 8) + b }
end
array_pack([24, 85, 0]) # will print 21784
like if I x is 8 and I write 8 << 8 it gives me response of 2048 so is it converting in bytes? or what exact is its purpose.
It is a Bitwise LEFT shift operator.
Definition:
The LEFT SHIFT operator << shifts each bit of a number to the left by n positions.
Example:
If you do 7 << 2 = 28
7 in Base 2: 0000 0111
128 64 32 16 8 4 2 1
----------------------
7: 0 0 0 0 0 1 1 1
Now shift each bit to the left by 2 positions
128 64 32 16 8 4 2 1
----------------------
28: 0 0 0 1 1 1 0 0
Why?
Bitwise operators are widely used for low-level programming on embedded systems to apply a mask (in this case to integer)
Benefits
See this SO answer: link
View Source for more details: link
As the documentation says, Integer:<< - Returns the integer shifted left "X" positions, or right if "X" is negative. In your scenario is shifts 8 positions to the left.
Here is how it works:
8.to(2) => "1000"
Now let's shift "1000" 8 positions to the left
(8 << 8).to_s(2) => "100000000000"
If you count the 0 above you will see it added 8 after "1000".
Now, let's see how it returns 2048
"100000000000".to_i(2) => 2048

how to convert decimal value to binary bits?

Basically I want to learn the algorithm on how to convert decimal to binary, I found this:
int convert(int dec)
{
if (dec == 0)
{
return 0;
}
else
{
return (dec % 2 + 10 * convert(dec / 2));
}
}
It works just fine, but I am not able to understand dec % 2 + 10 * convert(dec / 2). Can you please convert this in an understandable way for people with basic math? e.g. what method is performed first and how does the binary dec = 50 turns to 110010?
FYI: I can do it, this way: 50=(2^5=32)+(2^4=16)+(2^1)=50
Thanks in advance.
I won't implement it for you, but I am happy to describe the algorithm and give an example.
Converting from base 10 to base b ultimately follows the same series of steps which includes repeatedly dividing by b then saving the remainder.
An example of what this looks like for 50 (base10) to base2 would be:
Quotient Remainder
----------------------------
50 / 2 = 25 0
25 / 2 = 12 1
12 / 2 = 6 0
6 / 2 = 3 0
3 / 2 = 1 1
1 / 2 = 0 1
Examining the remainders in reverse (bottom to top) gives your the correct representation in base b (2 in this case): 110010
For information on why this works, take a look at this question: https://math.stackexchange.com/questions/86207/converting-decimalbase-10-numbers-to-binary-by-repeatedly-dividing-by-2
Let's look at dec % 2 + 10 * convert(dec / 2). The first part dec % 2 is a modulo operation, and this is what decides if a digit should be 1 or 0. The rest, 10 * convert(dec / 2) finds the next (and next and next recursively) digit and puts it on the left of the current digit.
You could quite easily see what is going on by slightly modifying your code. Change the else to:
else
{
int ret = (dec % 2 + 10 * convert(dec / 2));
printf("%d %d\n", dec, ret);
return ret;
}
and then convert(50) will print this:
$ ./a.out
1 1
3 11
6 110
12 1100
25 11001
50 110010
But as pointed out in the comments, this is not a real base conversion. You have converted the number 50 to a completely different number that looks like the binary representation.
An algorithm that will, given an integer N, produce a string of characters S representing N in binary notation.
do
{
if N is odd
{
add '1' to the beginning of S
}
else
{
add '0' to the beginning of S
}
divide N by 2
}
while N is non-zero
Using the requested example:
initially N=50 and S is empty
50 is even: S="0"
divide N by 2: N=25
25 is odd: S="10"
divide N by 2: N=12
12 is even: S="010"
divide N by 2: N=6
6 is even: S="0010"
divide N by 2: N=3
3 is odd: S="10010"
divide N by 2: N=1
1 is odd: S="110010"
divide N by 2: N=0
stop looping

Given 5 numbers, by only using addition multiplication and substraction check whether we can generate 42?

Given five numbers between 1-52 check whether you can generate 42 by using operations addition, multiplication and subtraction. You can use these operations any number of times.
I got this question during an online test and couldn't do it.
Assuming each number is to be used once and once only, with only five numbers and three operations, you can quite easily do this with a brute force approach.
It will only have to check 5 * 3 * 4 * 3 * 3 * 3 * 2 * 3 * 1, or about 10,000 potential solutions.
As proof-of-concept, here's a Python program for doing this:
import sys
import itertools
if len(sys.argv) != 6:
print "Usage: testprog.py <num1> <num2> <num3> <num4> <num5>"
sys.exit(1)
ops = ['+', '-', '*']
nums = []
for num in sys.argv[1:]:
nums.append(num)
for p in itertools.permutations(nums,len(nums)):
for op1 in ops:
for op2 in ops:
for op3 in ops:
for op4 in ops:
expr = p[0] + op1 + p[1] + op2 + p[2] + op3 + p[3] + op4 + p[4]
result = eval(expr)
if result == 42:
print expr, '=', result
Running that shows the results for the numbers { 1, 2, 3, 4, 5 }:
pax$ time python testprog.py 1 2 3 4 5
2*4*5-1+3 = 42
2*4*5+3-1 = 42
2*5*4-1+3 = 42
2*5*4+3-1 = 42
:
5*4*2-1+3 = 42
5*4*2+3-1 = 42
real 0m0.187s
user 0m0.093s
sys 0m0.077s
and you can see that it completes in about a fifth of a second (on my box).
assumtions:
any number may be used multiple times
operations are done immediately (no operator precedence)
do a breadth first search over the graph
from collections import defaultdict
def add(lhs, rhs):
return lhs+rhs
def sub(lhs, rhs):
return lhs-rhs
def mul(lhs, rhs):
return lhs*rhs
ops = [add, sub, mul] #allowed operations
graph = { 0:["0"]} #graph key is node(number); value is a list of shortest paths to this node
numbers=[1,2,3] #allowed numbers in operations
target=12 #target node(number)
gv_edges=[] #edges for optional graphviz output
#breadth first search until target is met
while not target in graph:
new_graph=defaultdict(list, graph)
for key in graph:
#inefficiently searches old nodes also
for n in numbers:
for op in ops:
newkey = op(key, n)
if newkey not in graph:
#not met in previous iterations, keep new edge
newvals = ["{} --{}({})--> {}".format(val, op.__name__, n, newkey) for val in new_graph[key]]
new_graph[newkey].extend(newvals)
gv_edges.append('"{}" -> "{}" [label="{}({})"]'.format(key, newkey, op.__name__, n))
else:
#already met in previous iterations (shorter paths), do not keep new
pass
graph=dict(new_graph)
#print all solutions
print "Solutions:"
print
for val in graph[target]:
print val
print
print
#print optional graphviz digraph
gv_digraph='digraph {{ rankdir=LR ranksep=2\n"{}" [color=green style=filled fillcolor=green]\n{}\n}}'.format(target,"\n".join(gv_edges))
print "Graphviz Digraph for paste into http://stamm-wilbrandt.de/GraphvizFiddle/"
print "do this for reasonable number of edges only"
print
print gv_digraph
results in the following solutions:
0 --add(1)--> 1 --add(3)--> 4 --mul(3)--> 12
0 --add(2)--> 2 --add(2)--> 4 --mul(3)--> 12
0 --add(2)--> 2 --mul(2)--> 4 --mul(3)--> 12
0 --add(3)--> 3 --add(1)--> 4 --mul(3)--> 12
0 --add(2)--> 2 --mul(3)--> 6 --mul(2)--> 12
0 --add(3)--> 3 --mul(2)--> 6 --mul(2)--> 12
0 --add(3)--> 3 --add(3)--> 6 --mul(2)--> 12
0 --add(3)--> 3 --mul(3)--> 9 --add(3)--> 12
the complete graph (only shortest paths!) for depth 3 looks like

Identify gaps in repeated sequences

I have a vector that should contain n sequences from 00 to 11
A = [00;01;02;03;04;05;06;07;08;09;10;11;00;01;02;03;04;05;06;07;08;09;10;11]
and I would like to check that the sequence "00 - 11 " is always respected (no missing values).
for example if
A =[00;01;02; 04;05;06;07;08;09;10;11;00;01;02;03;04;05;06;07;08;09;10;11]
(missing 03 in the 3rd position)
For each missing value I would like to have back this information in another vector
missing=
[value_1,position_1;
value_2, position_2;
etc, etc]
Can you help me?
For sure we know that the last element must be 11, so we can already check for this and make our life easier for testing all previous elements. We ensure that A is 11-terminated, so an "element-wise change" approach (below) will be valid. Note that the same is true for the beginning, but changing A there would mess with indices, so we better take care of that later.
missing = [];
if A(end) ~= 11
missing = [missing; 11, length(A) + 1];
A = [A, 11];
end
Then we can calculate the change dA = A(2:end) - A(1:end-1); from one element to another, and identify the gap positions idx_gap = find((dA~=1) & (dA~=-11));. Now we need to expand all missing indices and expected values, using ev for the expected value. ev can be obtained from the previous value, as in
for k = 1 : length(idx_gap)
ev = A(idx_gap(k));
Now, the number of elements to fill in is the change dA in that position minus one (because one means no gap). Note that this can wrap over if there is a gap at the boundary between segments, so we use the modulus.
for n = 1 : mod(dA(idx_gap(k)) - 1, 12)
ev = mod(ev + 1, 12);
missing = [missing; ev, idx_gap(k) + 1];
end
end
As a test, consider A = [5 6 7 8 9 10 3 4 5 6 7 8 9 10 11 0 1 2 3 4 6 7 8]. That's a case where the special initialization from the beginning will fire, memorizing the missing 11 already, and changing A to [5 6 ... 7 8 11]. missing then will yield
11 24 % recognizes improper termination of A.
11 7
0 7 % properly handles wrap-over here.
1 7
2 7
5 21 % recognizes single element as missing.
9 24
10 24
which should be what you are expecting. Now what's missing still is the beginning of A, so let's say missing = [0 : A(1) - 1, 1; missing]; to complete the list.
This will give you the missing values and their positions in the full sequence:
N = 11; % specify the repeating 0:N sub-sequence
n = 3; % reps of sub-sequence
A = [5 6 7 8 9 10 3 4 5 6 7 8 9 10 11 0 1 2 3 4 6 7 8]'; %' column from s.bandara
da = diff([A; N+1]); % EDITED to include missing end
skipLocs = find(~(da==1 | da==-N));
skipLength = da(skipLocs)-1;
skipLength(skipLength<0) = N + skipLength(skipLength<0) + 1;
firstSkipVal = A(skipLocs)+1;
patchFun = #(x,y)(0:y)'+x - (N+1)*(((0:y)'+x)>N);
patches = arrayfun(patchFun,firstSkipVal,skipLength-1,'uni',false);
locs = arrayfun(#(x,y)(x:x+y)',skipLocs+cumsum([A(1); skipLength(1:end-1)])+1,...
skipLength-1,'uni',false);
Then putting them together, including any missing values at the beginning:
>> gapMap = [vertcat(patches{:}) vertcat(locs{:})-1]; % not including lead
>> gapMap = [repmat((0 : A(1) - 1)',1,2); gapMap] %' including lead
gapMap =
0 0
1 1
2 2
3 3
4 4
11 11
0 12
1 13
2 14
5 29
9 33
10 34
11 35
The first column contains the missing values. The second column is the 0-based location in the hypothetical full sequence.
>> Afull = repmat(0:N,1,n)
>> isequal(gapMap(:,1), Afull(gapMap(:,2)+1)')
ans =
1
Although this doesn't solve your problem completely, you can identify the position of missing values, or of groups of contiguous missing values, like this:
ind = 1+find(~ismember(diff(A),[1 -11]));
ind gives the position with respect to the current sequence A, not to the completed sequence.
For example, with
A =[00;01;02; 04;05;06;07;08;09;10;11;00;01;02;03; ;06;07;08;09;10;11];
this gives
>> ind = 1+find(~ismember(diff(A),[1 -11]))
ind =
4
16

Resources