-
Notifications
You must be signed in to change notification settings - Fork 544
Tests for scrabble-score's optional extensions #249
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
Aha, the Travis tests fail because my new tests fail. What is the preferred method for me to continue? The rewriting would be non-trivial, because it requires state across individual characters. The current .fold() implementation can't be extended in that direction. my solution: |
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.
Hello and thank you.
It is true that we would like the example solution to pass the tests - this helps us ensure the exercise is actually solvable (we didn't make a mistake in the tests, or something).
I don't mind your solution. The match
for scoring each word is at least more compact than tan insert per letter, at least in terms of numbers of lines.
If you really want to fit double/triple into a fold, you would have the accumulator of the fold keep track of the previous letter's score as well, this would also be a worthy alternative.
I will wonder whether we should error on things like a:garbage
or :double
(doubling with no letter to double?), and also whether :double
is the best way to notate that the letter should be doubled (then again, it's not like I can come up with something better; maybe [double]
or something)
Oh yeah! and before I forget, I have to ask to ignore all but the first test, as I did in the other PR
I think this is a good start. Thanks. |
Thanks for the feedback! I'll try to incorporate it! I may be slow to respond, but that won't mean I've abandoned this, it's just that I'm doing this in the brief lost minutes during my commute :-) I'm undecided on |
Yes, it does. I should have explained it, my bad for not doing so!
Ah! This could be a fine idea. You are right about the spec. As in the other PR, this could be a thing all languages can benefit from, so it could be worth opening an issue in x-common to discuss how the spec should be interpreted. And if we reach an agreement, a PR can be sent to x-common. If agreement can't be reached in x-common, we could possibly clarify the specification for our track by adding a exercises/scrabble-score/HINTS.md - this is a special file that gets appended to the README. |
Multiplying a letter value with a modifying token introduces dependency between characters of the word. This inter-character dependency makes it hard to keep the old map+fold method, which, in all its glorious functional-ness, doesn't like state between its iterations. We switch to a for-loop, which mutates state kept in the 'score' and 'previous_char_value' variables. Idiomatic rust prefers for-loops over map() if the primary effect of the iteration is the side-effect, as is now the case. Unfortunately, the inter-loop dependency sacrifices (potential) iteration parallelism. An alternative approach that could conserve parallelism would be to replace any "X:double" with "XX" and "X:triple" with "XXX". However, that capability is beyond std's String::replace(), and introducing the (admittedly awesome) regex-crate just for this is probably overkill.. The previous HashMap dictionary() is no longer suitable, as the value of some tokens ('2' and '3') now dynamically depends on the previous char. Also, Rust's match() is precisely 102% cooler than a HashMap, so use that!
update!
feel free to nitpick over variable names and comments! It's the example after all, so it should be clear! I'm opening a discussion issue on x-common next. P.S. @petertseng thank you for your very polite and very welcoming responses! I appreciate it! |
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.
Given that x-common won't have it, now the Rust track should decide whether we want to add this, in contravention of x-common.
I honestly do not feel strongly either way, so if anyone does, you should speak up.
What I will say is that if we are to add it, we will want to specify how the double-letter scoring should be specified in exercises/scrabble-score/HINTS.md. I know Ian said:
In-line notation seem super awkward to me. Parsing seems fraught with problems, as you mention. I think a more robust structure is necessary.
Perhaps one would say that strings can only do so much for us. I suppose the best we can do with a string would be something like br[o:double]wn
. Any alternatives?
// reduce the multi-character value multipliers :double and :triple to a single char. | ||
let tokenised_word = word.to_lowercase().replace(":double", "2").replace(":triple", "3"); | ||
|
||
for a_char in tokenised_word.chars() { |
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.
ah, I was about to say that char
would be sufficient, but one probably can't use the name of a type as an identifier. makes sense to have a_char
, then. Maybe c
would be fine though, I'm OK with very short names for variables in use for very short time.
values | ||
/// Calculates the value of the current character. | ||
/// | ||
/// The previous characters' value is required in case the current |
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.
probably just characters' -> character's
/// | ||
/// The previous characters' value is required in case the current | ||
/// token is a multiplier, which affects the score of the previous char. | ||
fn char_value(the_char: char, prev_value: u16) -> u16 { |
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 might also consider c
here.
A delimiter like
|
And I'm fine having tests in place to handle the "extra credit" problems, even if those tests aren't in canonical. |
Ah, delimiters! I like how simple the implementation could become: score += Match c {
'[' => multiplyer *= 2; 0,
']' => multiplyer /= 2; 0,
'<' => multiplyer *= 3; 0,
'>' => multiplyer /= 3; 0,
'a'|'e'|'u'.... => 1,
... => 2,
_ => 0
} * multiplyer Edit: Wow, it does work! I also like how this would mean that there is no special-casing for word-multiplyer vs. letter-multiplyer. Edit 2: Seems my code-smell nose wasn't too far off: Clippy has doubts:
Introducing an explicit temp-value solves this |
If I'm reading this PR correctly, there are just a few small changes @petertseng mentioned in comments. Are those blocking merge? Or can we move on this PR without those changes? |
I had a different reading of this PR: I thought all of my comments are unimportant, and what we would want to discuss before merge is:
And that whatever notation we use should be added to HINTS.md |
Ah, yes. I saw the comment approving the ideas of delimiters, but hadn't checked the code to see if delimiters had been implemented. |
After the discussion on the common track, I understood that the optional exercise was intentionally left vague. Figuring out a syntax was explicitly said to be part of the exercise. |
Ok. Sounds like we can close, then. Thanks for your work on this, @juleskers! |
So I set myself the challenge of doing scrabble-score's extensions for
:double
- and:triple
-scoring letters.In the course of doing so, I wrote tests. I thought these may be useful to the source, so here is my offer to include them upstream.
Comments, suggestions, nits and other (constructive) criticism welcome; this is my first contribution to exercism.io, so I may need some guidance ;-)