-
-
Notifications
You must be signed in to change notification settings - Fork 554
Luhn: Update testcase to avoid wrong solution #1480
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not having convenient access to a Java dev environment, I've rewritten your example in Python, as directly as possible:
>>> def isValid(candidate):
... number = candidate.replace(' ', '')
... if number == '0':
... return False
... digits = [ord(c) - 48 for c in number]
... return sum(2*digits[i] - (9*(1 if digits[i] >= 5 else 0)) if i % 2 == 0 else digits[i] for i in range(len(digits))) % 10 == 0
...
I've confirmed that where the old test case correctly returned False
by accident, the new test case will incorrectly return True
, failing the test case.
>>> isValid("055a 444 285")
False
>>> isValid("055b 444 285")
True
It's not a perfectly general solution, but it's an elegant way to stop this particular wrong algorithm from succeeding. I like it.
I also don't have access to running Java so I'll have to rely on others' help for the answer to the question: What does it do to |
Using the previous Python def of >>> isValid(':9')
True Given that the expected value of this case is |
It seems that this solution is already be ruled out by that test case. My mistake.
Given that the range of |
That means the interesting thing about these two cases I won't stand in the way if the decision is instead to ignore this recommendation and merge this PR as it currently stands. |
I agree that we should update the description to better describe the test, do you have any suggestions? By the way, is it possible to add a comment in a test about the intent of that test? It is not easy to recognize just by looking at the file. Just in case there's a wrong solution with a similar approach that passes, we know we should update the test suite to a more rigorous version. |
I have a hard time finding a short description for the cases. Even though it is not a requirement that it be short, #1198 seems to imply there are benefits. I'll try:
Open question, do we need to mention "ascii value offset from the value of 0" or is "ascii value" sufficient
it is possible. see an example in problem-specifications/exercises/largest-series-product/canonical-data.json Lines 107 to 120 in d28d6a5
see the formal spec in
problem-specifications/canonical-schema.json Lines 62 to 67 in d28d6a5
|
I updated the descriptions based on your suggestion. I also grouped them together to reflect the fact that they address the same problem. |
exercises/luhn/canonical-data.json
Outdated
"Convert non-digits to their ascii value and then offset them by 48 sometimes accidently return the correct result.", | ||
"This test is designed to avoid that solution." | ||
], | ||
"description": "using ascii value for doubled non-digit isn't allow", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think for grammar, allow
should be allowed
here, and in the other test case as well
exercises/luhn/canonical-data.json
Outdated
@@ -123,7 +115,23 @@ | |||
"expected": true | |||
}, | |||
{ | |||
"description": "strings with non-digits is invalid", | |||
"comments": [ | |||
"Convert non-digits to their ascii value and then offset them by 48 sometimes accidently return the correct result.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spelling accidently
-> accidentally
exercises/luhn/canonical-data.json
Outdated
@@ -123,7 +115,23 @@ | |||
"expected": true | |||
}, | |||
{ | |||
"description": "strings with non-digits is invalid", | |||
"comments": [ | |||
"Convert non-digits to their ascii value and then offset them by 48 sometimes accidently return the correct result.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"accidentally return the correct result" might be easy to misinterpret, or require careful thinking before a reader can determine whether the sentence is true. Can I suggest "accidentally declare an invalid string to be valid" so that requires less brainpower? my feeble mind was having a hard time figuring things out
Thank you for the review. I made a new commit based on your suggestion. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I have one last comment, that these two have been swapped.
I plan to approve after the two descriptions are swapped, or someone tells me I got mixed up. I do not plan to wait long after that to merge it. So, if other reviewers have some things to say, you should say them soon.
exercises/luhn/canonical-data.json
Outdated
"Convert non-digits to their ascii values and then offset them by 48 sometimes accidentally declare an invalid string to be valid.", | ||
"This test is designed to avoid that solution." | ||
], | ||
"description": "using ascii value for doubled non-digit isn't allowed", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you double-check me on this one? I think in this case, the b
is in a non-doubled position, and in the latter case the :
is in a doubled position. So these two test case descriptions should be switched, right?
Or did I get them mixed up
You're correct. I fix that in the new commit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this PR makes the purposes of these test cases clearer, a good improvement.
* luhn: Updated the exercise to the version 1.6.1 Relevant PRs: - exercism/problem-specifications#1420 - exercism/problem-specifications#1480 - exercism/problem-specifications#1500 - exercism/problem-specifications#1523 * luhn: Fixed the 'exercise' util generated comments in the test suite
Changes included: 1. exercism/problem-specifications#1480: 1.4.0 to 1.5.0: Change "055a 444 285" test into "055b 444 285" for subtle reasons. New test name: using ascii value for doubled non-digit isn't allowed 2. exercism/problem-specifications#1500: 1.5.0 to 1.6.0: Add test case: valid number with an odd number of spaces 3. exercism/problem-specifications#1635: 1.6.0 to 1.7.0: Add test case: invalid long number with an even remainder
The change might seem trivia at first. It isn't. Here's a solution that passes all the test in Java
In this solution, after I remove all the whitespaces, I convert all characters to the ascii number and subtract them to 48 (the ascii code of 0) to get the digits. Then I check with the list I receive and it passes all test cases. I didn't remove invalid characters at all.
The problem is that the ascii code of the invalid characters automatically make the valid number becomes invalid, so no need to remove them.
With the new test case, the sum is 90, and it should still be false because if the invalid character.