Skip to content

Commit c592280

Browse files
authored
[Wordy]: Moar Typos & Missing Links. (#3789)
* Moar typos and missing links. Hopefully, this is the last round. * Added in missing hints file. * Further touchup on intro md.
1 parent 63cc10b commit c592280

File tree

2 files changed

+75
-19
lines changed

2 files changed

+75
-19
lines changed

exercises/practice/wordy/.approaches/introduction.md

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,45 @@
11
# Introduction
22

33
The objective of the Wordy exercise is to parse and evaluate small/simple mathematical word problems, returning the result as an integer.
4-
These problems do not require complex or [PEMDAS][PEMDAS]-based evaluation and are instead processed from left-to-right _in sequence_.
4+
These questions do not require complex or [PEMDAS][PEMDAS]-based evaluation and are instead processed from left-to-right _in sequence_.
55
This means that for some of the test cases, the solution will not be the same as if the word problem was evaluated like a traditional math problem.
66

7+
<br>
8+
79

810
## General Guidance
911

1012
The key to a Wordy solution is to remove the "question" portion of the sentence (_"What is", "?"_) and process the remaining words between numbers as [operators][mathematical operators].
11-
12-
1313
If a single number remains after removing the "question" pieces, it should be converted to an [`int`][int] and returned as the answer.
1414

1515

16-
Any words or word-number combinations that do not fall into the simple mathematical evaluation pattern (_number-operator-number_) should [`raise`][raise-statement] a [`ValueError`][value-error] with a message.
16+
Any words or word-number combinations that do not fall into the simple mathematical evaluation pattern (_number-operator-number_) should [`raise`][raise-statement] a ["ValueError('syntax error")`][value-error] with a message.
1717
This includes any "extra" spaces between numbers.
18-
19-
20-
One way to reduce the number of `raise` statements/ `ValueError`s needed in the code is to determine if a problem is a "valid" question _before_ proceeding to parsing and calculation.
2118
As shown in various approaches, there are multiple strategies for validating questions, with no one "canonical" solution.
2219

2320

24-
One very effective validation approach is to check if a question starts with "What is", ends with "?", and does not include the word "cubed".
21+
A whole class of error can be eliminated up front by checking if a question starts with "What is", ends with "?", and does not include the word "cubed".
2522
Any other question formulation becomes a `ValueError("unknown operation")`.
26-
This very restrictive approach could lead to future maintenance issues if the definition of a question ever changes or operations are added, but for the purposes of passing the current Wordy tests, it works well.
23+
This could lead to future maintenance issues if the definition of a question ever changes or operations are added, but for the purposes of passing the current Wordy tests, it works well.
2724

2825

29-
Proceeding from validation, there are many Pythonic ways to go about the cleaning, parsing, and calculation steps of Wordy.
30-
However, they all follow these general steps:
26+
~~~~exercism/note
27+
There are many Pythonic ways to go about the cleaning, parsing, and calculation steps of Wordy.
28+
However, the solutions all follow these general steps:
3129
3230
1. Remove the parts of the question string that do not apply to calculating the answer.
3331
2. Iterate over the question, determining which words are numbers, and which are meant to be mathematical operations.
34-
- _Converting the question string into a `list` of words is hugely helpful here, but not absolutely necessary._
35-
3. **_Starting from the left_**, take the first three elements and convert number strings to `int` and operations words to +, -, *, /.
32+
-- _Converting the question string into a `list` of words is hugely helpful here._
33+
3. **_Starting from the left_**, take the first three elements and convert number strings to `int` and operations words to the mathematical operations +, -, *, and /.
3634
4. Apply the operation to the numbers, which should result in a single number.
37-
- _Employing a `try-except` block around the conversion and operator application steps can trap any errors thrown and make the code both "safer" and less complex._
35+
-- _Employing a `try-except` block can trap any errors thrown and make the code both "safer" and less complex._
3836
5. Use the calculated number from step 4 as the start for the next "trio" (_number, operation, number_) in the question. The calculated number + the remainder of the question becomes the question being worked on in the next iteration.
39-
- _Using a `while-loop` with a test on the length of the question to do calculation is a very common strategy._
37+
-- _Using a `while-loop` with a test on the length of the question to do calculation is a very common strategy._
4038
6. Once the question is calculated down to a single number, that is the answer. Anything else that happens in the loop/iteration or within the accumulated result is a `ValueError("syntax error")`.
39+
~~~~
4140

4241

43-
For cleaning the question, [`str.removeprefix`][removeprefix] and
42+
For question cleaning, [`str.removeprefix`][removeprefix] and
4443
[`str.removesuffix`][removesuffix] introduced in `Python 3.9` can be very useful:
4544

4645

@@ -79,20 +78,37 @@ Different combinations of [`str.find`][find], [`str.rfind`][rfind], or [`str.ind
7978
A [regex][regex] could be used to process the question as well, but might be considered overkill given the fixed nature of the prefix/suffix and operations.
8079
Finally, [`str.strip`][strip] and its variants are very useful for cleaning up any leftover leading or trailing whitespace.
8180

82-
Many solutions then use [`str.split`][split] to process the remaining "cleaned" question into a `list` for convenient looping/iteration, although other strategies can also be used.
81+
Many solutions then use [`str.split`][split] to process the remaining "cleaned" question into a `list` for convenient looping/iteration, although other strategies can also be used:
8382

8483

85-
For math operations, many solutions involve importing and using methods from the [operator][operator] module in combination with different looping, parsing, and substitution strategies.
84+
```python
85+
>>> sentence = "The quick brown fox jumped over the lazy dog 10 times"
86+
>>> sentence.split()
87+
['The', 'quick', 'brown', 'fox', 'jumped', 'over', 'the', 'lazy', 'dog', '10', 'times']
88+
```
89+
90+
91+
For math operations, many solutions involve importing and using methods from the [operator][operator] module.
8692
Some solutions use either [lambda][lambdas] expressions, [dunder/"special" methods][dunder-methods], or even `eval()` to replace words with arithmetic operations.
87-
However, the exercise can be solved **without** using `operator`, `lambdas`, `dunder-methods` or `eval`.
93+
94+
95+
However, the exercise can be solved without using `operator`, `lambdas`, `dunder-methods` or `eval`.
8896
It is recommended that you first start by solving it _without_ "advanced" strategies, and then refine your solution into something more compact or complex as you learn and practice.
8997

9098

9199
~~~~exercism/caution
92100
Using [`eval`][eval] for the operations might seem convenient, but it is a [dangerous][eval-danger] and possibly [destructive][eval-destructive] approach.
93101
It is also entirely unnecessary, as the other methods described here are safer and equally performant.
102+
103+
[eval-danger]: https://softwareengineering.stackexchange.com/questions/311507/why-are-eval-like-features-considered-evil-in-contrast-to-other-possibly-harmfu
104+
[eval-destructive]: https://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html
105+
[eval]: https://docs.python.org/3/library/functions.html?#eval
94106
~~~~
95107

108+
<br>
109+
110+
_____________
111+
96112

97113
## Approach: String, List, and Dictionary Methods
98114

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Hints
2+
3+
## General
4+
5+
- This challenge is all about validating, "cleaning up", and processing the given question in the **_correct order_**.
6+
- If you read the directions and tests carefully, you will find there are three conditions that need to be met for a question to be "valid".
7+
If a question is not valid, you will need to [raise ][raise-statement] a [ValueError][value-error] with a message (_`ValueError("unknown operation")`_).
8+
It is best if you get this particular check out of the way before doing anything else.
9+
- Processing a question before calculating the answer is all about utilizing [string methods][str-methods].
10+
A few popular ones to investigate include `str.removeprefix`, `str.removesuffix`, `str.replace`, and `str.strip`.
11+
Others you might want to check out are `str.startswith`, `str.endswith`, and `in` (_which can apply to more than just strings_).
12+
13+
- It is possible to iterate over a string. However, it is **much** easier to iterate over a list of _words_ if the string you are processing is a sentence or fragment with spaces. [`str.split`][split] can break apart a string and return a list of "words".
14+
- A [`while-loop`][while-loop] is very useful for iterating over the question to process items.
15+
- For fewer error checks and cleaner error-handling, a [`try-except`][handling-exceptions] is recommended as you process the question.
16+
- **Remember**: the question is processed **_left-to-right_**. That means "1 plus 12 minus 3 multiplied by 4" gets processed by:
17+
- Calculating "1 plus 12" (13),
18+
- Calculating "13 minus 3" (10),
19+
- Calculating "10 multiplied by 4" (40).
20+
- The result of the first calculation is _concatenated with the remainder of the question to form a new question for the next step_.
21+
- This technique is sometimes called [the accumulator pattern][accumulator-pattern], or [fold][fold] / [foldl][foldl] in functional programming languages like [Haskell][haskell-folds] or Lisp.
22+
- Python includes two methods that are purpose-built to apply the `accumulator-pattern` to iterable data structures like `lists`, `tuples`, and `strings`.
23+
[`functools.reduce`][reduce] and [`itertools.accumulate`][accumulate] could be interesting to investigate here.
24+
25+
- This exercise has many potential solutions and many paths you can take along the way.
26+
No path is manifestly "better" than another, although a particular path may be more interesting or better suited to what you want to learn or explore right now.
27+
28+
29+
[accumulate]: https://docs.python.org/3/library/itertools.html#itertools.accumulate
30+
[accumulator-pattern]: https://muzny.github.io/csci1200-notes/08/2/accumulator.html
31+
[fold]: https://en.wikipedia.org/wiki/Fold_(higher-order_function)
32+
[foldl]: https://slim.computer/eecs-111-ta-guide/material/higher-order/Fold.html
33+
[handling-exceptions]: https://docs.python.org/3.11/tutorial/errors.html#handling-exceptions
34+
[haskell-folds]: https://www.ashwinnarayan.com/post/a-study-on-haskell-folds/
35+
[raise-statement]: https://docs.python.org/3/reference/simple_stmts.html#the-raise-statement
36+
[reduce]: https://docs.python.org/3/library/functools.html#functools.reduce
37+
[split]: https://docs.python.org/3.9/library/stdtypes.html#str.split
38+
[str-methods]: https://docs.python.org/3/library/stdtypes.html#string-methods
39+
[value-error]: https://docs.python.org/3.11/library/exceptions.html#ValueError
40+
[while-loop]: https://python-practice.com/learn/loops/while_loop/

0 commit comments

Comments
 (0)