Well, I was going through some code and found this piece of code and am confused at statement 1.
vector<int> v{1,2,3,2};
mp<int,int> m;
for(auto i : v) m[i]++;
int ans = v.size();
for(auto i : v){
ans = min(ans, m[i] + 1 - (v.front() == i) - (v.back() == i)); //statement 1
}
The logic behind statement 1 is that if v contains element i in the front or the end then subtract 1 from the occurrence of i in map. It somehow is working correctly but how? I haven't seen such type of implementation of if before. Can someone please help how statement 1 if considering (v.front() == i) and (v.back() == i) as an if statement without mentioning any if keyword.
The expression v.front() == i evaluates to a bool that's either true or false.
A bool can be implicitly converted to an int with the value 1 or 0.
This is the same as when doing if (v.front() == i). The expression v.front() == i is again a bool true or false.
Related
I tried to solve this exercise
I got 66 percent
I can not understand why
can you help?
The exercise is:
Write a function:
int solution(vector &A);
that, given an array A of N integers, returns the smallest positive integer (greater than 0) that does not occur in A.
For example, given A = [1, 3, 6, 4, 1, 2], the function should return 5.
Given A = [1, 2, 3], the function should return 4.
Given A = [−1, −3], the function should return 1.
The solution I wrote is:
#include <algorithm>
#include<cmath>
using namespace std;
int solution(vector<int> &A) {
if (A.size() == 0 || (A.size() == 1 && A.at(0) <= 0))
return 1;
if (A.size() == 1)
return A.at(0) + 1;
sort(A.begin(), A.end());
if (A.at(A.size() - 1) <= 0)
return 1;
auto ip = std::unique(A.begin(), A.end());
A.resize(distance(A.begin(), ip));
A.erase(remove_if(A.begin(), A.end(), [](const int i) { return i < 0; }),A.end());
if (A.at(0) != 1)
return 1;
if (A.size() == 1)
return (A.at(0) != 1 ? 1 : 2);
int i = 0;
for (; i < A.size(); ++i) {
if (A.at(i) != i + 1)
return A.at(i - 1) + 1;
}
return A.at(A.size()) + 1;
}
The following algorithm has a complexity O(n). No need to sort or to erase.
We know that the first missing value is less or equal to n+1, if n is the array size.
Then we simply have to use an array of size n+2, present[n+2], initialised to 0, and then to look at all values A[i]:
if (A[i] <= 1+n && A[i] > 0) present[A[i]] = 1;
Finally, in a second step we simply have to examine the array present[.], and search for the first index k such that present[k]==0.
#include <iostream>
#include <vector>
int find_missing (const std::vector<int> &A) {
int n = A.size();
std::vector<int> present (n+2, 0);
int vmax = n+1;
for (int i = 0; i < n; ++i) {
if (A[i] <= vmax && A[i] > 0) {
present[A[i]] = 1;
}
}
for (int k = 1; k <= vmax; ++k) {
if (present[k] == 0) return k;
}
return -1;
}
int main() {
std::vector<int> A = {1, 2, 0, 3, -3, 5, 6, 8};
int missing = find_missing (A);
std::cout << "First missing element = " << missing << std::endl;
return 0;
}
Well this is wrong
if(A.size()==1)
return A.at(0)+1;
If A is {2} that code will return 3 when the correct answer is 1
Also
A.erase(remove_if(A.begin(), A.end(),[](const int i) {return i < 0; }),A.end());
should be
A.erase(remove_if(A.begin(), A.end(),[](const int i) {return i <= 0; }),A.end());
Also
return A.at(A.size()) + 1;
is a guaranteed vector out of bounds error.
Even a small amount of testing and debugging would have caught these errors. It's a habit you should get into.
I think there are far too many special cases in the code, which only serve to complicate the code and increase the chance of bugs.
This answer is the implementation of the proposal given in the comment by PaulMcKenzie.
So, all credits go to PaulMcKenzie
It is not the fastest solution, but compact. The idea is basically.
Sort the data
Then compare the adjacent values, if the next value is equal to the previous value+1.
If not, then we found a gap. This can be implemented by using the function std::adjacent_find. Description can be found here.
We put all the side conditions into the lambda. If std::adjacent_find cannot find a value, then we take the next possible positive value.
I am not sure, what I could describe more. Please see the below example:
#include <iostream>
#include <vector>
#include <algorithm>
int solution(std::vector<int>& data) {
// Sort
std::sort(data.begin(), data.end());
// Check if there is a gap in the positive values
const auto gap = std::adjacent_find(data.begin(), data.end(), [](const int p, const int n) { return (n !=p) && (n != (p + 1) && p>0); });
// If there is no gap, the take the next positive value
return (gap == data.end()) ? (data.back() > 0 ? data.back() + 1 : 1) : *gap + 1;
}
int main() {
//Some test cases
std::vector<std::vector<int>> testCases{
{1,3,6,4,1,2},
{1,2,3},
{-1,-3}
};
for (auto& testCase : testCases)
std::cout << solution(testCase) << '\n';
return 0;
}
others have already pointed out what are the main errors, but I would like to invite you to try a different solution instead of trying to fix all the bugs and spend much time on debugging, because your solution seems a little overcomplicated.
Here I propose a way you can think about the problem:
What is the minimum number the function can return? Since it returns a positive integer, it is 1, in the case 1 is not in the array. Since that we can use any number <=0 to see if we found our result scanning the vector (see next);
In case one is not in the array, how do I find the wanted number? Your intuition is correct, if your vector is sorted it is easier: you can iterate over your data, and when you find an "hole" between two subsequent elements, then the value of the first element of the hole + 1 is you result
What do I do if the array contains 1 and has no holes? Well, you return the smallest element that is not in the array, so the last element + 1. You may notice that by checking if your "candidate" value (that is a number that shouldn't be returned, so <=0) has changed during the scanning;
Let's go to the code:
int solution(std::vector<int>& v){
int retVal=0;
std::sort(v.begin(), v.end());
for(int i=0; i<v.size()-1; i++){
if(v[i]>0 && v[i+1]>v[i]+1){
retVal=v[i]+1;
break;
}
}
if(retVal==0) {
if (v.back() > 0)
retVal = v.back() + 1;
else
retVal = 1;
}
return retVal;
}
As suggested you can use the standard library a little bit more, but I think this is reasonably simple and efficient.
Other note:
I think your assignment does not bother you with this, but I mention just for completeness. Most of the times you don't want a function to modify your parameters: you can pass the vector "by value" meaning that actually you pass a complete copy of your data, without touching the original one, or you can pass a const reference and create a copy inside the function.
This function looks for an integer 'key' in a given vector from a position 'start'. It returns the position of key if it finds it. But if it does not find key, it should return -1.
However, it is only returning -1 as the output. The function works fine if the else statement is removed, but obviously I need it.
So what is wrong in this function? Please explain in simple terms, I am new to C++. Thank you for all your help.
int Sequential_Search(const vector<int>&v, int key, int start){
int result = 0;
int i;
for(i = start; i < v.size(); i++){
if(v[i] == key){
result = i;
}
else{
result = -1;
}
}
return result;
}
This is pretty easy to understand:
for(i = start; i < v.size(); i++){
if(v[i] == key){
result = i;
}
else{
result = -1;
}
}
Let's say your vector contains [1, 2, 3, 4] and you search 2 starting at index 0: here is what your code is doing:
i = 0: (v[i] : 1) == 2 -> false: result = -1
i = 1: (v[i] : 2) == 2 -> true: result = 1
i = 2: (v[i] : 3) == 2 -> false: result = -1
i = 3: (v[i] : 4) == 2 -> false: result = -1
When you've found your value, you still continue to read other value whereas you should stop.
Either using break or directly returning (return i) in the v[i] == key condition;
Either by checking result in the for condition (result == -1 && i < v.size())
Per comment remark: the case with break and return (the last one is not so hard):
int Sequential_Search(const vector<int>&v, int key, int start){
int result = -1; // important for 'break'
for(int i = start; i < v.size(); i++){
if(v[i] == key){
result = i; break;
}
}
return result;
}
int Sequential_Search(const vector<int>&v, int key, int start){
for(int i = start; i < v.size(); i++){
if(v[i] == key){
return i;
}
}
return -1;
}
When the loop finds the key, it sets result = i - but it doesn't stop looping. On the next iteration, v[i] is likely not equal to key, and the loop resets result to -1. The function returns -1 unless key just happens to match the last element.
The reason this is failing with the else statement is because there are many scenarios that the key would not be the last item in the vector.
If the key is 3 and the vector of ints if <1,3,4>, the for loop will loop through 3 times total. On the first iteration, it will go into the else statement since we did not find the key at the 0th index. Result is -1. On the second iteration, we found the key! Set result to i = 1. The third iteration will go into the else statement again, and set the result back to -1.
To fix this, you can use 'break' to leave the for loop as soon as you find result. Set result to I and then follow that with break; This will ensure that if the result is found, you will not go into the else statement again and reset it to -1.
I have a method which looks like this:
bool Perfect(int num) {
int sum = 0;
for (int i = 1; i < num; i++)
{
num%i == 0 ? sum += i : continue;
}
return sum == num ? true : false;
}
I'm trying to combine here ? operator with continue operator...
So logically if the statement here is false in this line:
num%i == 0 ? sum += i : continue;
I will just skip the iteration or do nothing?
If I do it like this the compiler reports an error like:
expected an expression
And in case like this:
num%i == 0 ? sum += i
It says:
Expected a ':'
Is there any way to use continue with ? operator or just simply avoid false case somehow ???
bool Perfect(int num) {
int sum = 0;
for (int i = 1; i < num; i++)
{
if(num % i == 0)
sum += i;
}
return sum == num;
}
Use an if statement. No need of continue since you have no other statement after sum += i.
C++ and C have both statements and expressions (notice that an assignment or a function call is an expression, and that expressions are statements). They are different syntactic (and semantical) things.
You could have coded (but this is weird style as a statement reduced to a ?: conditional expression) inside your for loop:
(num%i == 0) ? (sum += i) : 0;
(when num%i is non-zero, that evaluates to 0 which has no significant side effect; BTW that last occurrence of 0 could be 1234 or any constant integral expression)
Some programming languages (notably Scheme, read SICP) have only expressions (and no statements).
The ternary ?: operator applies to expressions and gives an expression (so can't be used for statements).
Conditional statements use the if keyword. In your case it is much more readable (because you are using sum += i only for its side effect) and an if statement is here easier to understand.
You can't use a ternary operator in this way. You would normally use it for assigning a value to a variable based on an expression being true or false. Eg.
int j, i,
j = (i == 2) ? 5: 10;
If i is equal to 2 then j is given the value of 5 else if i is not equal to 2 then j is given the value of 10.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I just came upon one problem. I wanted to compare whether my Eratostenes's Sieve contains prime numbers or not. In the code i have this line
if (sieve[2] == is_prime(2)) // returns false
printf ("true");
Now, sieve[2] is a boolean and it's value is true (I even checked in the array, so there's no doubt about it). is_prime(2) is a boolean aswell (I also checked).
Now my problem. The line presented above returns false. Yes - it returns false even though it's statement is:
if ( true == true ) // which normally returns true
printf ("true");
However, after removing one equation sign:
if ( sieve[2] = is_prime(2) ) // returns true
printf ("true");
This statement returns true.
Can someone briefly explain how does one equation mark work in this case in comparison to ==?
Thanks in advance
EDIT
is_prime:
bool is_prime(int x) {
unsigned int i,j,k;
if (x < 2) return false;
else {
for (i=2; i!=x; i++) {
if (x == i) return true;
else if (x % i == 0) return false;
}
}
}
sieve:
const int n = 10000;
bool sieve[n+1];
.
.
unsigned long int i;
sieve[0] = sieve[1] = false;
for (i=2; i<=n; i++) sieve[i] = true;
for (i=2; i*i<=n; i++) {
if (sieve[i]) {
unsigned tmp = 2*i;
while (tmp <= n) {
sieve[tmp] = false;
tmp += i;
}
}
}
[EDIT2]
The problem was with "is_prime(x)" Changed loop condition from "i!=x" to "i<=x"
Sorry for the trouble and thanks for the answers
UPDATE
bool is_prime(int x) {
unsigned int i,j,k;
if (x < 2) return false;
else {
for (i=2; i!=x; i++) {
if (x == i) return true;
else if (x % i == 0) return false;
}
}
}
Your is_prime() (above) is broken, with undefined behaviour, as when x is 2 (or indeed any actually prime number) it reaches the end of the function without having a return statement - the i!=x test means the x == i inside the loop can never be true.
is_prime(2) it's likely to return effectively random results (based on left over stack or register content / in your documented output it's seeming "returning" x itself, presumably because your ABI uses the same CPU register or stack address to pass in the argument and pass back the function's return value).
Specifically for 2, flow enters the first else clause, then with i=2 the first i!=x test fails and the for loop immediately exits... there's no return after the for's scope. Minimally corrected code (faster implementations are possible, but keeping the simplicity and intended logic):
bool is_prime(int x)
{
if (x < 2) return false;
for (int i = 2; i < x; ++i)
if (x % i == 0)
return false;
return true;
}
Equivality / ==
With sieve[2] == is_prime(2) it's checking they have the same value - possibly after converting one of the values to enable the comparison, but you say they're both booleans so that's not necessary. This would yield a "true" value for the if when they're both true or both false.
Now my problem. The line presented above returns false. Yes - it returns false even though...
That doesn't make any sense... I suggest you add the following before the if statement to check the variables' values:
std::cout << "sieve[2] " << sieve[2] << " (bool)" << (bool)sieve[2]
<< ", is_prime(2) " << is_prime(2) << std::endl;
I even checked in the array, so there's no doubt about it
Be wary of mistakes like seeing the array content displayed ala { true false true false } and thinking [2] is the second value... it's actually the third. as array indexing starts at 0.
Assignment / =
With sieve[2] = is_prime(2) you're assigning the value of is_prime(2) into sieve[2], and the if statement is deemed "true" if that value is deemed true in a boolean context (i.e. it's a boolean with value true, or a non-0 number or pointer etc.). For most data types, the execution flow of if (sieve[2] = is_prime(2)) ... is the same as simply if (is_prime(2)) ..., but of course it also modifies sieve[2].
It assigns the right hand operand to left, and returns the left operand.Since you are assigning true to your variable, it evaluates to true. If you set your variable to false, you don't get the output, e.g:
bool x;
if(x = false)
printf("this won't be printed");
Here the equal affect the left operator with the value of the right operator then test the value. So the result must be the value of the right operator.
Your loop in is_prime will never run for the check x == i will be true, because it runs as long as x != i. Those two conditions are mutually exclusive.
That means the function will end without a return statement, which leads to undefined behavior.
This
if ( sieve[2] = is_prime(2) )
contains an assignment, not a comparison.
As the value of an assignment is the value assigned, it is true whenever is_prime(2) is.
However, let's look at your is_prime and see what happens if we pass it a 2...
bool is_prime(int x) {
unsigned int i,j,k;
So far, so good, but j and k are never used, so they shouldn't really be here.
if (x < 2) return false;
2 isn't less than 2, so we'll continue...
else {
for (i=2; i!=x; i++) {
OK, set i = 2, and compare it to x which is 2, and... oops, i is equal to x, so we'll abandon the loop immediately...
if (x == i) return true;
else if (x % i == 0) return false;
}
}
... and fall through here, where we're not returning a value like we promised, and causing undefined behaviour.
}
So, your program is undefined (you really should switch on compiler warnings, or start listening to them).
And this happens on every number that is prime.
You can rewrite the loop like this:
for (i=2; i <= x; i++) {
if (x == i) return true;
else if (x % i == 0) return false;
}
or
for (i=2; i < x; i++) {
if (x % i == 0) return false;
}
return true;
Why does if (is_prime(2)) appear to work?
(Since this code is undefined, the following is largely speculation and should only be taken with suitable measures of salt.)
Often, when a function is supposed to return something but doesn't, the calling function will just grab whatever is stored in the place where the return value should have been and use that.
This value is in this case very likely not the same as the bit pattern that represents true, so will compare unequal to true, in if (is_prime(2) == true).
It will however, also very likely, not be the bit pattern that represents false either, so will be considered true in a conditional, if(is_prime(2)).
I'm new to programming, can someone take two minutes to explain this statement for me? how can I write it like this :
if (condition) {...} else {...}
if (myFunction(i == 8? (j + 1): j, (j + 1) % 9))
{
return true;
}
The function is called with two arguments. First one uses a ternary operator to check if i (the index) is 8; if so, increment j, else leave j as is.
Second argument increments j by 1, it uses primary expression operator around j+1 because arithmetic + has lower precedence than modulus (%) http://www.swansontec.com/sopc.html. If j is 1 and we increment by 1, then 2 % 9 is 2, since the modulo operation returns the remainder. This assumes C style syntax.
int arg1 = i == 8 ? (j + 1) : j;
int arg2 = (j + 1) % 9;
if (myFunction(arg1,arg2))
{
return true;
}
else
{
return false;
}