Can’t work out why I fail test 2

Hi folks,
I can’t work out why I fail test 2 using the code below. For some reason the “return true” in the else part of the if/else statement is failing where a number is in-range as per test 2. I can’t see why, especially when test 7 passes correctly, indicating the if/else return true is operating correctly. Appreciate any help - thank you.

inRange(number, startValue, endValue){
let lowerValue = startValue;
let upperValue = endValue;

if (endValue = ‘undefined’){
lowerValue = 0;
upperValue = startValue;
}

if (startValue > endValue) {
lowerValue = endValue;
upperValue = startValue;
}

if (number <= lowerValue || number > upperValue) {
return false
} else {
return true
}
}

node test/in-range.js _.inRange() Tests: 1 - _.inRange() is defined - Passed! 2 - Returns true if an in-range value is in range - Failed: _.inRange(2, 1, 3) returned false instead of true. 3 - Returns false if a too small value is out of range - Passed! 4 - Returns false if a too large value is out of range - Passed! 5 - Uses end value as start value and start value as 0 if end value is not defined - Passed! 6 - Reverses start and end values if start is bigger than end - Passed! 7 - Returns true if provided value is same as start value - Passed! 8 - Returns false if provided value is same as end value - Passed!

Compare that to the specifications…

If the provided number is larger than or equal to the end value, .inRange() will return false.

Your version excludes the lower value, rather than excluding the upper value.

Thank you for the reply. Funnily enough I worked that out, after I posted, but having thought I was correcting it, the change made the test results worse - now failing 2,3 and 7. The “corrected” version is shown below.

inRange(number, startValue, endValue){
let lowerValue = startValue;
let upperValue = endValue;

if (endValue = ‘undefined’){
lowerValue = 0;
upperValue = startValue;
}

if (startValue > endValue) {
lowerValue = endValue;
upperValue = startValue;
}

if (number < lowerValue || number >= upperValue) {
return false;
} else {
return true;
}
}

node test/in-range.js _.inRange() Tests: 1 - _.inRange() is defined - Passed! 2 - Returns true if an in-range value is in range - Failed: _.inRange(2, 1, 3) returned false instead of true. 3 - Returns false if a too small value is out of range - Failed: _.inRange(0, 1, 3) returned true instead of false. 4 - Returns false if a too large value is out of range - Passed! 5 - Uses end value as start value and start value as 0 if end value is not defined - Passed! 6 - Reverses start and end values if start is bigger than end - Passed! 7 - Returns true if provided value is same as start value - Failed: _.inRange(1, 1, 3) returned false instead of true. 8 - Returns false if provided value is same as end value - Passed!

There is still a problem with the comparisons. The upper value cannot be in the range, and the lower value can be.

For the sake of readability, let’s simplify the variable names.

inRange (n, start, end) {
  if (! end) {                   // `end` is undefined
    [start, end] = [0, start]    // swap
  } else
  if (start > end) {
    [start, end] = [end, start]  // swap
  }
  return n >= start && end > n   // boolean returned
}

There is a slight difference from your code, especially as it is pared down to the very minimum. We used destructuring assignment to perform the swaps, also for simplicity. It lets us see the logic more clearly.

Thank you.

I understand the way that you’ve provided. I believe that the destructuring assignment achieves the same as I have achieved with if/else statements (and have passed those tests on that basis).

However, even when I restructure my final if/else statement in the way you have shown (using my less simplified variable names) I get the same errors. Effectively I had been saying if out of range => return false, otherwise return true. I can turn that round to say if in range => return true, otherwise return false.

I can then simplify further as you have done to the following statement, which again, gives me the same fails in the test:

return number >= lowerValue && upperValue > number;

This implies that it is something I’ve done incorrectly earlier on in my if/else statements, and I’d really like to understand how the logic breaks down using the syntax I tried. Otherwise I’m just copying other people’s code and giving up on my own method, which I think is equally logical (if more long-winded!).

Please post your latest code, thanks.

Do you still have that line in your code?

We have used your logic, just a different swapping method and less variables.

inRange(number, startValue, endValue){
let lowerValue = startValue;
let upperValue = endValue;

if (endValue = ‘undefined’){
lowerValue = 0;
upperValue = startValue;
}

if (startValue > endValue) {
lowerValue = endValue;
upperValue = startValue;
}

return number >= lowerValue && upperValue > number;

},

That’s the other culprit I was secretly hoping you would spot on your own. It’s an assignment where a relation is being tested.

I’d just seen! And that resolves all but test 5, which I’m now trying to figure out!

5 - Uses end value as start value and start value as 0 if end value is not defined

So there must be a problem with how that first conditional is resolved.

Got it! So in fact my final if/else was working fine with the first correction, it was === instead of =, and I was looking at the string ‘undefined’ instead of the value of undefined.

The following works…

Thank you for your help :pray:

inRange(number, startValue, endValue){

let lowerValue = startValue;

let upperValue = endValue;

if (endValue === undefined){

lowerValue = 0;

upperValue = startValue;

}

if (startValue > endValue) {

lowerValue = endValue;

upperValue = startValue;

}

if (number < lowerValue || number >= upperValue) {

return false;

} else {

return true;

}

},

1 Like

Excuse me for reading that wrong. Was biased toward a true result; sheesh.

As an aside, is there a way to have both arrows point the same direction? It is so much more readable and perhaps my snafu could have been avoided.


Great that you learned a little more about undefined.

Trick question, "Is undefined a JavaScript object?

What other instances can you think of where undefined surfaces?

Can you see the difference between your explicit (identity) comparison and my truth-tested expression?

What would be the advantage of the explicit comparison (not a trick question)?

So I guess you could turn round:

if (number < lowerValue || number >= upperValue) {

to read:

if (lowerValue > number || number >= upperValue) {


Second part:

  • undefined is a property of the global object I believe. I recall it can come up when a variable has no value assigned to it, or where no value is returned.
  • Your method returned a boolean (true or false) whereas mine returned true or false directly based on the result of the comparison, which in this case I’d set up to act like a boolean as it was either true or false with an if/else that only ever gave those outcomes. I guess the explicit comparison could therefore give you more potential outcomes using an else if, if that was required and it was set up that way.
1 Like

Forgive me again, this time for not being explicit about the conditional in question. It was this one I was referring to…

if (end === undefined)

as compared to,

if (! end)

Your explicit (as much as it can be with undefined) confines the match to that very identity (or non-identity, as it were). Mine just lets its absence of any truth value suffice. The difference is plain. Which is better can only be debated on a case by case basis so there is no point painting one black and other white. Case by case.

The two differing methods of return are equally explicit/truth-based, so I should have taken that into account. The return method of choice is the one that works 100% of the time. Both do the job. I’m partial to the one that has no primitive literals.

Is undefined an object? That’s the question.

Use this tool to get what I mean…

typeof

If you push the button below, your code won’t lose it’s formatting and will be more readable