Conversation
|
Hi @lemoncurry this is my proposal for say exercise. |
|
@mirkoperillo How to create the README.md is described here. |
|
done @lemoncurry. |
|
Thank you @mirkoperillo for contributing again to the Java track 😄 |
|
@lemoncurry now |
| String sentence = ""; | ||
|
|
||
| if (digits.length == 3) { | ||
| digits = filterInitialZeros(digits); |
There was a problem hiding this comment.
Reassigning method parameters is not a great practice to be encouraging in our canonical implementation.
There was a problem hiding this comment.
Is it not common to prefix method parameters with final to discourage exactly this? E.g.
private String sayDigits(final char[] digits, final int orderNumber) {
...(I'm a functional programmer and have learned Java from functional programmers, so I admit to my own insanity wrt. knowing things at compile-time.)
There was a problem hiding this comment.
Annoyingly, there is a conflict here with the track policies:
Avoid using final in user-facing code. Liberal use of the
finalkeyword remains controversial. It adds little value to test suites, and if included in starter implementations, places implicit restrictions on user solutions.
My work has more-or-less the same policy (only using the final keyword for class constants and constructor assigned member variables). Even at that, we still look at it as a bad practice to re-assign a parameter because you can lose track of the reassignment. Someone comes along later to edit the same code and does not expect the parameter to have changed so they try to check something about the input and then they debug for a while until they discover that somewhere else the input parameter has been reassigned. Principle of least surprise says don't do it.
| if (number < 0) { | ||
| throw new IllegalArgumentException("input out of range"); | ||
| } | ||
| char[] digits = String.valueOf(number).toCharArray(); |
There was a problem hiding this comment.
Rather than processing a list of characters, why not turn the input number into a long and then we can extract the numbers using numeric operations (eg. integer division and modulo)? This also gets rid of the leading zeros problem that you had to address multiple times in this solution.
| import java.util.Arrays; | ||
|
|
||
| public class Say { | ||
|
|
There was a problem hiding this comment.
General comment about this solution: I think we need a better breakdown here. This one is very chaotic and hard to follow. The instructions recommend a certain strategy that chunks things in groups of three digits. I suggest we try to have our solution mirror that suggestion.
There was a problem hiding this comment.
TL;DR: If the contributor says "If it's not broken, I think this is good enough", this leads to a better reward mechanism.
Be sure to notice that the track policy on reference solutions is: "The solution does not need to be particularly great code, it is only used to verify that the exercise is coherent." There is a similar point for Haskell track on example solutions: "The example solution could be inspiration for other language implementors. It doesn't need to be perfect or very elegant. But it should be efficient enough for the test suite to finish in only a few seconds."
So while a reference solution could be better, it is okay to stop improving on it so long as it doesn't do anything "wrong" in the track interpretation of the exercise (canonical tests ± track-specific tests). If the contributor likes the mentorship of improving the reference solution, that is of course very fine.
But otherwise, it is probably better to improve on it in a separate commit, and, in general, not do that so as to discourage the tendency for reference solutions to become a gallery of well-done solutions, since we already have the (currently dysfunctional) community solutions page on the website.
There was a problem hiding this comment.
I find it unusual that we officially require less rigorous code for our canonical solution than we do for our students. In particular, because the canonical solution has to be maintained afterwards by the track maintainers. For example, when the problem specifications add new canonical test cases, someone else is going to have to come along and may have to modify this code to add the new test cases.
That said, I understand that there are conflicts of interest here since we want to encourage contributions. I'm just surprised that we allow so much less rigor on our canonical implementations.
| private String order(int length) { | ||
| switch (length) { | ||
| case 2: | ||
| return "thousand"; | ||
| case 3: | ||
| return "million"; | ||
| case 4: | ||
| return "billion"; | ||
| default: | ||
| return ""; | ||
| } | ||
| } |
There was a problem hiding this comment.
These feel like an enum...
| } | ||
| } | ||
|
|
||
| private String convertUnit(char digit) { |
There was a problem hiding this comment.
If working with longs instead of individual characters, we would be able to use a three digit set (like 123) and then extract the hundreds, tens, and ones digits to correctly say what we want. Something like this:
private String convertNumber(long number) {
// optionally - throw if number is greater than 999
int hundreds = number / 100;
int tens = (number % 100) / 10;
int ones = number % 10;
StringBuilder sb = new StringBuilder();
if (hundreds > 0) {
sb.append(convertOnes(hundreds)).append(" hundred ")
}
if (tens > 0) {
sb.append(convertTwoDigit(number / 10)).append(" ");
} else {
sb.append(convertOnes(ones)).append(" ");
}
return sb.toString();
}
String convertTwoDigit(long number) {
// Optionally throw if number > 99
// Determine if we are in the 10-19 (which would use a switch-case)
if (number < 20) return ...
String multipleOfTen = ... // eg. "forty"
int ones = number % 10;
if (ones == 0) {
return multipleOfTen;
}
return multipleOfTen + "-" + convertOnes(ones);
}
String convertOnes(long number) {
// This one can be a simple switch-case IMO
...
}
sshine
left a comment
There was a problem hiding this comment.
Nice of you to get back to this, @jmrunkle. Much needed.
I won't comment much on the code itself, but more on the process.
It would seem that a good strategy forward is for @mirkoperillo to decide what amount of feedback he wishes to incorporate in the reference solution. It could definitely be improved, but it shouldn't have to be perfected.
| import java.util.Arrays; | ||
|
|
||
| public class Say { | ||
|
|
There was a problem hiding this comment.
TL;DR: If the contributor says "If it's not broken, I think this is good enough", this leads to a better reward mechanism.
Be sure to notice that the track policy on reference solutions is: "The solution does not need to be particularly great code, it is only used to verify that the exercise is coherent." There is a similar point for Haskell track on example solutions: "The example solution could be inspiration for other language implementors. It doesn't need to be perfect or very elegant. But it should be efficient enough for the test suite to finish in only a few seconds."
So while a reference solution could be better, it is okay to stop improving on it so long as it doesn't do anything "wrong" in the track interpretation of the exercise (canonical tests ± track-specific tests). If the contributor likes the mentorship of improving the reference solution, that is of course very fine.
But otherwise, it is probably better to improve on it in a separate commit, and, in general, not do that so as to discourage the tendency for reference solutions to become a gallery of well-done solutions, since we already have the (currently dysfunctional) community solutions page on the website.
| String sentence = ""; | ||
|
|
||
| if (digits.length == 3) { | ||
| digits = filterInitialZeros(digits); |
There was a problem hiding this comment.
Is it not common to prefix method parameters with final to discourage exactly this? E.g.
private String sayDigits(final char[] digits, final int orderNumber) {
...(I'm a functional programmer and have learned Java from functional programmers, so I admit to my own insanity wrt. knowing things at compile-time.)
Fair enough. I was not aware that we officially require so much less of our canonical / reference implementations. |
|
Hi guys, thank you for the review , I will try to integrate your suggestions ASAP |
config.json
Outdated
| "slug": "say", | ||
| "uuid": "3c76a983-e689-4d82-8f1b-6d52f3c5434c", | ||
| "core": false, | ||
| "unlocked_by": null, |
There was a problem hiding this comment.
I did not notice this earlier, but this should be unlocked by one of the core exercises. For difficulty 3, I would suggest either one of the difficulty 2 or 3 exercises should unlock this one.
@mirkoperillo - Any chance you are going to get around to this soonish? |
Add folder structure and settings for say exercise.
Work in progress. Fixes #1752