Hoare Logic Loop variant on user specified value - logic

I have the following problem:
pre-condition is True
int n = askUser();
int i = 0;
while(i<n){
...
i++;
}
The variant I am thinking of is: n-i.
However, I don't think there is anything that stops the user from supplying a negative value, and in that case the variant will be negative (which contradicts its definition).
Is it possible to specify the invariant as |n| - i, or does n>=0 has to be included as pre-condition?
Any help or suggestions will be greatly appreciated.

Related

What is the purpose of this method?

in an interview question, I got asked the following:
What is the purpose of the below method, and how can we rewrite it?
public int question_1(int a, int b)
{
while (a > b)
{
a -= b;
}
return a;
}
at first I thought it is equivalent to a%b, but it is not since it is "while (a > b)" and not "while ( a >= b)".
Thanks
Honestly, it's impossible to know the purpose of a method just by reading its implementation, even if we assume that it's bug-free.
But, we can start by documenting its behaviors:
If b is positive:
If a is positive, the method returns the least positive integer that is congruent to a modulo b. (For example, given 15 and 10, it will return 5; given 30 and 10, it will return 10.)
Otherwise, the method returns a.
If b is zero:
If a is positive, the method loops forever.
Otherwise, the method returns a.
If b is negative:
If a ≤ b, the method returns a.
Otherwise, the method's behavior depends on the language, since it will increase a until it's no longer greater than b. If the language defines integer arithmetic using "wraparound" rules, then the method will loop for a long time, then finally return a very negative number (unless b is itself very negative, in which case, depending on the value of a, the function might loop forever).
and given these, we can infer that the behaviors with zero and negative numbers are bizarre enough that the method is probably actually only intended to be used with positive numbers. So its behavior can be summarized as:
If a and b are both positive, then the method returns the least positive integer that is congruent to a modulo b.
If the above inference is correct, then the method can be rewritten as:
public int question_1(int a, int b) {
if (a <= 0 || b <= 0)
throw new IllegalArgumentException();
return (a - 1) % b + 1;
}
I would guess that its purpose is to compute a%b for positive ints, and that it has a bug.
If I saw this in production, I would have to check the uses of this function to see if question_1(n,n) == n is really correct. If so, I'd add a comment indicating why that is so. Otherwise I'd fix it.
It either case, it could be rewritten to use the % operator instead of a loop. If it's correct, it could be rewritten like this:
public int question_1(int a, int b)
{
if (a>b)
{
a = ((a-1)%b) + 1;
}
return a;
}
This is not the same in its handling of negative numbers, though, so again you'd have to check to make sure that's OK.
The reason I provide this answer when #ruakh has already provided such a carefully considered answer is that this is an interview question, so it's best if you take the opportunity to show how you would approach a problem like this on the job.
You don't really want to give the impression that you would spend a long time and a lot of effort thinking carefully about such a simple problem -- if you have to spend that much effort to solve a simple problem, imagine what you would spend on a big one!
At the same time, you want to demonstrate that you recognize the possible bug, and take the initiative to fix it or to spare future engineers the same task.

Instance of subset sum problem

I have a problem which is a pretty clear instance of the subset sum problem:
"given a list of Integers in the range [-65000,65000], the function returns true if any subset of the list summed is equal to zero. False otherwise."
What I wanted to ask is more of an explanation than a solution.
This was an instance-specific solution I came up before thinking about the complexity of the problem.
Sort the array A[] and, during sort, sum each element to a counter 'extSum' (O(NLogN))
Define to pointers low = A[0] and high = A[n-1]
Here is the deciding code:
while(A[low]<0){
sum = extSum;
if(extSum>0){
while(sum - A[high] < sum){
tmp = sum - A[high];
if(tmp==0) return true;
else if(tmp > 0){
sum = tmp;
high--;
}
else{
high--;
}
}
extSum -= A[low];
low++;
high = n - 1;
}
else{
/* Symmetric code: switch low, high and the operation > and < */
}
}
return false;
First of all, is this solution correct? I made some tests, but I am not sure...it looks too easy...
Isn't the time complexity of this code O(n^2)?
I already read the various DP solutions and the thing I would like to understand is, for the specific instance of the problem I am facing, how much better than this naive and intuitive solution they are. I know my approach can be improved a lot but nothing that would make a big difference when it comes to the time complexity....
Thank you for the clarifications
EDIT: One obvious optimization would be that, while sorting, if a 0 is found, the function returns true immediately....but it's only for the specific case in which there are 0s in the array.
Hmm, I think {0} will beat your answer.
Because it will simply ignore while and return false.

Algorithm to find duplicate in an array

I have an assignment to create an algorithm to find duplicates in an array which includes number values. but it has not said which kind of numbers, integers or floats. I have written the following pseudocode:
FindingDuplicateAlgorithm(A) // A is the array
mergeSort(A);
for int i <- 0 to i<A.length
if A[i] == A[i+1]
i++
return A[i]
else
i++
have I created an efficient algorithm?
I think there is a problem in my algorithm, it returns duplicate numbers several time. for example if array include 2 in two for two indexes i will have ...2, 2,... in the output. how can i change it to return each duplicat only one time?
I think it is a good algorithm for integers, but does it work good for float numbers too?
To handle duplicates, you can do the following:
if A[i] == A[i+1]:
result.append(A[i]) # collect found duplicates in a list
while A[i] == A[i+1]: # skip the entire range of duplicates
i++ # until a new value is found
Do you want to find Duplicates in Java?
You may use a HashSet.
HashSet h = new HashSet();
for(Object a:A){
boolean b = h.add(a);
boolean duplicate = !b;
if(duplicate)
// do something with a;
}
The return-Value of add() is defined as:
true if the set did not already
contain the specified element.
EDIT:
I know HashSet is optimized for inserts and contains operations. But I'm not sure if its fast enough for your concerns.
EDIT2:
I've seen you recently added the homework-tag. I would not prefer my answer if itf homework, because it may be to "high-level" for an allgorithm-lesson
http://download.oracle.com/javase/1.4.2/docs/api/java/util/HashSet.html#add%28java.lang.Object%29
Your answer seems pretty good. First sorting and them simply checking neighboring values gives you O(n log(n)) complexity which is quite efficient.
Merge sort is O(n log(n)) while checking neighboring values is simply O(n).
One thing though (as mentioned in one of the comments) you are going to get a stack overflow (lol) with your pseudocode. The inner loop should be (in Java):
for (int i = 0; i < array.length - 1; i++) {
...
}
Then also, if you actually want to display which numbers (and or indexes) are the duplicates, you will need to store them in a separate list.
I'm not sure what language you need to write the algorithm in, but there are some really good C++ solutions in response to my question here. Should be of use to you.
O(n) algorithm: traverse the array and try to input each element in a hashtable/set with number as the hash key. if you cannot enter, than that's a duplicate.
Your algorithm contains a buffer overrun. i starts with 0, so I assume the indexes into array A are zero-based, i.e. the first element is A[0], the last is A[A.length-1]. Now i counts up to A.length-1, and in the loop body accesses A[i+1], which is out of the array for the last iteration. Or, simply put: If you're comparing each element with the next element, you can only do length-1 comparisons.
If you only want to report duplicates once, I'd use a bool variable firstDuplicate, that's set to false when you find a duplicate and true when the number is different from the next. Then you'd only report the first duplicate by only reporting the duplicate numbers if firstDuplicate is true.
public void printDuplicates(int[] inputArray) {
if (inputArray == null) {
throw new IllegalArgumentException("Input array can not be null");
}
int length = inputArray.length;
if (length == 1) {
System.out.print(inputArray[0] + " ");
return;
}
for (int i = 0; i < length; i++) {
if (inputArray[Math.abs(inputArray[i])] >= 0) {
inputArray[Math.abs(inputArray[i])] = -inputArray[Math.abs(inputArray[i])];
} else {
System.out.print(Math.abs(inputArray[i]) + " ");
}
}
}

Dynamic programming problems

I'm looking for some pointers about a dynamic programming problem. I cannot find any relevant information about how to solve this kind of problem. The only kind of problem I know how to solve using dynamic programming is when I have two sequences and create a matrix of those sequences. But I don't see how I can apply that to the following problem...
If I have a set A = {7,11,33,71,111} and a number B. Then C which is a subset of A, contains the elements from A which builds the sum B.
EXAMPLE:
A = {7,11,33,71,111}
If B = 18, then C = {7,11} (because 7+11 = 18)
If B = 3, then there is no solution
Thankful for any help here, I just don't know how to think when solving these kind of problems. I cannot find any general method either, only some examples on gene sequences and stuff like that.
Dynamic programming is a broad category of solutions wherein a partial solution is kept in some structure for the next iteration to build upon instead of having it recalculate the intermediate results over and over again.
If I were to take a dynamic approach to this particular problem, I would probably keep a running list of every sum calculable from the previous step, as well as the set used to compute that sum.
So for example the first iteration my working set would contain {null, 7}, then I would add 11 to everything in that that set as well as the set itself (let's pretend that null+11=11 for now). Now my working set would contain {null, 7, 11, 18}. For each value in the set, I would keep track of how I got that result: so 7 maps to the original set {7} and 18 maps to the original set {7,11}. Iteration would end when either A) the target value is generated or B) the original set is exhausted without finding the value. You could optimize the negative case with an ordered set, but I'll leave figuring that out to you.
There is more than one way to approach this problem. This is a dynamic solution, and it's not very efficient as it needs to build a set of 2^(size of set) members. But the general approach corresponds to what dynamic programming was created to solve.
I think dynamic approach depend on B and number elements of A.
I suggested a dynamic approach in this case with B*number element of A <= 1.000.000
Use call F[i,j] is true if use can use from A[1] to A[j] to build i and false otherwise
So each step you have to choise:
use a[j] then F[i,j]=F[i-a[j],j-1]
don't user a[j] then F[i,j] = F[i,j-1]
Then if existing a F[B,*]=1 ,you can build B.
Bellow is example code:
#include<stdio.h>
#include<iostream>
using namespace std;
int f[1000][1000], a[1000], B,n;
// f[i][j] = 1 => can build i when using A[1]..a[j], 0 otherwisw
int tmax(int a, int b){
if (a>b) return a;
return b;
}
void DP(){
f[0][0] = 1;
for (int i=1;i<=B;i++)
for (int j=1;j<=n;j++)
{
f[i][j] = f[i][j-1];
if (a[j]<=i)
f[i][j] = tmax(f[i-a[j]][j-1], f[i][j]);
}
}
int main(){
cin >> n >> B;
for (int i=1;i<=n;i++) cin >>a[i];
DP();
bool ok = false;
for (int i=1;i<=n;i++){
if (f[B][i]==1) {
cout<<"YES";
ok = true;
break;
}
}
if (!ok) cout <<"NO";
}

Linear Time Voting Algorithm. I don't get it

As I was reading this (Find the most common entry in an array), the Boyer and Moore's Linear Time Voting Algorithm was suggested.
If you follow the link to the site, there is a step by step explanation of how the algorithm works. For the given sequence, AAACCBBCCCBCC it presents the right solution.
When we move the pointer forward over
an element e:
If the counter is 0, we set the current candidate to e and we set the
counter to 1.
If the counter is not 0, we increment or decrement the counter
according to whether e is the current
candidate.
When we are done, the current
candidate is the majority element, if
there is a majority.
If I use this algorithm on a piece of paper with AAACCBB as input, the suggested candidate would become B what is obviously wrong.
As I see it, there are two possibilities
The authors have never tried their algorithm on anything else than AAACCBBCCCBCC, are completely incompetent and should be fired on the spot (doubtfull).
I am clearly missing something, must get banned from Stackoverflow and never be allowed again to touch anything involving logic.
Note: Here is a a C++ implementation of the algorithm from Niek Sanders. I believe he correctly implemented the idea and as such it has the same problem (or doesn't it?).
The algorithm only works when the set has a majority -- more than half of the elements being the same. AAACCBB in your example has no such majority. The most frequent letter occurs 3 times, the string length is 7.
Small but an important addition to the other explanations. Moore's Voting algorithm has 2 parts -
first part of running Moore's Voting algorithm only gives you a candidate for the majority element. Notice the word "candidate" here.
In the second part, we need to iterate over the array once again to determine if this candidate occurs maximum number of times (i.e. greater than size/2 times).
First iteration is to find the candidate & second iteration is to check if this element occurs majority of times in the given array.
So time complexity is: O(n) + O(n) ≈ O(n)
From the first linked SO question:
with the property that more than half of the entries in the array are equal to N
From the Boyer and Moore page:
which element of a sequence is in the majority, provided there is such an element
Both of these algorithms explicitly assume that one element occurs at least N/2 times. (Note in particular that "majority" is not the same as "most common.")
I wrote a C++ code for this algorithm
char find_more_than_half_shown_number(char* arr, int len){
int i=0;
std::vector<int> vec;
while(i<len){
if(vec.empty()){
vec.push_back(arr[i]);
vec.push_back(1);
}else if(vec[0]==arr[i]){
vec[1]++;
}else if(vec[0]!=arr[i]&&vec[1]!=0){
vec[1]--;
}else{
vec[0]=arr[i];
}
i++;
}
int tmp_count=0;
for(int i=0;i<len;i++){
if(arr[i]==vec[0])
tmp_count++;
}
if(tmp_count>=(len+1)/2)
return vec[0];
else
return -1;
}
and the main function is as below:
int main(int argc, const char * argv[])
{
char arr[]={'A','A','A','C','C','B','B','C','C','C','B','C','C'};
int len=sizeof(arr)/sizeof(char);
char rest_num=find_more_than_half_shown_number(arr,len);
std::cout << "rest_num="<<rest_num<<std::endl;
return 0;
}
When the test case is "AAACCBB", the set has no majority. Because no element occurs more than 3 times since the length of "AAACCBB" is 7.
Here's the code for "the Boyer and Moore's Linear Time Voting Algorithm":
int Voting(vector<int> &num) {
int count = 0;
int candidate;
for(int i = 0; i < num.size(); ++i) {
if(count == 0) {
candidate = num[i];
count = 1;
}
else
count = (candidate == num[i]) ? ++count : --count;
}
return candidate;
}

Resources