Change the inequality in binary search code - algorithm

shouldn't be
if(a[mid] < t)return BS(mid+1,high);
else return BS(low,mid);
the same as
if(a[mid] > t)return BS(low,mid-1);
else return BS(mid,high);
But the second one doesn't work, why?
Edit: I mean by doesn't work, that the code doesn't reach the base case.

In calculating mid as (low+high)/2 it uses integer division.
In Bref. By example
Let low = 3 , high = 4 , a[3] >= t
so by calling BS(low,high)
mid = (3+4)/2 = 3 #Integer_division
Since a[mid] >=t So return BS(mid,high) which is equivalent to BS(low,high) #infinite_loop
The solution use the integer division in your side So the code should be like
if(a[mid] >= t)return BS(low,mid);
else return BS(mid+1,high);
Think this will solve your issue.

Related

Programming Pearls: Column 9.3 Binary Search - range initialization

In Section 9.3 Job Bentley presents a modified binary search..
a brief snip of the typical implementation and the better approach shown in 9.3
if (arr[mid] < key) low = mid+1
else if (arr[mid] > key) high = mid-1
else return mid;
modified/efficient comparison with a different invariant..
if (arr[mid] < key) low = m;
else high = m;
And outside the loop there is a check if the key at the index 'high'. In the modified binary search the left index 'low' starts at -1 (instead of 0) and 'high' index starts at n (instead of n-1).. and the loop runs
while (low + 1 != high)
This modified search seems to work even if I set low = 0 and high = n-1.
But I would rather not second guess Job Bentley in his code. So why is he setting low to -1 and high to n ? Is there any corner case where only this will work ?
If you have an array that is empty (n == 0), then a check of while(low + 1 != high) will only correctly terminate if low begins at -1 and high at 0.
while((-1 + 1) != 0) //true
If low began at 0 instead, or high began at -1 (or both), then the loop will clearly perform at least one check:
while((0 + 1) != 0) // false
while((-1 + 1) != -1) // false
while((0 + 1) != -1) // false
That one check on an empty array will likely access an out of bounds index, which invokes undefined behavior.

Looping in an array to attain nearest larger integer

Below is my code to solve the following problem:
Write a function, nearest_larger(arr, i) which takes an array and an
index. The function should return another index, j: this should
satisfy:
(a) arr[i] < arr[j], AND
(b) there is no j2 closer to i than j where arr[i] < arr[j].
In case of ties choose the earliest (left-most)
of the two indices. If no number in arr is larger than arr[i],
return nil.
This was my attempt:
def nearest_larger(arr, i)
k = 1
loop do
jleft = i - k
jright = i + k
if (arr[i] < arr[jleft]) && (jleft >= 0)
return jleft
elsif (arr[i] < arr[jright]) && (jright < arr.length)
return jright
elsif (jleft < 0) && (jright >= arr.length)
return nil
end
k += 1
end
end
This is the actual correct answer
def nearest_larger(arr, idx)
diff = 1
loop do
left = idx - diff
right = idx + diff
if (left >= 0) && (arr[left] > arr[idx])
return left
elsif (right < arr.length) && (arr[right] > arr[idx])
return right
elsif (left < 0) && (right >= arr.length)
return nil
end
diff += 1
end
end
While my code works well for many of the values I tested when I use certain combinations like this:
x = [1,6,9,4,5]
puts nealest_larger(x, 4)
I get this error
calc.rb:8:in `<': comparison of Fixnum with nil failed (ArgumentError)
from calc.rb:8:in `block in nealest_larger'
from calc.rb:3:in `loop'
from calc.rb:3:in `nealest_larger'
from calc.rb:40:in `<main>'
Can someone tell me how my code differs from the actual answer, to me it seems like it should behave exactly the same but I must have missed some syntax or overlooked a piece of logic. I need another pair of eyes as I am unable to see the difference, thanks!
Your version uses array indices before you've checked that they're in-bounds, i.e., on the left-hand side of the &&. The working version checks for in-bounds first, then uses the index if it's legal. Because Ruby && short circuits, test && use approach avoids the problem you ran into with your implementation.
The 8th line of code in your solution compares the values in the array before first checking the bounds of the array. Notice the correct solution does those comparisons in the reverse order, and the && operator short circuits, avoiding the second (invalid) comparison.

Best practice to evaluate permutations

I came across this question, where the OP wanted to improve the following if-block. I open this as a new question because I'm searching a more general solution to this kind of problem.
public int fightMath(int one, int two) {
if(one == 0 && two == 0) { result = 0; }
else if(one == 0 && two == 1) { result = 0; }
else if(one == 0 && two == 2) { result = 1; }
else if(one == 0 && two == 3) { result = 2; }
else if(one == 1 && two == 0) { result = 0; }
else if(one == 1 && two == 1) { result = 0; }
else if(one == 1 && two == 2) { result = 2; }
else if(one == 1 && two == 3) { result = 1; }
else if(one == 2 && two == 0) { result = 2; }
else if(one == 2 && two == 1) { result = 1; }
else if(one == 2 && two == 2) { result = 3; }
else if(one == 2 && two == 3) { result = 3; }
else if(one == 3 && two == 0) { result = 2; }
else if(one == 3 && two == 1) { result = 1; }
else if(one == 3 && two == 2) { result = 3; }
else if(one == 3 && two == 3) { result = 3; }
return result;
}
Now there are n^k possibilities to get a result, where n = 2 and k = 4.
Some answers are suggesting to use an multi-array as a table to reduce the if-jungle.
But I would like to know how to solve such a problem with big n and k? Because a solution with if, switch and the suggested array approach will not scale well and to type things like that in code should be avoided.
If I think about combinatoric problems, there have to be a way to evaluate them easy.
It's just a table of data. The answer to the question is found by multiple keys. It is no different to returning some data held in a database table which could itself be huge and perhaps span multiple tables.
There are two ways to solve this:
Data-based. For example you could create a HashMap mapping the pair of values to the result.
class Pair {
int one, two;
//Generate hashcode and equals
}
Map<Pair, Integer> counts = new HashMap<>();
Pattern-based. Identify a rule/formula that can be used to determine the new value.
This is obviously better but relies on being able to identify a rule that covers all cases.
I would like to know how to solve such a problem with big n and k.
Since the output is determined arbitrarily (a game designer's whims) instead of mathematically (a formula), there's no guarantee of any pattern. Therefore the only general solution is some kind of lookup table.
Essentially, the question is similar to asking for a program that does f(a,b) -> c mapping, but you don't know any of the data beforehand -- instead it's provided at runtime. That program could process the data and find a pattern/formula (which might not exist) or it could build a lookup table.
Personally, I think it's clearer to change the logic to operate on intent (so reading the code explains how the attack works) instead of the actual outcomes (enumerating the list of inputs and matching outputs). Instead of building an if-jungle or a lookup table, structure your code based on how you want the logic to work. JAB's enum-based solution expresses the fight logic explicitly which makes it easier to see where to add new functionality and easier to see bugs (an off by one error in a lookup table isn't obviously wrong on inspection). A lookup table is a likely optimization, but that's only necessary if a profiler says so.
Looking at your question and the original one there appears to be no deducible pattern between the input from the two players and the output (perhaps I'm wrong). Given this the only options are the "if-jungle" you mention or to use a data structure.
To solve such a problem for big n and k values my suggestion would be to create a rule to determine the output (either none, one or both players hit), but ensuring that this rule isn't easily deducible to the players. You could do this by making the rule a function of turn number (e.g. if both players press button 1 on turn #1 the output will be different to if they take the same action on turn #2).

native string matching algorithm

Following is a very famous question in native string matching. Please can someone explain me the answer.
Suppose that all characters in the pattern P are different. Show how to accelerate NAIVE-STRING MATCHER to run in time O(n) on an n-character text T.
The basic idea:
Iterate through the input and the pattern at the same time, comparing their characters to each other
Whenever you get a non-matching character between the two, you can just reset the pattern position and keep the input position as is
This works because the pattern characters are all different, which means that whenever you have a partial match, there can be no other match overlapping with that, so we can just start looking from the end of the partial match.
Here's some pseudo-code that shouldn't be too difficult to understand:
input[n]
pattern[k]
pPos = 0
iPos = 0
while iPos < n
if pPos == k
FOUND!
if pattern[pPos] == input[iPos]
pPos++
iPos++
else
// if pPos is already 0, we need to increase iPos,
// otherwise we just keep comparing the same characters
if pPos == 0
iPos++
pPos = 0
It's easy to see that iPos increases at least every second loop, thus there can be at most 2n loop runs, making the running time O(n).
When T[i] and P[j] mismatches in NAIVE-STRING-MATCHER, we can skip all characters before T[i] and begin new matching from T[i + 1] with P[1].
NAIVE-STRING-MATCHER(T, P)
1 n length[T]
2 m length[P]
3 for s 0 to n - m
4 do if P[1 . . m] = T[s + 1 . . s + m]
5 then print "Pattern occurs with shift" s
Naive string search algorithm implementations in Python 2.7:
https://gist.github.com/heyhuyen/4341692
In the middle of implementing Boyer-Moore's string search algorithm, I decided to play with my original naive search algorithm. It's implemented as an instance method that takes a string to be searched. The object has an attribute 'pattern' which is the pattern to match.
1) Here is the original version of the search method, using a double for-loop.
Makes calls to range and len
def search(self, string):
for i in range(len(string)):
for j in range(len(self.pattern)):
if string[i+j] != self.pattern[j]:
break
elif j == len(self.pattern) - 1:
return i
return -1
2) Here is the second version, using a double while-loop instead.
Slightly faster, not making calls to range
def search(self, string):
i = 0
while i < len(string):
j = 0
while j < len(self.pattern) and self.pattern[j] == string[i+j]:
j += 1
if j == len(self.pattern):
return i
i += 1
return -1
3) Here is the original, replacing range with xrange.
Faster than both of the previous two.
def search(self, string):
for i in xrange(len(string)):
for j in xrange(len(self.pattern)):
if string[i+j] != self.pattern[j]:
break
elif j == len(self.pattern) - 1:
return i
return -1
4) Storing values in local variables = win! With the double while loop, this is the fastest.
def search(self, string):
len_pat = len(self.pattern)
len_str = len(string)
i = 0
while i < len_str:
j = 0
while j < len_pat and self.pattern[j] == string[i+j]:
j += 1
if j == len_pat:
return i
i += 1
return -1

What is the difference between these two find algorithms?

I have these two find algorithm which look the same to me. Can anyone help me out why they are actually different?
Find ( x ) :
if x.parent = x then
return x
else
return Find ( x.parent )
vs
Find ( x ) :
if x.parent = x then
return x
else
x.parent <- Find(x.parent)
return x.parent
I interpret the first one as
int i = 0;
return i++;
while the second one as
int i = 0;
int tmp = i++;
return tmp
which are exactly the same to me.
This looks like Disjoint-set data structure.
Now to the question:
For the sake of clarity first version is FindA, second is FindB.
Suppose you have structure:
0
|
1
|
2
|
...
n
First call to FindA(n) will return 0 in O(n), second call will return 0 in O(n) and so on.
If you call FindB(n) it will return 0 in O(n), but will also modify structure:
0
/ /|\
1 2...n
Now second call to FindB(n) will return 0 in O(1). More over FindB(k) will return 0 in O(1).
The second one will change the value of x.parent as a side effect to the result of find

Resources