Add new exercises for python
This commit is contained in:
parent
164a2443de
commit
e6c7977320
32 changed files with 2448 additions and 0 deletions
27
python/black-jack/.exercism/config.json
Normal file
27
python/black-jack/.exercism/config.json
Normal file
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"authors": [
|
||||
"Ticktakto",
|
||||
"Yabby1997",
|
||||
"limm-jk",
|
||||
"OMEGA-Y",
|
||||
"wnstj2007",
|
||||
"pranasziaukas",
|
||||
"bethanyG"
|
||||
],
|
||||
"contributors": [
|
||||
"PaulT89"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"black_jack.py"
|
||||
],
|
||||
"test": [
|
||||
"black_jack_test.py"
|
||||
],
|
||||
"exemplar": [
|
||||
".meta/exemplar.py"
|
||||
]
|
||||
},
|
||||
"icon": "poker",
|
||||
"blurb": "Learn about comparisons by implementing some Black Jack judging rules."
|
||||
}
|
1
python/black-jack/.exercism/metadata.json
Normal file
1
python/black-jack/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"track":"python","exercise":"black-jack","id":"1717580736c8411a9af5b913da36035f","url":"https://exercism.org/tracks/python/exercises/black-jack","handle":"DanielSiepmann","is_requester":true,"auto_approve":false}
|
130
python/black-jack/HELP.md
Normal file
130
python/black-jack/HELP.md
Normal file
|
@ -0,0 +1,130 @@
|
|||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
We use [pytest][pytest: Getting Started Guide] as our website test runner.
|
||||
You will need to install `pytest` on your development machine if you want to run tests for the Python track locally.
|
||||
You should also install the following `pytest` plugins:
|
||||
|
||||
- [pytest-cache][pytest-cache]
|
||||
- [pytest-subtests][pytest-subtests]
|
||||
|
||||
Extended information can be found in our website [Python testing guide][Python track tests page].
|
||||
|
||||
|
||||
### Running Tests
|
||||
|
||||
To run the included tests, navigate to the folder where the exercise is stored using `cd` in your terminal (_replace `{exercise-folder-location}` below with your path_).
|
||||
Test files usually end in `_test.py`, and are the same tests that run on the website when a solution is uploaded.
|
||||
|
||||
Linux/MacOS
|
||||
```bash
|
||||
$ cd {path/to/exercise-folder-location}
|
||||
```
|
||||
|
||||
Windows
|
||||
```powershell
|
||||
PS C:\Users\foobar> cd {path\to\exercise-folder-location}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
Next, run the `pytest` command in your terminal, replacing `{exercise_test.py}` with the name of the test file:
|
||||
|
||||
Linux/MacOS
|
||||
```bash
|
||||
$ python3 -m pytest -o markers=task {exercise_test.py}
|
||||
==================== 7 passed in 0.08s ====================
|
||||
```
|
||||
|
||||
Windows
|
||||
```powershell
|
||||
PS C:\Users\foobar> py -m pytest -o markers=task {exercise_test.py}
|
||||
==================== 7 passed in 0.08s ====================
|
||||
```
|
||||
|
||||
|
||||
### Common options
|
||||
- `-o` : override default `pytest.ini` (_you can use this to avoid marker warnings_)
|
||||
- `-v` : enable verbose output.
|
||||
- `-x` : stop running tests on first failure.
|
||||
- `--ff` : run failures from previous test before running other test cases.
|
||||
|
||||
For additional options, use `python3 -m pytest -h` or `py -m pytest -h`.
|
||||
|
||||
|
||||
### Fixing warnings
|
||||
|
||||
If you do not use `pytest -o markers=task` when invoking `pytest`, you might receive a `PytestUnknownMarkWarning` for tests that use our new syntax:
|
||||
|
||||
```bash
|
||||
PytestUnknownMarkWarning: Unknown pytest.mark.task - is this a typo? You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/stable/mark.html
|
||||
```
|
||||
|
||||
To avoid typing `pytest -o markers=task` for every test you run, you can use a `pytest.ini` configuration file.
|
||||
We have made one that can be downloaded from the top level of the Python track directory: [pytest.ini][pytest.ini].
|
||||
|
||||
You can also create your own `pytest.ini` file with the following content:
|
||||
|
||||
```ini
|
||||
[pytest]
|
||||
markers =
|
||||
task: A concept exercise task.
|
||||
```
|
||||
|
||||
Placing the `pytest.ini` file in the _root_ or _working_ directory for your Python track exercises will register the marks and stop the warnings.
|
||||
More information on pytest marks can be found in the `pytest` documentation on [marking test functions][pytest: marking test functions with attributes] and the `pytest` documentation on [working with custom markers][pytest: working with custom markers].
|
||||
|
||||
Information on customizing pytest configurations can be found in the `pytest` documentation on [configuration file formats][pytest: configuration file formats].
|
||||
|
||||
|
||||
### Extending your IDE or Code Editor
|
||||
|
||||
Many IDEs and code editors have built-in support for using `pytest` and other code quality tools.
|
||||
Some community-sourced options can be found on our [Python track tools page][Python track tools page].
|
||||
|
||||
[Pytest: Getting Started Guide]: https://docs.pytest.org/en/latest/getting-started.html
|
||||
[Python track tools page]: https://exercism.org/docs/tracks/python/tools
|
||||
[Python track tests page]: https://exercism.org/docs/tracks/python/tests
|
||||
[pytest-cache]:http://pythonhosted.org/pytest-cache/
|
||||
[pytest-subtests]:https://github.com/pytest-dev/pytest-subtests
|
||||
[pytest.ini]: https://github.com/exercism/python/blob/main/pytest.ini
|
||||
[pytest: configuration file formats]: https://docs.pytest.org/en/6.2.x/customize.html#configuration-file-formats
|
||||
[pytest: marking test functions with attributes]: https://docs.pytest.org/en/6.2.x/mark.html#raising-errors-on-unknown-marks
|
||||
[pytest: working with custom markers]: https://docs.pytest.org/en/6.2.x/example/markers.html#working-with-custom-markers
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit black_jack.py` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Python track's documentation](https://exercism.org/docs/tracks/python)
|
||||
- The [Python track's programming category on the forum](https://forum.exercism.org/c/programming/python)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
Below are some resources for getting help if you run into trouble:
|
||||
|
||||
- [The PSF](https://www.python.org) hosts Python downloads, documentation, and community resources.
|
||||
- [The Exercism Community on Discord](https://exercism.org/r/discord)
|
||||
- [Python Community on Discord](https://pythondiscord.com/) is a very helpful and active community.
|
||||
- [/r/learnpython/](https://www.reddit.com/r/learnpython/) is a subreddit designed for Python learners.
|
||||
- [#python on Libera.chat](https://www.python.org/community/irc/) this is where the core developers for the language hang out and get work done.
|
||||
- [Python Community Forums](https://discuss.python.org/)
|
||||
- [Free Code Camp Community Forums](https://forum.freecodecamp.org/)
|
||||
- [CodeNewbie Community Help Tag](https://community.codenewbie.org/t/help)
|
||||
- [Pythontutor](http://pythontutor.com/) for stepping through small code snippets visually.
|
||||
|
||||
Additionally, [StackOverflow](http://stackoverflow.com/questions/tagged/python) is a good spot to search for your problem/question to see if it has been answered already.
|
||||
If not - you can always [ask](https://stackoverflow.com/help/how-to-ask) or [answer](https://stackoverflow.com/help/how-to-answer) someone else's question.
|
45
python/black-jack/HINTS.md
Normal file
45
python/black-jack/HINTS.md
Normal file
|
@ -0,0 +1,45 @@
|
|||
# Hints
|
||||
|
||||
[The Python comparisons tutorial][python comparisons tutorial] and [Python comparisons examples][python comparisons examples] are a great introduction covering the content of this exercise.
|
||||
|
||||
## 1. Calculate the value of a card
|
||||
|
||||
- You can use the equality comparison operator `==` to determine if a card is an ace card: `card == 'A'`.
|
||||
- You can use the containment operator `in` to determine if a substring is contained inside a string: `'Q' in 'KJQ'`.
|
||||
- You can use the [`int` constructor][int constructor] to convert a `str` of an `int` to an `int`: `int('13')`.
|
||||
|
||||
## 2. Determine which card has a higher value
|
||||
|
||||
- Once you have defined the `value_of_card` function, you can call it from other functions.
|
||||
- You can use the value comparison operators `>` and `<` to determine if specific cards are _greater than_ or _less than_ a given value: `3 < 12`.
|
||||
- You can use the equality comparison operator `==` to determine if two values are equal to one another.
|
||||
|
||||
## 3. Calculate the value of an ace
|
||||
|
||||
- Once you have defined the `value_of_card` function, you can call it from other functions.
|
||||
- You can use the order comparison operator `>` to decide the appropriate course of action here.
|
||||
|
||||
## 4. Determine Blackjack
|
||||
|
||||
- Remember, you can use the [`if`/`elif`/`else` syntax][if syntax] to handle different combinations of cards.
|
||||
- You can chain BOTH comparison operators and boolean operators _arbitrarily_: `y < z < x` or `(y or z) and (x or z)`
|
||||
- You can reuse the already implemented `value_of_card` function.
|
||||
|
||||
## 5. Splitting pairs
|
||||
|
||||
- You can reuse the already implemented `value_of_card` function.
|
||||
- You can handle the `A` case (when at least one of the cards in an ace) separately.
|
||||
|
||||
## 6. Doubling down
|
||||
|
||||
- An `A` scored at 11 will never allow doubling down if there are two cards in the hand.
|
||||
- Given the first point, you _should_ be able to reuse the already implemented `value_of_card` function.
|
||||
- You can chain comparison operators _arbitrarily_: `y < z < x`.
|
||||
- You can use the [conditional expression][conditional expression] (_sometimes called a "ternary operator"_)
|
||||
to shorten simple `if`/`else` statements: `13 if letter == 'M' else 3`.
|
||||
|
||||
[conditional expression]: https://docs.python.org/3/reference/expressions.html#conditional-expressions
|
||||
[if syntax]: https://docs.python.org/3/tutorial/controlflow.html#if-statements
|
||||
[int constructor]: https://docs.python.org/3/library/functions.html#int
|
||||
[python comparisons examples]: https://www.tutorialspoint.com/python/comparison_operators_example.htm
|
||||
[python comparisons tutorial]: https://docs.python.org/3/reference/expressions.html#comparisons
|
395
python/black-jack/README.md
Normal file
395
python/black-jack/README.md
Normal file
|
@ -0,0 +1,395 @@
|
|||
# Black Jack
|
||||
|
||||
Welcome to Black Jack on Exercism's Python Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
|
||||
|
||||
## Introduction
|
||||
|
||||
## Comparisons
|
||||
|
||||
Python supports the following basic comparison operators:
|
||||
|
||||
| Operator | Operation | Description |
|
||||
| -------- | -------------------------- | ------------------------------------------------------------------------- |
|
||||
| `>` | "greater than" | `a > b` is `True` if `a` is **strictly** greater in value than `b` |
|
||||
| `<` | "less than" | `a < b` is `True` if `a` is **strictly** less in value than `b` |
|
||||
| `==` | "equal to" | `a == b` is `True` if `a` is **strictly** equal to `b` in value |
|
||||
| `>=` | "greater than or equal to" | `a >= b` is `True` if `a > b` OR `a == b` in value |
|
||||
| `<=` | "less than or equal to" | `a <= b` is `True` if `a < b` or `a == b` in value |
|
||||
| `!=` | "not equal to" | `a != b` is `True` if `a == b` is `False` |
|
||||
| `is` | "identity" | `a is b` is `True` if **_and only if_** `a` and `b` are the same _object_ |
|
||||
| `is not` | "negated identity" | `a is not b` is `True` if `a` and `b` are **not** the same _object_ |
|
||||
| `in` | "containment test" | `a in b` is `True` if `a` is member, subset, or element of `b` |
|
||||
| `not in` | "negated containment test" | `a not in b` is `True` if `a` is not a member, subset, or element of `b` |
|
||||
|
||||
They all have the same priority (_which is higher than that of [Boolean operations][boolean operations], but lower than that of arithmetic or bitwise operations_).
|
||||
|
||||
## Comparison between different data types
|
||||
|
||||
Objects that are different types (_except numeric types_) never compare equal by default.
|
||||
Non-identical instances of a `class` will also _**not**_ compare as equal unless the `class` defines special [rich comparison][rich comparisons] methods that customize the default `object` comparison behavior.
|
||||
Customizing via `rich comparisons` will be covered in a follow-on exercise.
|
||||
For (much) more detail on this topic, see [Value comparisons][value comparisons] in the Python documentation.
|
||||
|
||||
Numeric types are (mostly) an exception to this type matching rule.
|
||||
An `integer` **can** be considered equal to a `float` (_or an [`octal`][octal] equal to a [`hexadecimal`][hex]_), as long as the types can be implicitly converted for comparison.
|
||||
|
||||
For the other numeric types in the Python standard library ([complex][complex numbers], [decimal][decimal numbers], [fractions][rational numbers]), comparison operators are defined where they "make sense" (_where implicit conversion does not change the outcome_), but throw a `TypeError` if the underlying objects cannot be accurately converted for comparison.
|
||||
For more information on the rules that python uses for _numeric conversion_, see [arithmetic conversions][arithmetic conversions] in the Python documentation.
|
||||
|
||||
```python
|
||||
>>> import fractions
|
||||
|
||||
# A string cannot be converted to an int.
|
||||
>>> 17 == '17'
|
||||
False
|
||||
|
||||
# An int can be converted to float for comparison.
|
||||
>>> 17 == 17.0
|
||||
True
|
||||
|
||||
# The fraction 6/3 can be converted to the int 2
|
||||
# The int 2 can be converted to 0b10 in binary.
|
||||
>>> 6/3 == 0b10
|
||||
True
|
||||
|
||||
# An int can be converted to a complex number with a 0 imaginary part.
|
||||
>>> 17 == complex(17)
|
||||
True
|
||||
|
||||
# The fraction 2/5 can be converted to the float 0.4
|
||||
>>> 0.4 == 2/5
|
||||
True
|
||||
|
||||
>>> complex(2/5, 1/2) == complex(0.4, 0.5)
|
||||
True
|
||||
```
|
||||
|
||||
Any ordered comparison of a number to a `NaN` (_not a number_) type is `False`.
|
||||
A confusing side effect of Python's `NaN` definition is that `NaN` never compares equal to `NaN`.
|
||||
|
||||
```python
|
||||
>>> x = float('NaN')
|
||||
|
||||
>>> 3 < x
|
||||
False
|
||||
|
||||
>>> x < 3
|
||||
False
|
||||
|
||||
# NaN never compares equal to NaN
|
||||
>>> x == x
|
||||
False
|
||||
```
|
||||
|
||||
## Comparing Strings
|
||||
|
||||
Unlike numbers, strings (`str`) are compared [_lexicographically_][lexographic order], using their individual Unicode code points (_the result of passing each code point in the `str` to the built-in function [`ord()`][ord], which returns an `int`_).
|
||||
If all code points in both strings match and are _**in the same order**_, the two strings are considered equal.
|
||||
This comparison is done in a 'pair-wise' fashion - first-to-first, second-to-second, etc.
|
||||
In Python 3.x, `str` and `bytes` cannot be directly coerced/compared.
|
||||
|
||||
```python
|
||||
>>> 'Python' > 'Rust'
|
||||
False
|
||||
|
||||
>>> 'Python' > 'JavaScript'
|
||||
True
|
||||
|
||||
# Examples with Mandarin.
|
||||
# hello < goodbye
|
||||
>>> '你好' < '再见'
|
||||
True
|
||||
|
||||
# ord() of first characters
|
||||
>>> ord('你'), ord('再')
|
||||
(20320, 20877)
|
||||
|
||||
# ord() of second characters
|
||||
>>> ord('好'), ord('见')
|
||||
(22909, 35265)
|
||||
|
||||
# And with Korean words.
|
||||
# Pretty < beautiful.
|
||||
>>> '예쁜' < '아름다운'
|
||||
False
|
||||
|
||||
>>> ord('예'), ord('아')
|
||||
(50696, 50500)
|
||||
```
|
||||
|
||||
## Comparison Chaining
|
||||
|
||||
Comparison operators can be chained _arbitrarily_ -- meaning that they can be used in any combination of any length.
|
||||
Note that the evaluation of an expression takes place from `left` to `right`.
|
||||
|
||||
As an example, `x < y <= z` is equivalent to `x < y` `and` `y <= z`, except that `y` is evaluated **only once**.
|
||||
In both cases, `z` is _not_ evaluated **at all** when `x < y` is found to be `False`.
|
||||
This is often called `short-circuit evaluation` - the evaluation stops if the truth value of the expression has already been determined.
|
||||
|
||||
`Short circuiting` is supported by various boolean operators, functions, and also by comparison chaining in Python.
|
||||
Unlike many other programming languages, including `C`, `C++`, `C#`, and `Java`, chained expressions like `a < b < c` in Python have a conventional [mathematical interpretation][three way boolean comparison] and precedence.
|
||||
|
||||
```python
|
||||
>>> x = 2
|
||||
>>> y = 5
|
||||
>>> z = 10
|
||||
|
||||
>>> x < y < z
|
||||
True
|
||||
|
||||
>>> x < y > z
|
||||
False
|
||||
|
||||
>>> x > y < z
|
||||
False
|
||||
```
|
||||
|
||||
## Comparing object identity
|
||||
|
||||
The operators `is` and `is not` test for object [_identity_][object identity], as opposed to object _value_.
|
||||
An object's identity never changes after creation and can be found by using the [`id()`][id function] function.
|
||||
|
||||
`<apple> is <orange>` evaluates to `True` if _**and only if**_ `id(<apple>)` == `id(<orange>)`.
|
||||
`<apple> is not <orange>` yields the inverse.
|
||||
|
||||
Due to their singleton status, `None` and `NotImplemented` should always be compared to items using `is` and `is not`.
|
||||
See the Python reference docs on [value comparisons][value comparisons none] and [PEP8][pep8 programming recommendations] for more details on this convention.
|
||||
|
||||
```python
|
||||
>>> my_fav_numbers = [1, 2, 3]
|
||||
|
||||
>>> your_fav_numbers = my_fav_numbers
|
||||
|
||||
>>> my_fav_numbers is your_fav_numbers
|
||||
True
|
||||
|
||||
# The returned id will differ by system and python version.
|
||||
>>> id(my_fav_numbers)
|
||||
4517478208
|
||||
|
||||
# your_fav_numbers is only an alias pointing to the original my_fav_numbers object.
|
||||
# Assigning a new name does not create a new object.
|
||||
>>> id(your_fav_numbers)
|
||||
4517478208
|
||||
|
||||
|
||||
>>> my_fav_numbers is not your_fav_numbers
|
||||
False
|
||||
|
||||
>>> my_fav_numbers is not None
|
||||
True
|
||||
|
||||
>>> my_fav_numbers is NotImplemented
|
||||
False
|
||||
```
|
||||
|
||||
## Membership comparisons
|
||||
|
||||
The operators `in` and `not in` test for _membership_.
|
||||
`<fish> in <soup>` evaluates to `True` if `<fish>` is a member of `<soup>` (_if `<fish>` is a subset of or is contained within `<soup>`_), and evaluates `False` otherwise.
|
||||
`<fish> not in <soup>` returns the negation, or _opposite of_ `<fish> in <soup>`.
|
||||
|
||||
For string and bytes types, `<name> in <fullname>` is `True` _**if and only if**_ `<name>` is a substring of `<fullname>`.
|
||||
|
||||
```python
|
||||
# A set of lucky numbers.
|
||||
>>> lucky_numbers = {11, 22, 33}
|
||||
>>> 22 in lucky_numbers
|
||||
True
|
||||
|
||||
>>> 44 in lucky_numbers
|
||||
False
|
||||
|
||||
# A dictionary of employee information.
|
||||
>>> employee = {'name': 'John Doe',
|
||||
'id': 67826, 'age': 33,
|
||||
'title': 'ceo'}
|
||||
|
||||
# Checking for the membership of certain keys.
|
||||
>>> 'age' in employee
|
||||
True
|
||||
|
||||
>>> 33 in employee
|
||||
False
|
||||
|
||||
>>> 'lastname' not in employee
|
||||
True
|
||||
|
||||
# Checking for substring membership
|
||||
>>> name = 'Super Batman'
|
||||
>>> 'Bat' in name
|
||||
True
|
||||
|
||||
>>> 'Batwoman' in name
|
||||
False
|
||||
```
|
||||
|
||||
[arithmetic conversions]: https://docs.python.org/3/reference/expressions.html?highlight=number%20conversion#arithmetic-conversions
|
||||
[boolean operations]: https://docs.python.org/3/library/stdtypes.html#boolean-operations-and-or-not
|
||||
[complex numbers]: https://docs.python.org/3/library/functions.html#complex
|
||||
[decimal numbers]: https://docs.python.org/3/library/decimal.html
|
||||
[hex]: https://docs.python.org/3/library/functions.html?highlight=hex#hex
|
||||
[id function]: https://docs.python.org/3/library/functions.html#id
|
||||
[lexographic order]: https://en.wikipedia.org/wiki/Lexicographic_order
|
||||
[object identity]: https://docs.python.org/3/reference/datamodel.html
|
||||
[octal]: https://docs.python.org/3/library/functions.html?#oct
|
||||
[ord]: https://docs.python.org/3/library/functions.html#ord
|
||||
[pep8 programming recommendations]: https://pep8.org/#programming-recommendations
|
||||
[rational numbers]: https://docs.python.org/3/library/fractions.html
|
||||
[rich comparisons]: https://docs.python.org/3/reference/datamodel.html#object.__lt__
|
||||
[three way boolean comparison]: https://en.wikipedia.org/wiki/Three-way_comparison
|
||||
[value comparisons none]: https://docs.python.org/3/reference/expressions.html?highlight=none#value-comparisons
|
||||
[value comparisons]: https://docs.python.org/3/reference/expressions.html?highlight=nan#value-comparisons
|
||||
|
||||
## Instructions
|
||||
|
||||
In this exercise you are going to implement some rules of [Blackjack][blackjack],
|
||||
such as the way the game is played and scored.
|
||||
|
||||
**Note** : In this exercise, _`A`_ means ace, _`J`_ means jack, _`Q`_ means queen, and _`K`_ means king.
|
||||
Jokers are discarded.
|
||||
A [standard French-suited 52-card deck][standard_deck] is assumed, but in most versions, several decks are shuffled together for play.
|
||||
|
||||
## 1. Calculate the value of a card
|
||||
|
||||
In Blackjack, it is up to each individual player if an ace is worth 1 or 11 points (_more on that later_).
|
||||
Face cards (`J`, `Q`, `K`) are scored at 10 points and any other card is worth its "pip" (_numerical_) value.
|
||||
|
||||
Define the `value_of_card(<card>)` function with parameter `card`.
|
||||
The function should return the _numerical value_ of the passed-in card string.
|
||||
Since an ace can take on multiple values (1 **or** 11), this function should fix the value of an ace card at 1 for the time being.
|
||||
Later on, you will implement a function to determine the value of an ace card, given an existing hand.
|
||||
|
||||
```python
|
||||
>>> value_of_card('K')
|
||||
10
|
||||
|
||||
>>> value_of_card('4')
|
||||
4
|
||||
|
||||
>>> value_of_card('A')
|
||||
1
|
||||
```
|
||||
|
||||
## 2. Determine which card has a higher value
|
||||
|
||||
Define the `higher_card(<card_one>, <card_two>)` function having parameters `card_one` and `card_two`.
|
||||
For scoring purposes, the value of `J`, `Q` or `K` is 10.
|
||||
The function should return which card has the higher value for scoring.
|
||||
If both cards have an equal value, return both.
|
||||
Returning both cards can be done by using a comma in the `return` statement:
|
||||
|
||||
```python
|
||||
# Using a comma in a return creates a Tuple. Tuples will be covered in a later exercise.
|
||||
>>> def returning_two_values(value_one, value_two):
|
||||
return value_one, value_two
|
||||
|
||||
>>> returning_two_values('K', '3')
|
||||
('K', '3')
|
||||
```
|
||||
|
||||
An ace can take on multiple values, so we will fix `A` cards to a value of 1 for this task.
|
||||
|
||||
```python
|
||||
>>> higher_card('K', '10')
|
||||
('K', '10')
|
||||
|
||||
>>> higher_card('4', '6')
|
||||
'6'
|
||||
|
||||
>>> higher_card('K', 'A')
|
||||
'K'
|
||||
```
|
||||
|
||||
## 3. Calculate the value of an ace
|
||||
|
||||
As mentioned before, an ace can be worth _either_ 1 **or** 11 points.
|
||||
Players try to get as close as possible to a score of 21, without going _over_ 21 (_going "bust"_).
|
||||
|
||||
Define the `value_of_ace(<card_one>, <card_two>)` function with parameters `card_one` and `card_two`, which are a pair of cards already in the hand _before_ getting an ace card.
|
||||
Your function will have to decide if the upcoming ace will get a value of 1 or a value of 11, and return that value.
|
||||
Remember: the value of the hand with the ace needs to be as high as possible _without_ going over 21.
|
||||
|
||||
**Hint**: if we already have an ace in hand, then the value for the upcoming ace would be 1.
|
||||
|
||||
```python
|
||||
>>> value_of_ace('6', 'K')
|
||||
1
|
||||
|
||||
>>> value_of_ace('7', '3')
|
||||
11
|
||||
```
|
||||
|
||||
## 4. Determine a "Natural" or "Blackjack" Hand
|
||||
|
||||
If the first two cards a player is dealt are an ace (A) and a ten-card (_10, K , Q or J_), then the player has a score of 21.
|
||||
This is known as a blackjack hand.
|
||||
|
||||
|
||||
Define the `is_blackjack(<card_one>, <card_two>)` function with parameters `card_one` and `card_two`, which are a pair of cards.
|
||||
Determine if the two-card hand is a `blackjack`, and return the boolean `True` if it is, `False` otherwise.
|
||||
|
||||
**Note** : The score _calculation_ can be done in many ways.
|
||||
But if possible, we'd like you to check if there is an ace and a ten-card **_in_** the hand (or at a certain position), as opposed to _summing_ the hand values.
|
||||
|
||||
```python
|
||||
>>> is_blackjack('A', 'K')
|
||||
True
|
||||
|
||||
>>> is_blackjack('10', '9')
|
||||
False
|
||||
```
|
||||
|
||||
## 5. Splitting pairs
|
||||
|
||||
If the players first two cards are of the same value, such as two sixes, or a `Q` and `K` a player may choose to treat them as two separate hands.
|
||||
This is known as "splitting pairs".
|
||||
|
||||
Define the `can_split_pairs(<card_one>, <card_two>)` function with parameters `card_one` and `card_two`, which are a pair of cards.
|
||||
Determine if this two-card hand can be split into two pairs.
|
||||
If the hand can be split, return the boolean `True` otherwise, return `False`
|
||||
|
||||
```python
|
||||
>>> can_split_pairs('Q', 'K')
|
||||
True
|
||||
|
||||
>>> can_split_pairs('10', 'A')
|
||||
False
|
||||
```
|
||||
|
||||
## 6. Doubling down
|
||||
|
||||
When the original two cards dealt total 9, 10, or 11 points, a player can place an additional bet equal to their original bet.
|
||||
This is known as "doubling down".
|
||||
|
||||
Define the `can_double_down(<card_one>, <card_two>)` function with parameters `card_one` and `card_two`, which are a pair of cards.
|
||||
Determine if the two-card hand can be "doubled down", and return the boolean `True` if it can, `False` otherwise.
|
||||
|
||||
```python
|
||||
>>> can_double_down('A', '9')
|
||||
True
|
||||
|
||||
>>> can_double_down('10', '2')
|
||||
False
|
||||
```
|
||||
|
||||
[blackjack]: https://bicyclecards.com/how-to-play/blackjack/
|
||||
[standard_deck]: https://en.wikipedia.org/wiki/Standard_52-card_deck
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @Ticktakto
|
||||
- @Yabby1997
|
||||
- @limm-jk
|
||||
- @OMEGA-Y
|
||||
- @wnstj2007
|
||||
- @pranasziaukas
|
||||
- @bethanyG
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @PaulT89
|
81
python/black-jack/black_jack.py
Normal file
81
python/black-jack/black_jack.py
Normal file
|
@ -0,0 +1,81 @@
|
|||
"""Functions to help play and score a game of blackjack.
|
||||
|
||||
How to play blackjack: https://bicyclecards.com/how-to-play/blackjack/
|
||||
"Standard" playing cards: https://en.wikipedia.org/wiki/Standard_52-card_deck
|
||||
"""
|
||||
|
||||
|
||||
def value_of_card(card):
|
||||
"""Determine the scoring value of a card.
|
||||
|
||||
:param card: str - given card.
|
||||
:return: int - value of a given card. See below for values.
|
||||
|
||||
1. 'J', 'Q', or 'K' (otherwise known as "face cards") = 10
|
||||
2. 'A' (ace card) = 1
|
||||
3. '2' - '10' = numerical value.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def higher_card(card_one, card_two):
|
||||
"""Determine which card has a higher value in the hand.
|
||||
|
||||
:param card_one, card_two: str - cards dealt in hand. See below for values.
|
||||
:return: str or tuple - resulting Tuple contains both cards if they are of equal value.
|
||||
|
||||
1. 'J', 'Q', or 'K' (otherwise known as "face cards") = 10
|
||||
2. 'A' (ace card) = 1
|
||||
3. '2' - '10' = numerical value.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def value_of_ace(card_one, card_two):
|
||||
"""Calculate the most advantageous value for the ace card.
|
||||
|
||||
:param card_one, card_two: str - card dealt. See below for values.
|
||||
:return: int - either 1 or 11 value of the upcoming ace card.
|
||||
|
||||
1. 'J', 'Q', or 'K' (otherwise known as "face cards") = 10
|
||||
2. 'A' (ace card) = 11 (if already in hand)
|
||||
3. '2' - '10' = numerical value.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def is_blackjack(card_one, card_two):
|
||||
"""Determine if the hand is a 'natural' or 'blackjack'.
|
||||
|
||||
:param card_one, card_two: str - card dealt. See below for values.
|
||||
:return: bool - is the hand is a blackjack (two cards worth 21).
|
||||
|
||||
1. 'J', 'Q', or 'K' (otherwise known as "face cards") = 10
|
||||
2. 'A' (ace card) = 11 (if already in hand)
|
||||
3. '2' - '10' = numerical value.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def can_split_pairs(card_one, card_two):
|
||||
"""Determine if a player can split their hand into two hands.
|
||||
|
||||
:param card_one, card_two: str - cards dealt.
|
||||
:return: bool - can the hand be split into two pairs? (i.e. cards are of the same value).
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def can_double_down(card_one, card_two):
|
||||
"""Determine if a blackjack player can place a double down bet.
|
||||
|
||||
:param card_one, card_two: str - first and second cards in hand.
|
||||
:return: bool - can the hand can be doubled down? (i.e. totals 9, 10 or 11 points).
|
||||
"""
|
||||
|
||||
pass
|
114
python/black-jack/black_jack_test.py
Normal file
114
python/black-jack/black_jack_test.py
Normal file
|
@ -0,0 +1,114 @@
|
|||
import unittest
|
||||
import pytest
|
||||
|
||||
from black_jack import (
|
||||
value_of_card,
|
||||
higher_card,
|
||||
value_of_ace,
|
||||
is_blackjack,
|
||||
can_split_pairs,
|
||||
can_double_down
|
||||
)
|
||||
|
||||
|
||||
class BlackJackTest(unittest.TestCase):
|
||||
|
||||
@pytest.mark.task(taskno=1)
|
||||
def test_value_of_card(self):
|
||||
test_data = [('2', 2), ('5', 5), ('8', 8),
|
||||
('A', 1), ('10', 10), ('J', 10),
|
||||
('Q', 10), ('K', 10)]
|
||||
|
||||
for variant, (card, expected) in enumerate(test_data, 1):
|
||||
with self.subTest(f'variation #{variant}', card=card, expected=expected):
|
||||
actual_result = value_of_card(card)
|
||||
error_msg = (f'Called value_of_card({card}). '
|
||||
f'The function returned {actual_result} as the value of the {card} card, '
|
||||
f'but the test expected {expected} as the {card} card value.')
|
||||
|
||||
self.assertEqual(actual_result, expected, msg=error_msg)
|
||||
|
||||
|
||||
@pytest.mark.task(taskno=2)
|
||||
def test_higher_card(self):
|
||||
test_data = [('A', 'A', ('A', 'A')),
|
||||
('10', 'J', ('10', 'J')),
|
||||
('3', 'A', '3'),
|
||||
('3', '6', '6'),
|
||||
('Q', '10', ('Q', '10')),
|
||||
('4', '4', ('4', '4')),
|
||||
('9', '10', '10'),
|
||||
('6', '9', '9'),
|
||||
('4', '8', '8')]
|
||||
|
||||
for variant, (card_one, card_two, expected) in enumerate(test_data, 1):
|
||||
with self.subTest(f'variation #{variant}', card_one=card_one, card_two=card_two, expected=expected):
|
||||
actual_result = higher_card(card_one, card_two)
|
||||
error_msg = (f'Called higher_card({card_one}, {card_two}). '
|
||||
f'The function returned {actual_result}, '
|
||||
f'but the test expected {expected} as the result for the cards {card_one, card_two}.')
|
||||
|
||||
self.assertEqual(actual_result, expected, msg=error_msg)
|
||||
|
||||
@pytest.mark.task(taskno=3)
|
||||
def test_value_of_ace(self):
|
||||
test_data = [('2', '3', 11), ('3', '6', 11), ('5', '2', 11),
|
||||
('8', '2', 11), ('5', '5', 11), ('Q', 'A', 1),
|
||||
('10', '2', 1), ('7', '8', 1), ('J', '9', 1),
|
||||
('K', 'K', 1), ('2', 'A', 1), ('A', '2', 1)]
|
||||
|
||||
for variant, (card_one, card_two, ace_value) in enumerate(test_data, 1):
|
||||
with self.subTest(f'variation #{variant}', card_one=card_one, card_two=card_two, ace_value=ace_value):
|
||||
actual_result = value_of_ace(card_one, card_two)
|
||||
error_msg = (f'Called value_of_ace({card_one}, {card_two}). '
|
||||
f'The function returned {actual_result}, '
|
||||
f'but the test expected {ace_value} as the value of an ace card '
|
||||
f'when the hand includes {card_one, card_two}.')
|
||||
|
||||
self.assertEqual(value_of_ace(card_one, card_two), ace_value, msg=error_msg)
|
||||
|
||||
@pytest.mark.task(taskno=4)
|
||||
def test_is_blackjack(self):
|
||||
test_data = [(('A', 'K'), True), (('10', 'A'), True),
|
||||
(('10', '9'), False), (('A', 'A'), False),
|
||||
(('4', '7'), False), (('9', '2'), False),
|
||||
(('Q', 'K'), False)]
|
||||
|
||||
for variant, (hand, expected) in enumerate(test_data, 1):
|
||||
with self.subTest(f'variation #{variant}', hand=hand, expected=expected):
|
||||
actual_result = is_blackjack(*hand)
|
||||
error_msg = (f'Called is_blackjack({hand[0]}, {hand[1]}). '
|
||||
f'The function returned {actual_result}, '
|
||||
f'but hand {hand} {"is" if expected else "is not"} a blackjack.')
|
||||
|
||||
self.assertEqual(actual_result, expected, msg=error_msg)
|
||||
|
||||
@pytest.mark.task(taskno=5)
|
||||
def test_can_split_pairs(self):
|
||||
test_data = [(('Q', 'K'), True), (('6', '6'), True),
|
||||
(('A', 'A'), True),(('10', 'A'), False),
|
||||
(('10', '9'), False)]
|
||||
|
||||
for variant, (hand, expected) in enumerate(test_data, 1):
|
||||
with self.subTest(f'variation #{variant}', input=hand, expected=expected):
|
||||
actual_result = can_split_pairs(*hand)
|
||||
error_msg = (f'Called can_split_pairs({hand[0]}, {hand[1]}). '
|
||||
f'The function returned {actual_result}, '
|
||||
f'but hand {hand} {"can" if expected else "cannot"} be split into pairs.')
|
||||
|
||||
self.assertEqual(actual_result, expected, msg=error_msg)
|
||||
|
||||
@pytest.mark.task(taskno=6)
|
||||
def test_can_double_down(self):
|
||||
test_data = [(('A', '9'), True), (('K', 'A'), True),
|
||||
(('4', '5'), True),(('A', 'A'), False),
|
||||
(('10', '2'), False), (('10', '9'), False)]
|
||||
|
||||
for variant, (hand, expected) in enumerate(test_data, 1):
|
||||
with self.subTest(f'variation #{variant}', hand=hand, expected=expected):
|
||||
actual_result = can_double_down(*hand)
|
||||
error_msg = (f'Called can_double_down({hand[0]}, {hand[1]}). '
|
||||
f'The function returned {actual_result}, '
|
||||
f'but hand {hand} {"can" if expected else "cannot"} be doubled down.')
|
||||
|
||||
self.assertEqual(actual_result, expected, msg=error_msg)
|
47
python/bob/.exercism/config.json
Normal file
47
python/bob/.exercism/config.json
Normal file
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
"authors": [],
|
||||
"contributors": [
|
||||
"0xae",
|
||||
"aldraco",
|
||||
"atg-abhishek",
|
||||
"austinlyons",
|
||||
"behrtam",
|
||||
"BethanyG",
|
||||
"cmccandless",
|
||||
"cypher",
|
||||
"Dog",
|
||||
"etrepum",
|
||||
"ikhadykin",
|
||||
"janetriley",
|
||||
"jremmen",
|
||||
"koljakube",
|
||||
"kytrinyx",
|
||||
"lowks",
|
||||
"lucasdpau",
|
||||
"miketamis",
|
||||
"N-Parsons",
|
||||
"patricksjackson",
|
||||
"pheanex",
|
||||
"sdublish",
|
||||
"sjakobi",
|
||||
"stonemirror",
|
||||
"thenigan",
|
||||
"thomasjpfan",
|
||||
"tqa236",
|
||||
"yawpitch"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"bob.py"
|
||||
],
|
||||
"test": [
|
||||
"bob_test.py"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.py"
|
||||
]
|
||||
},
|
||||
"blurb": "Bob is a lackadaisical teenager. In conversation, his responses are very limited.",
|
||||
"source": "Inspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial.",
|
||||
"source_url": "https://pine.fm/LearnToProgram/?Chapter=06"
|
||||
}
|
1
python/bob/.exercism/metadata.json
Normal file
1
python/bob/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"track":"python","exercise":"bob","id":"43ba401157eb4fbdbe509c56987c49c3","url":"https://exercism.org/tracks/python/exercises/bob","handle":"DanielSiepmann","is_requester":true,"auto_approve":false}
|
130
python/bob/HELP.md
Normal file
130
python/bob/HELP.md
Normal file
|
@ -0,0 +1,130 @@
|
|||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
We use [pytest][pytest: Getting Started Guide] as our website test runner.
|
||||
You will need to install `pytest` on your development machine if you want to run tests for the Python track locally.
|
||||
You should also install the following `pytest` plugins:
|
||||
|
||||
- [pytest-cache][pytest-cache]
|
||||
- [pytest-subtests][pytest-subtests]
|
||||
|
||||
Extended information can be found in our website [Python testing guide][Python track tests page].
|
||||
|
||||
|
||||
### Running Tests
|
||||
|
||||
To run the included tests, navigate to the folder where the exercise is stored using `cd` in your terminal (_replace `{exercise-folder-location}` below with your path_).
|
||||
Test files usually end in `_test.py`, and are the same tests that run on the website when a solution is uploaded.
|
||||
|
||||
Linux/MacOS
|
||||
```bash
|
||||
$ cd {path/to/exercise-folder-location}
|
||||
```
|
||||
|
||||
Windows
|
||||
```powershell
|
||||
PS C:\Users\foobar> cd {path\to\exercise-folder-location}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
Next, run the `pytest` command in your terminal, replacing `{exercise_test.py}` with the name of the test file:
|
||||
|
||||
Linux/MacOS
|
||||
```bash
|
||||
$ python3 -m pytest -o markers=task {exercise_test.py}
|
||||
==================== 7 passed in 0.08s ====================
|
||||
```
|
||||
|
||||
Windows
|
||||
```powershell
|
||||
PS C:\Users\foobar> py -m pytest -o markers=task {exercise_test.py}
|
||||
==================== 7 passed in 0.08s ====================
|
||||
```
|
||||
|
||||
|
||||
### Common options
|
||||
- `-o` : override default `pytest.ini` (_you can use this to avoid marker warnings_)
|
||||
- `-v` : enable verbose output.
|
||||
- `-x` : stop running tests on first failure.
|
||||
- `--ff` : run failures from previous test before running other test cases.
|
||||
|
||||
For additional options, use `python3 -m pytest -h` or `py -m pytest -h`.
|
||||
|
||||
|
||||
### Fixing warnings
|
||||
|
||||
If you do not use `pytest -o markers=task` when invoking `pytest`, you might receive a `PytestUnknownMarkWarning` for tests that use our new syntax:
|
||||
|
||||
```bash
|
||||
PytestUnknownMarkWarning: Unknown pytest.mark.task - is this a typo? You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/stable/mark.html
|
||||
```
|
||||
|
||||
To avoid typing `pytest -o markers=task` for every test you run, you can use a `pytest.ini` configuration file.
|
||||
We have made one that can be downloaded from the top level of the Python track directory: [pytest.ini][pytest.ini].
|
||||
|
||||
You can also create your own `pytest.ini` file with the following content:
|
||||
|
||||
```ini
|
||||
[pytest]
|
||||
markers =
|
||||
task: A concept exercise task.
|
||||
```
|
||||
|
||||
Placing the `pytest.ini` file in the _root_ or _working_ directory for your Python track exercises will register the marks and stop the warnings.
|
||||
More information on pytest marks can be found in the `pytest` documentation on [marking test functions][pytest: marking test functions with attributes] and the `pytest` documentation on [working with custom markers][pytest: working with custom markers].
|
||||
|
||||
Information on customizing pytest configurations can be found in the `pytest` documentation on [configuration file formats][pytest: configuration file formats].
|
||||
|
||||
|
||||
### Extending your IDE or Code Editor
|
||||
|
||||
Many IDEs and code editors have built-in support for using `pytest` and other code quality tools.
|
||||
Some community-sourced options can be found on our [Python track tools page][Python track tools page].
|
||||
|
||||
[Pytest: Getting Started Guide]: https://docs.pytest.org/en/latest/getting-started.html
|
||||
[Python track tools page]: https://exercism.org/docs/tracks/python/tools
|
||||
[Python track tests page]: https://exercism.org/docs/tracks/python/tests
|
||||
[pytest-cache]:http://pythonhosted.org/pytest-cache/
|
||||
[pytest-subtests]:https://github.com/pytest-dev/pytest-subtests
|
||||
[pytest.ini]: https://github.com/exercism/python/blob/main/pytest.ini
|
||||
[pytest: configuration file formats]: https://docs.pytest.org/en/6.2.x/customize.html#configuration-file-formats
|
||||
[pytest: marking test functions with attributes]: https://docs.pytest.org/en/6.2.x/mark.html#raising-errors-on-unknown-marks
|
||||
[pytest: working with custom markers]: https://docs.pytest.org/en/6.2.x/example/markers.html#working-with-custom-markers
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit bob.py` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Python track's documentation](https://exercism.org/docs/tracks/python)
|
||||
- The [Python track's programming category on the forum](https://forum.exercism.org/c/programming/python)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
Below are some resources for getting help if you run into trouble:
|
||||
|
||||
- [The PSF](https://www.python.org) hosts Python downloads, documentation, and community resources.
|
||||
- [The Exercism Community on Discord](https://exercism.org/r/discord)
|
||||
- [Python Community on Discord](https://pythondiscord.com/) is a very helpful and active community.
|
||||
- [/r/learnpython/](https://www.reddit.com/r/learnpython/) is a subreddit designed for Python learners.
|
||||
- [#python on Libera.chat](https://www.python.org/community/irc/) this is where the core developers for the language hang out and get work done.
|
||||
- [Python Community Forums](https://discuss.python.org/)
|
||||
- [Free Code Camp Community Forums](https://forum.freecodecamp.org/)
|
||||
- [CodeNewbie Community Help Tag](https://community.codenewbie.org/t/help)
|
||||
- [Pythontutor](http://pythontutor.com/) for stepping through small code snippets visually.
|
||||
|
||||
Additionally, [StackOverflow](http://stackoverflow.com/questions/tagged/python) is a good spot to search for your problem/question to see if it has been answered already.
|
||||
If not - you can always [ask](https://stackoverflow.com/help/how-to-ask) or [answer](https://stackoverflow.com/help/how-to-answer) someone else's question.
|
72
python/bob/README.md
Normal file
72
python/bob/README.md
Normal file
|
@ -0,0 +1,72 @@
|
|||
# Bob
|
||||
|
||||
Welcome to Bob on Exercism's Python Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Introduction
|
||||
|
||||
Bob is a [lackadaisical][] teenager.
|
||||
He likes to think that he's very cool.
|
||||
And he definitely doesn't get excited about things.
|
||||
That wouldn't be cool.
|
||||
|
||||
When people talk to him, his responses are pretty limited.
|
||||
|
||||
[lackadaisical]: https://www.collinsdictionary.com/dictionary/english/lackadaisical
|
||||
|
||||
## Instructions
|
||||
|
||||
Your task is to determine what Bob will reply to someone when they say something to him or ask him a question.
|
||||
|
||||
Bob only ever answers one of five things:
|
||||
|
||||
- **"Sure."**
|
||||
This is his response if you ask him a question, such as "How are you?"
|
||||
The convention used for questions is that it ends with a question mark.
|
||||
- **"Whoa, chill out!"**
|
||||
This is his answer if you YELL AT HIM.
|
||||
The convention used for yelling is ALL CAPITAL LETTERS.
|
||||
- **"Calm down, I know what I'm doing!"**
|
||||
This is what he says if you yell a question at him.
|
||||
- **"Fine. Be that way!"**
|
||||
This is how he responds to silence.
|
||||
The convention used for silence is nothing, or various combinations of whitespace characters.
|
||||
- **"Whatever."**
|
||||
This is what he answers to anything else.
|
||||
|
||||
## Source
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @0xae
|
||||
- @aldraco
|
||||
- @atg-abhishek
|
||||
- @austinlyons
|
||||
- @behrtam
|
||||
- @BethanyG
|
||||
- @cmccandless
|
||||
- @cypher
|
||||
- @Dog
|
||||
- @etrepum
|
||||
- @ikhadykin
|
||||
- @janetriley
|
||||
- @jremmen
|
||||
- @koljakube
|
||||
- @kytrinyx
|
||||
- @lowks
|
||||
- @lucasdpau
|
||||
- @miketamis
|
||||
- @N-Parsons
|
||||
- @patricksjackson
|
||||
- @pheanex
|
||||
- @sdublish
|
||||
- @sjakobi
|
||||
- @stonemirror
|
||||
- @thenigan
|
||||
- @thomasjpfan
|
||||
- @tqa236
|
||||
- @yawpitch
|
||||
|
||||
### Based on
|
||||
|
||||
Inspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial. - https://pine.fm/LearnToProgram/?Chapter=06
|
2
python/bob/bob.py
Normal file
2
python/bob/bob.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
def response(hey_bob):
|
||||
pass
|
102
python/bob/bob_test.py
Normal file
102
python/bob/bob_test.py
Normal file
|
@ -0,0 +1,102 @@
|
|||
# These tests are auto-generated with test data from:
|
||||
# https://github.com/exercism/problem-specifications/tree/main/exercises/bob/canonical-data.json
|
||||
# File last updated on 2023-07-20
|
||||
|
||||
import unittest
|
||||
|
||||
from bob import (
|
||||
response,
|
||||
)
|
||||
|
||||
|
||||
class BobTest(unittest.TestCase):
|
||||
def test_stating_something(self):
|
||||
self.assertEqual(response("Tom-ay-to, tom-aaaah-to."), "Whatever.")
|
||||
|
||||
def test_shouting(self):
|
||||
self.assertEqual(response("WATCH OUT!"), "Whoa, chill out!")
|
||||
|
||||
def test_shouting_gibberish(self):
|
||||
self.assertEqual(response("FCECDFCAAB"), "Whoa, chill out!")
|
||||
|
||||
def test_asking_a_question(self):
|
||||
self.assertEqual(
|
||||
response("Does this cryogenic chamber make me look fat?"), "Sure."
|
||||
)
|
||||
|
||||
def test_asking_a_numeric_question(self):
|
||||
self.assertEqual(response("You are, what, like 15?"), "Sure.")
|
||||
|
||||
def test_asking_gibberish(self):
|
||||
self.assertEqual(response("fffbbcbeab?"), "Sure.")
|
||||
|
||||
def test_talking_forcefully(self):
|
||||
self.assertEqual(response("Hi there!"), "Whatever.")
|
||||
|
||||
def test_using_acronyms_in_regular_speech(self):
|
||||
self.assertEqual(
|
||||
response("It's OK if you don't want to go work for NASA."), "Whatever."
|
||||
)
|
||||
|
||||
def test_forceful_question(self):
|
||||
self.assertEqual(
|
||||
response("WHAT'S GOING ON?"), "Calm down, I know what I'm doing!"
|
||||
)
|
||||
|
||||
def test_shouting_numbers(self):
|
||||
self.assertEqual(response("1, 2, 3 GO!"), "Whoa, chill out!")
|
||||
|
||||
def test_no_letters(self):
|
||||
self.assertEqual(response("1, 2, 3"), "Whatever.")
|
||||
|
||||
def test_question_with_no_letters(self):
|
||||
self.assertEqual(response("4?"), "Sure.")
|
||||
|
||||
def test_shouting_with_special_characters(self):
|
||||
self.assertEqual(
|
||||
response("ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!"),
|
||||
"Whoa, chill out!",
|
||||
)
|
||||
|
||||
def test_shouting_with_no_exclamation_mark(self):
|
||||
self.assertEqual(response("I HATE THE DENTIST"), "Whoa, chill out!")
|
||||
|
||||
def test_statement_containing_question_mark(self):
|
||||
self.assertEqual(response("Ending with ? means a question."), "Whatever.")
|
||||
|
||||
def test_non_letters_with_question(self):
|
||||
self.assertEqual(response(":) ?"), "Sure.")
|
||||
|
||||
def test_prattling_on(self):
|
||||
self.assertEqual(response("Wait! Hang on. Are you going to be OK?"), "Sure.")
|
||||
|
||||
def test_silence(self):
|
||||
self.assertEqual(response(""), "Fine. Be that way!")
|
||||
|
||||
def test_prolonged_silence(self):
|
||||
self.assertEqual(response(" "), "Fine. Be that way!")
|
||||
|
||||
def test_alternate_silence(self):
|
||||
self.assertEqual(response("\t\t\t\t\t\t\t\t\t\t"), "Fine. Be that way!")
|
||||
|
||||
def test_multiple_line_question(self):
|
||||
self.assertEqual(
|
||||
response("\nDoes this cryogenic chamber make me look fat?\nNo."),
|
||||
"Whatever.",
|
||||
)
|
||||
|
||||
def test_starting_with_whitespace(self):
|
||||
self.assertEqual(response(" hmmmmmmm..."), "Whatever.")
|
||||
|
||||
def test_ending_with_whitespace(self):
|
||||
self.assertEqual(
|
||||
response("Okay if like my spacebar quite a bit? "), "Sure."
|
||||
)
|
||||
|
||||
def test_other_whitespace(self):
|
||||
self.assertEqual(response("\n\r \t"), "Fine. Be that way!")
|
||||
|
||||
def test_non_question_ending_with_whitespace(self):
|
||||
self.assertEqual(
|
||||
response("This is a statement ending with whitespace "), "Whatever."
|
||||
)
|
19
python/little-sisters-vocab/.exercism/config.json
Normal file
19
python/little-sisters-vocab/.exercism/config.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"authors": [
|
||||
"aldraco",
|
||||
"BethanyG"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"strings.py"
|
||||
],
|
||||
"test": [
|
||||
"strings_test.py"
|
||||
],
|
||||
"exemplar": [
|
||||
".meta/exemplar.py"
|
||||
]
|
||||
},
|
||||
"icon": "two-fer",
|
||||
"blurb": "Learn about strings by helping your little sister with her vocabulary homework."
|
||||
}
|
1
python/little-sisters-vocab/.exercism/metadata.json
Normal file
1
python/little-sisters-vocab/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"track":"python","exercise":"little-sisters-vocab","id":"67360f1a7adb4d37ab110d2e3d1dc2fc","url":"https://exercism.org/tracks/python/exercises/little-sisters-vocab","handle":"DanielSiepmann","is_requester":true,"auto_approve":false}
|
130
python/little-sisters-vocab/HELP.md
Normal file
130
python/little-sisters-vocab/HELP.md
Normal file
|
@ -0,0 +1,130 @@
|
|||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
We use [pytest][pytest: Getting Started Guide] as our website test runner.
|
||||
You will need to install `pytest` on your development machine if you want to run tests for the Python track locally.
|
||||
You should also install the following `pytest` plugins:
|
||||
|
||||
- [pytest-cache][pytest-cache]
|
||||
- [pytest-subtests][pytest-subtests]
|
||||
|
||||
Extended information can be found in our website [Python testing guide][Python track tests page].
|
||||
|
||||
|
||||
### Running Tests
|
||||
|
||||
To run the included tests, navigate to the folder where the exercise is stored using `cd` in your terminal (_replace `{exercise-folder-location}` below with your path_).
|
||||
Test files usually end in `_test.py`, and are the same tests that run on the website when a solution is uploaded.
|
||||
|
||||
Linux/MacOS
|
||||
```bash
|
||||
$ cd {path/to/exercise-folder-location}
|
||||
```
|
||||
|
||||
Windows
|
||||
```powershell
|
||||
PS C:\Users\foobar> cd {path\to\exercise-folder-location}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
Next, run the `pytest` command in your terminal, replacing `{exercise_test.py}` with the name of the test file:
|
||||
|
||||
Linux/MacOS
|
||||
```bash
|
||||
$ python3 -m pytest -o markers=task {exercise_test.py}
|
||||
==================== 7 passed in 0.08s ====================
|
||||
```
|
||||
|
||||
Windows
|
||||
```powershell
|
||||
PS C:\Users\foobar> py -m pytest -o markers=task {exercise_test.py}
|
||||
==================== 7 passed in 0.08s ====================
|
||||
```
|
||||
|
||||
|
||||
### Common options
|
||||
- `-o` : override default `pytest.ini` (_you can use this to avoid marker warnings_)
|
||||
- `-v` : enable verbose output.
|
||||
- `-x` : stop running tests on first failure.
|
||||
- `--ff` : run failures from previous test before running other test cases.
|
||||
|
||||
For additional options, use `python3 -m pytest -h` or `py -m pytest -h`.
|
||||
|
||||
|
||||
### Fixing warnings
|
||||
|
||||
If you do not use `pytest -o markers=task` when invoking `pytest`, you might receive a `PytestUnknownMarkWarning` for tests that use our new syntax:
|
||||
|
||||
```bash
|
||||
PytestUnknownMarkWarning: Unknown pytest.mark.task - is this a typo? You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/stable/mark.html
|
||||
```
|
||||
|
||||
To avoid typing `pytest -o markers=task` for every test you run, you can use a `pytest.ini` configuration file.
|
||||
We have made one that can be downloaded from the top level of the Python track directory: [pytest.ini][pytest.ini].
|
||||
|
||||
You can also create your own `pytest.ini` file with the following content:
|
||||
|
||||
```ini
|
||||
[pytest]
|
||||
markers =
|
||||
task: A concept exercise task.
|
||||
```
|
||||
|
||||
Placing the `pytest.ini` file in the _root_ or _working_ directory for your Python track exercises will register the marks and stop the warnings.
|
||||
More information on pytest marks can be found in the `pytest` documentation on [marking test functions][pytest: marking test functions with attributes] and the `pytest` documentation on [working with custom markers][pytest: working with custom markers].
|
||||
|
||||
Information on customizing pytest configurations can be found in the `pytest` documentation on [configuration file formats][pytest: configuration file formats].
|
||||
|
||||
|
||||
### Extending your IDE or Code Editor
|
||||
|
||||
Many IDEs and code editors have built-in support for using `pytest` and other code quality tools.
|
||||
Some community-sourced options can be found on our [Python track tools page][Python track tools page].
|
||||
|
||||
[Pytest: Getting Started Guide]: https://docs.pytest.org/en/latest/getting-started.html
|
||||
[Python track tools page]: https://exercism.org/docs/tracks/python/tools
|
||||
[Python track tests page]: https://exercism.org/docs/tracks/python/tests
|
||||
[pytest-cache]:http://pythonhosted.org/pytest-cache/
|
||||
[pytest-subtests]:https://github.com/pytest-dev/pytest-subtests
|
||||
[pytest.ini]: https://github.com/exercism/python/blob/main/pytest.ini
|
||||
[pytest: configuration file formats]: https://docs.pytest.org/en/6.2.x/customize.html#configuration-file-formats
|
||||
[pytest: marking test functions with attributes]: https://docs.pytest.org/en/6.2.x/mark.html#raising-errors-on-unknown-marks
|
||||
[pytest: working with custom markers]: https://docs.pytest.org/en/6.2.x/example/markers.html#working-with-custom-markers
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit strings.py` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Python track's documentation](https://exercism.org/docs/tracks/python)
|
||||
- The [Python track's programming category on the forum](https://forum.exercism.org/c/programming/python)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
Below are some resources for getting help if you run into trouble:
|
||||
|
||||
- [The PSF](https://www.python.org) hosts Python downloads, documentation, and community resources.
|
||||
- [The Exercism Community on Discord](https://exercism.org/r/discord)
|
||||
- [Python Community on Discord](https://pythondiscord.com/) is a very helpful and active community.
|
||||
- [/r/learnpython/](https://www.reddit.com/r/learnpython/) is a subreddit designed for Python learners.
|
||||
- [#python on Libera.chat](https://www.python.org/community/irc/) this is where the core developers for the language hang out and get work done.
|
||||
- [Python Community Forums](https://discuss.python.org/)
|
||||
- [Free Code Camp Community Forums](https://forum.freecodecamp.org/)
|
||||
- [CodeNewbie Community Help Tag](https://community.codenewbie.org/t/help)
|
||||
- [Pythontutor](http://pythontutor.com/) for stepping through small code snippets visually.
|
||||
|
||||
Additionally, [StackOverflow](http://stackoverflow.com/questions/tagged/python) is a good spot to search for your problem/question to see if it has been answered already.
|
||||
If not - you can always [ask](https://stackoverflow.com/help/how-to-ask) or [answer](https://stackoverflow.com/help/how-to-answer) someone else's question.
|
37
python/little-sisters-vocab/HINTS.md
Normal file
37
python/little-sisters-vocab/HINTS.md
Normal file
|
@ -0,0 +1,37 @@
|
|||
# Hints
|
||||
|
||||
## General
|
||||
|
||||
- The Python Docs [Tutorial for strings][python-str-doc] has an overview of the Python `str` type.
|
||||
- String methods [`str.join()`][str-join] and [`str.split()`][str-split] ar very helpful when processing strings.
|
||||
- The Python Docs on [Sequence Types][common sequence operations] has a rundown of operations common to all sequences, including `strings`, `lists`, `tuples`, and `ranges`.
|
||||
|
||||
There's four activities in the assignment, each with a set of text or words to work with.
|
||||
|
||||
## 1. Add a prefix to a word
|
||||
|
||||
- Small strings can be concatenated with the `+` operator.
|
||||
|
||||
## 2. Add prefixes to word groups
|
||||
|
||||
- Believe it or not, [`str.join()`][str-join] is all you need here.
|
||||
- Like [`str.split()`][str-split]`, `str.join()` can take an arbitrary-length string, made up of any unicode code points.
|
||||
|
||||
## 3. Remove a suffix from a word
|
||||
|
||||
- Strings can be indexed or sliced from either the left (starting at 0) or the right (starting at -1).
|
||||
- If you want the last code point of an arbitrary-length string, you can use [-1].
|
||||
- The last three letters in a string can be "sliced off" using a negative index. e.g. 'beautiful'[:-3] == 'beauti'
|
||||
|
||||
## 4. Extract and transform a word
|
||||
|
||||
- Using [`str.split()`][str-split] returns a `list` of strings broken on white space.
|
||||
- `lists` are sequences, and can be indexed.
|
||||
- [`str.split()`][str-split] can be directly indexed: `'Exercism rocks!'.split()[0] == 'Exercism'`
|
||||
- Be careful of punctuation! Periods can be removed via slice: `'dark.'[:-1] == 'dark'`
|
||||
|
||||
|
||||
[common sequence operations]: https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str
|
||||
[python-str-doc]: https://docs.python.org/3/tutorial/introduction.html#strings
|
||||
[str-join]: https://docs.python.org/3/library/stdtypes.html#str.join
|
||||
[str-split]: https://docs.python.org/3/library/stdtypes.html#str.split
|
340
python/little-sisters-vocab/README.md
Normal file
340
python/little-sisters-vocab/README.md
Normal file
|
@ -0,0 +1,340 @@
|
|||
# Little Sister's Vocabulary
|
||||
|
||||
Welcome to Little Sister's Vocabulary on Exercism's Python Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
|
||||
|
||||
## Introduction
|
||||
|
||||
A `str` in Python is an [immutable sequence][text sequence] of [Unicode code points][unicode code points].
|
||||
These could include letters, diacritical marks, positioning characters, numbers, currency symbols, emoji, punctuation, space and line break characters, and more.
|
||||
Being immutable, a `str` object's value in memory doesn't change; methods that appear to modify a string return a new copy or instance of that `str` object.
|
||||
|
||||
|
||||
A `str` literal can be declared via single `'` or double `"` quotes. The escape `\` character is available as needed.
|
||||
|
||||
|
||||
```python
|
||||
|
||||
>>> single_quoted = 'These allow "double quoting" without "escape" characters.'
|
||||
|
||||
>>> double_quoted = "These allow embedded 'single quoting', so you don't have to use an 'escape' character".
|
||||
|
||||
>>> escapes = 'If needed, a \'slash\' can be used as an escape character within a string when switching quote styles won\'t work.'
|
||||
```
|
||||
|
||||
Multi-line strings are declared with `'''` or `"""`.
|
||||
|
||||
|
||||
```python
|
||||
>>> triple_quoted = '''Three single quotes or "double quotes" in a row allow for multi-line string literals.
|
||||
Line break characters, tabs and other whitespace are fully supported.
|
||||
|
||||
You\'ll most often encounter these as "doc strings" or "doc tests" written just below the first line of a function or class definition.
|
||||
They\'re often used with auto documentation ✍ tools.
|
||||
'''
|
||||
```
|
||||
|
||||
Strings can be concatenated using the `+` operator.
|
||||
This method should be used sparingly, as it is not very performant or easily maintained.
|
||||
|
||||
|
||||
```python
|
||||
language = "Ukrainian"
|
||||
number = "nine"
|
||||
word = "дев'ять"
|
||||
|
||||
sentence = word + " " + "means" + " " + number + " in " + language + "."
|
||||
|
||||
>>> print(sentence)
|
||||
...
|
||||
"дев'ять means nine in Ukrainian."
|
||||
```
|
||||
|
||||
If a `list`, `tuple`, `set` or other collection of individual strings needs to be combined into a single `str`, [`<str>.join(<iterable>)`][str-join], is a better option:
|
||||
|
||||
|
||||
```python
|
||||
# str.join() makes a new string from the iterables elements.
|
||||
>>> chickens = ["hen", "egg", "rooster"]
|
||||
>>> ' '.join(chickens)
|
||||
'hen egg rooster'
|
||||
|
||||
# Any string can be used as the joining element.
|
||||
>>> ' :: '.join(chickens)
|
||||
'hen :: egg :: rooster'
|
||||
|
||||
>>> ' 🌿 '.join(chickens)
|
||||
'hen 🌿 egg 🌿 rooster'
|
||||
```
|
||||
|
||||
Code points within a `str` can be referenced by `0-based index` number from the left:
|
||||
|
||||
|
||||
```python
|
||||
creative = '창의적인'
|
||||
|
||||
>>> creative[0]
|
||||
'창'
|
||||
|
||||
>>> creative[2]
|
||||
'적'
|
||||
|
||||
>>> creative[3]
|
||||
'인'
|
||||
```
|
||||
|
||||
Indexing also works from the right, starting with a `-1-based index`:
|
||||
|
||||
|
||||
```python
|
||||
creative = '창의적인'
|
||||
|
||||
>>> creative[-4]
|
||||
'창'
|
||||
|
||||
>>> creative[-2]
|
||||
'적'
|
||||
|
||||
>>> creative[-1]
|
||||
'인'
|
||||
|
||||
```
|
||||
|
||||
|
||||
There is no separate “character” or "rune" type in Python, so indexing a string produces a new `str` of length 1:
|
||||
|
||||
|
||||
```python
|
||||
|
||||
>>> website = "exercism"
|
||||
>>> type(website[0])
|
||||
<class 'str'>
|
||||
|
||||
>>> len(website[0])
|
||||
1
|
||||
|
||||
>>> website[0] == website[0:1] == 'e'
|
||||
True
|
||||
```
|
||||
|
||||
Substrings can be selected via _slice notation_, using [`<str>[<start>:stop:<step>]`][common sequence operations] to produce a new string.
|
||||
Results exclude the `stop` index.
|
||||
If no `start` is given, the starting index will be 0.
|
||||
If no `stop` is given, the `stop` index will be the end of the string.
|
||||
|
||||
|
||||
```python
|
||||
moon_and_stars = '🌟🌟🌙🌟🌟⭐'
|
||||
sun_and_moon = '🌞🌙🌞🌙🌞🌙🌞🌙🌞'
|
||||
|
||||
>>> moon_and_stars[1:4]
|
||||
'🌟🌙🌟'
|
||||
|
||||
>>> moon_and_stars[:3]
|
||||
'🌟🌟🌙'
|
||||
|
||||
>>> moon_and_stars[3:]
|
||||
'🌟🌟⭐'
|
||||
|
||||
>>> moon_and_stars[:-1]
|
||||
'🌟🌟🌙🌟🌟'
|
||||
|
||||
>>> moon_and_stars[:-3]
|
||||
'🌟🌟🌙'
|
||||
|
||||
>>> sun_and_moon[::2]
|
||||
'🌞🌞🌞🌞🌞'
|
||||
|
||||
>>> sun_and_moon[:-2:2]
|
||||
'🌞🌞🌞🌞'
|
||||
|
||||
>>> sun_and_moon[1:-1:2]
|
||||
'🌙🌙🌙🌙'
|
||||
```
|
||||
|
||||
Strings can also be broken into smaller strings via [`<str>.split(<separator>)`][str-split], which will return a `list` of substrings.
|
||||
The list can then be further indexed or split, if needed.
|
||||
Using `<str>.split()` without any arguments will split the string on whitespace.
|
||||
|
||||
|
||||
```python
|
||||
>>> cat_ipsum = "Destroy house in 5 seconds mock the hooman."
|
||||
>>> cat_ipsum.split()
|
||||
...
|
||||
['Destroy', 'house', 'in', '5', 'seconds', 'mock', 'the', 'hooman.']
|
||||
|
||||
|
||||
>>> cat_ipsum.split()[-1]
|
||||
'hooman.'
|
||||
|
||||
|
||||
>>> cat_words = "feline, four-footed, ferocious, furry"
|
||||
>>> cat_words.split(', ')
|
||||
...
|
||||
['feline', 'four-footed', 'ferocious', 'furry']
|
||||
```
|
||||
|
||||
|
||||
Separators for `<str>.split()` can be more than one character.
|
||||
The **whole string** is used for split matching.
|
||||
|
||||
|
||||
```python
|
||||
|
||||
>>> colors = """red,
|
||||
orange,
|
||||
green,
|
||||
purple,
|
||||
yellow"""
|
||||
|
||||
>>> colors.split(',\n')
|
||||
['red', 'orange', 'green', 'purple', 'yellow']
|
||||
```
|
||||
|
||||
Strings support all [common sequence operations][common sequence operations].
|
||||
Individual code points can be iterated through in a loop via `for item in <str>`.
|
||||
Indexes _with_ items can be iterated through in a loop via `for index, item in enumerate(<str>)`.
|
||||
|
||||
|
||||
```python
|
||||
|
||||
>>> exercise = 'လေ့ကျင့်'
|
||||
|
||||
# Note that there are more code points than perceived glyphs or characters
|
||||
>>> for code_point in exercise:
|
||||
... print(code_point)
|
||||
...
|
||||
လ
|
||||
ေ
|
||||
့
|
||||
က
|
||||
ျ
|
||||
င
|
||||
်
|
||||
့
|
||||
|
||||
# Using enumerate will give both the value and index position of each element.
|
||||
>>> for index, code_point in enumerate(exercise):
|
||||
... print(index, ": ", code_point)
|
||||
...
|
||||
0 : လ
|
||||
1 : ေ
|
||||
2 : ့
|
||||
3 : က
|
||||
4 : ျ
|
||||
5 : င
|
||||
6 : ်
|
||||
7 : ့
|
||||
```
|
||||
|
||||
|
||||
[common sequence operations]: https://docs.python.org/3/library/stdtypes.html#common-sequence-operations
|
||||
[str-join]: https://docs.python.org/3/library/stdtypes.html#str.join
|
||||
[str-split]: https://docs.python.org/3/library/stdtypes.html#str.split
|
||||
[text sequence]: https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str
|
||||
[unicode code points]: https://stackoverflow.com/questions/27331819/whats-the-difference-between-a-character-a-code-point-a-glyph-and-a-grapheme
|
||||
|
||||
## Instructions
|
||||
|
||||
You are helping your younger sister with her English vocabulary homework, which she is finding very tedious.
|
||||
Her class is learning to create new words by adding _prefixes_ and _suffixes_.
|
||||
Given a set of words, the teacher is looking for correctly transformed words with correct spelling by adding the prefix to the beginning or the suffix to the ending.
|
||||
|
||||
There's four activities in the assignment, each with a set of text or words to work with.
|
||||
|
||||
|
||||
## 1. Add a prefix to a word
|
||||
|
||||
One of the most common prefixes in English is `un`, meaning "not".
|
||||
In this activity, your sister needs to make negative, or "not" words by adding `un` to them.
|
||||
|
||||
Implement the `add_prefix_un(<word>)` function that takes `word` as a parameter and returns a new `un` prefixed word:
|
||||
|
||||
|
||||
```python
|
||||
>>> add_prefix_un("happy")
|
||||
'unhappy'
|
||||
|
||||
>>> add_prefix_un("manageable")
|
||||
'unmanageable'
|
||||
```
|
||||
|
||||
|
||||
## 2. Add prefixes to word groups
|
||||
|
||||
There are four more common prefixes that your sister's class is studying:
|
||||
`en` (_meaning to 'put into' or 'cover with'_),
|
||||
`pre` (_meaning 'before' or 'forward'_),
|
||||
`auto` (_meaning 'self' or 'same'_),
|
||||
and `inter` (_meaning 'between' or 'among'_).
|
||||
|
||||
In this exercise, the class is creating groups of vocabulary words using these prefixes, so they can be studied together.
|
||||
Each prefix comes in a list with common words it's used with.
|
||||
The students need to apply the prefix and produce a string that shows the prefix applied to all of the words.
|
||||
|
||||
Implement the `make_word_groups(<vocab_words>)` function that takes a `vocab_words` as a parameter in the following form:
|
||||
`[<prefix>, <word_1>, <word_2> .... <word_n>]`, and returns a string with the prefix applied to each word that looks like:
|
||||
`'<prefix> :: <prefix><word_1> :: <prefix><word_2> :: <prefix><word_n>'`.
|
||||
|
||||
|
||||
```python
|
||||
>>> make_word_groups(['en', 'close', 'joy', 'lighten'])
|
||||
'en :: enclose :: enjoy :: enlighten'
|
||||
|
||||
>>> make_word_groups(['pre', 'serve', 'dispose', 'position'])
|
||||
'pre :: preserve :: predispose :: preposition'
|
||||
|
||||
>> make_word_groups(['auto', 'didactic', 'graph', 'mate'])
|
||||
'auto :: autodidactic :: autograph :: automate'
|
||||
|
||||
>>> make_word_groups(['inter', 'twine', 'connected', 'dependent'])
|
||||
'inter :: intertwine :: interconnected :: interdependent'
|
||||
```
|
||||
|
||||
|
||||
## 3. Remove a suffix from a word
|
||||
|
||||
`ness` is a common suffix that means _'state of being'_.
|
||||
In this activity, your sister needs to find the original root word by removing the `ness` suffix.
|
||||
But of course there are pesky spelling rules: If the root word originally ended in a consonant followed by a 'y', then the 'y' was changed to 'i'.
|
||||
Removing 'ness' needs to restore the 'y' in those root words. e.g. `happiness` --> `happi` --> `happy`.
|
||||
|
||||
Implement the `remove_suffix_ness(<word>)` function that takes in a `word`, and returns the root word without the `ness` suffix.
|
||||
|
||||
|
||||
```python
|
||||
>>> remove_suffix_ness("heaviness")
|
||||
'heavy'
|
||||
|
||||
>>> remove_suffix_ness("sadness")
|
||||
'sad'
|
||||
```
|
||||
|
||||
## 4. Extract and transform a word
|
||||
|
||||
Suffixes are often used to change the part of speech a word is assigned to.
|
||||
A common practice in English is "verbing" or "verbifying" -- where an adjective _becomes_ a verb by adding an `en` suffix.
|
||||
|
||||
In this task, your sister is going to practice "verbing" words by extracting an adjective from a sentence and turning it into a verb.
|
||||
Fortunately, all the words that need to be transformed here are "regular" - they don't need spelling changes to add the suffix.
|
||||
|
||||
Implement the `adjective_to_verb(<sentence>, <index>)` function that takes two parameters.
|
||||
A `sentence` using the vocabulary word, and the `index` of the word, once that sentence is split apart.
|
||||
The function should return the extracted adjective as a verb.
|
||||
|
||||
|
||||
```python
|
||||
>>> adjective_to_verb('I need to make that bright.', -1 )
|
||||
'brighten'
|
||||
|
||||
>>> adjective_to_verb('It got dark as the sun set.', 2)
|
||||
'darken'
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @aldraco
|
||||
- @BethanyG
|
54
python/little-sisters-vocab/strings.py
Normal file
54
python/little-sisters-vocab/strings.py
Normal file
|
@ -0,0 +1,54 @@
|
|||
"""Functions for creating, transforming, and adding prefixes to strings."""
|
||||
|
||||
|
||||
def add_prefix_un(word):
|
||||
"""Take the given word and add the 'un' prefix.
|
||||
|
||||
:param word: str - containing the root word.
|
||||
:return: str - of root word prepended with 'un'.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def make_word_groups(vocab_words):
|
||||
"""Transform a list containing a prefix and words into a string with the prefix followed by the words with prefix prepended.
|
||||
|
||||
:param vocab_words: list - of vocabulary words with prefix in first index.
|
||||
:return: str - of prefix followed by vocabulary words with
|
||||
prefix applied.
|
||||
|
||||
This function takes a `vocab_words` list and returns a string
|
||||
with the prefix and the words with prefix applied, separated
|
||||
by ' :: '.
|
||||
|
||||
For example: list('en', 'close', 'joy', 'lighten'),
|
||||
produces the following string: 'en :: enclose :: enjoy :: enlighten'.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def remove_suffix_ness(word):
|
||||
"""Remove the suffix from the word while keeping spelling in mind.
|
||||
|
||||
:param word: str - of word to remove suffix from.
|
||||
:return: str - of word with suffix removed & spelling adjusted.
|
||||
|
||||
For example: "heaviness" becomes "heavy", but "sadness" becomes "sad".
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def adjective_to_verb(sentence, index):
|
||||
"""Change the adjective within the sentence to a verb.
|
||||
|
||||
:param sentence: str - that uses the word in sentence.
|
||||
:param index: int - index of the word to remove and transform.
|
||||
:return: str - word that changes the extracted adjective to a verb.
|
||||
|
||||
For example, ("It got dark as the sun set.", 2) becomes "darken".
|
||||
"""
|
||||
|
||||
pass
|
126
python/little-sisters-vocab/strings_test.py
Normal file
126
python/little-sisters-vocab/strings_test.py
Normal file
|
@ -0,0 +1,126 @@
|
|||
import unittest
|
||||
import pytest
|
||||
from strings import (add_prefix_un,
|
||||
make_word_groups,
|
||||
remove_suffix_ness,
|
||||
adjective_to_verb)
|
||||
|
||||
|
||||
class LittleSistersVocabTest(unittest.TestCase):
|
||||
|
||||
@pytest.mark.task(taskno=1)
|
||||
def test_add_prefix_un(self):
|
||||
input_data = ['happy', 'manageable', 'fold', 'eaten', 'avoidable', 'usual']
|
||||
result_data = [f'un{item}' for item in input_data]
|
||||
|
||||
for variant, (word, expected) in enumerate(zip(input_data, result_data), start=1):
|
||||
with self.subTest(f'variation #{variant}', word=word, expected=expected):
|
||||
|
||||
actual_result = add_prefix_un(word)
|
||||
error_message = (f'Called add_prefix_un("{word}"). '
|
||||
f'The function returned "{actual_result}", but the '
|
||||
f'tests expected "{expected}" after adding "un" as a prefix.')
|
||||
|
||||
self.assertEqual(actual_result, expected, msg=error_message)
|
||||
|
||||
@pytest.mark.task(taskno=2)
|
||||
def test_make_word_groups_en(self):
|
||||
input_data = ['en', 'circle', 'fold', 'close', 'joy', 'lighten', 'tangle', 'able', 'code', 'culture']
|
||||
expected = ('en :: encircle :: enfold :: enclose :: enjoy :: enlighten ::'
|
||||
' entangle :: enable :: encode :: enculture')
|
||||
|
||||
actual_result = make_word_groups(input_data)
|
||||
error_message = (f'Called make_word_groups({input_data}). '
|
||||
f'The function returned "{actual_result}", '
|
||||
f'but the tests expected "{expected}" for the '
|
||||
'word groups.')
|
||||
|
||||
self.assertEqual(actual_result, expected, msg=error_message)
|
||||
|
||||
@pytest.mark.task(taskno=2)
|
||||
def test_make_word_groups_pre(self):
|
||||
input_data = ['pre', 'serve', 'dispose', 'position', 'requisite', 'digest',
|
||||
'natal', 'addressed', 'adolescent', 'assumption', 'mature', 'compute']
|
||||
expected = ('pre :: preserve :: predispose :: preposition :: prerequisite :: '
|
||||
'predigest :: prenatal :: preaddressed :: preadolescent :: preassumption :: '
|
||||
'premature :: precompute')
|
||||
|
||||
actual_result = make_word_groups(input_data)
|
||||
error_message = (f'Called make_word_groups({input_data}). '
|
||||
f'The function returned "{actual_result}", '
|
||||
f'but the tests expected "{expected}" for the '
|
||||
'word groups.')
|
||||
|
||||
self.assertEqual(actual_result, expected, msg=error_message)
|
||||
|
||||
@pytest.mark.task(taskno=2)
|
||||
def test_make_word_groups_auto(self):
|
||||
input_data = ['auto', 'didactic', 'graph', 'mate', 'chrome', 'centric', 'complete',
|
||||
'echolalia', 'encoder', 'biography']
|
||||
expected = ('auto :: autodidactic :: autograph :: automate :: autochrome :: '
|
||||
'autocentric :: autocomplete :: autoecholalia :: autoencoder :: '
|
||||
'autobiography')
|
||||
|
||||
actual_result = make_word_groups(input_data)
|
||||
error_message = (f'Called make_word_groups({input_data}). '
|
||||
f'The function returned "{actual_result}", '
|
||||
f'but the tests expected "{expected}" for the '
|
||||
'word groups.')
|
||||
|
||||
self.assertEqual(actual_result, expected, msg=error_message)
|
||||
|
||||
@pytest.mark.task(taskno=2)
|
||||
def test_make_words_groups_inter(self):
|
||||
input_data = ['inter', 'twine', 'connected', 'dependent', 'galactic', 'action',
|
||||
'stellar', 'cellular', 'continental', 'axial', 'operative', 'disciplinary']
|
||||
expected = ('inter :: intertwine :: interconnected :: interdependent :: '
|
||||
'intergalactic :: interaction :: interstellar :: intercellular :: '
|
||||
'intercontinental :: interaxial :: interoperative :: interdisciplinary')
|
||||
|
||||
actual_result = make_word_groups(input_data)
|
||||
error_message = (f'Called make_word_groups({input_data}). '
|
||||
f'The function returned "{actual_result}", '
|
||||
f'but the tests expected "{expected}" for the '
|
||||
'word groups.')
|
||||
|
||||
self.assertEqual(actual_result, expected, msg=error_message)
|
||||
|
||||
@pytest.mark.task(taskno=3)
|
||||
def test_remove_suffix_ness(self):
|
||||
input_data = ['heaviness', 'sadness', 'softness', 'crabbiness', 'lightness', 'artiness', 'edginess']
|
||||
result_data = ['heavy', 'sad', 'soft', 'crabby', 'light', 'arty', 'edgy']
|
||||
|
||||
for variant, (word, expected) in enumerate(zip(input_data, result_data), start=1):
|
||||
with self.subTest(f'variation #{variant}', word=word, expected=expected):
|
||||
actual_result = remove_suffix_ness(word)
|
||||
error_message = (f'Called remove_suffix_ness("{word}"). '
|
||||
f'The function returned "{actual_result}", '
|
||||
f'but the tests expected "{expected}" after the '
|
||||
'suffix was removed.')
|
||||
|
||||
self.assertEqual(actual_result, expected, msg=error_message)
|
||||
|
||||
@pytest.mark.task(taskno=4)
|
||||
def test_adjective_to_verb(self):
|
||||
input_data = ['Look at the bright sky.',
|
||||
'His expression went dark.',
|
||||
'The bread got hard after sitting out.',
|
||||
'The butter got soft in the sun.',
|
||||
'Her eyes were light blue.',
|
||||
'The morning fog made everything damp with mist.',
|
||||
'He cut the fence pickets short by mistake.',
|
||||
'Charles made weak crying noises.',
|
||||
'The black oil got on the white dog.']
|
||||
index_data = [-2, -1, 3, 3, -2, -3, 5, 2, 1]
|
||||
result_data = ['brighten', 'darken', 'harden', 'soften',
|
||||
'lighten', 'dampen', 'shorten', 'weaken', 'blacken']
|
||||
|
||||
for variant, (sentence, index, expected) in enumerate(zip(input_data, index_data, result_data), start=1):
|
||||
with self.subTest(f'variation #{variant}', sentence=sentence, index=index, expected=expected):
|
||||
actual_result = adjective_to_verb(sentence, index)
|
||||
error_message = (f'Called adjective_to_verb("{sentence}", {index}). '
|
||||
f'The function returned "{actual_result}", but the tests '
|
||||
f'expected "{expected}" as the verb for '
|
||||
f'the word at index {index}.')
|
||||
|
||||
self.assertEqual(actual_result, expected, msg=error_message)
|
30
python/pig-latin/.exercism/config.json
Normal file
30
python/pig-latin/.exercism/config.json
Normal file
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"authors": [
|
||||
"behrtam"
|
||||
],
|
||||
"contributors": [
|
||||
"akashsara",
|
||||
"cmccandless",
|
||||
"Dog",
|
||||
"ikhadykin",
|
||||
"N-Parsons",
|
||||
"pheanex",
|
||||
"Sukhj1nder",
|
||||
"tqa236",
|
||||
"yawpitch"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"pig_latin.py"
|
||||
],
|
||||
"test": [
|
||||
"pig_latin_test.py"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.py"
|
||||
]
|
||||
},
|
||||
"blurb": "Implement a program that translates from English to Pig Latin.",
|
||||
"source": "The Pig Latin exercise at Test First Teaching by Ultrasaurus",
|
||||
"source_url": "https://github.com/ultrasaurus/test-first-teaching/blob/master/learn_ruby/pig_latin/"
|
||||
}
|
1
python/pig-latin/.exercism/metadata.json
Normal file
1
python/pig-latin/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"track":"python","exercise":"pig-latin","id":"3f746fd8371241dca8d222d21db49a7b","url":"https://exercism.org/tracks/python/exercises/pig-latin","handle":"DanielSiepmann","is_requester":true,"auto_approve":false}
|
130
python/pig-latin/HELP.md
Normal file
130
python/pig-latin/HELP.md
Normal file
|
@ -0,0 +1,130 @@
|
|||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
We use [pytest][pytest: Getting Started Guide] as our website test runner.
|
||||
You will need to install `pytest` on your development machine if you want to run tests for the Python track locally.
|
||||
You should also install the following `pytest` plugins:
|
||||
|
||||
- [pytest-cache][pytest-cache]
|
||||
- [pytest-subtests][pytest-subtests]
|
||||
|
||||
Extended information can be found in our website [Python testing guide][Python track tests page].
|
||||
|
||||
|
||||
### Running Tests
|
||||
|
||||
To run the included tests, navigate to the folder where the exercise is stored using `cd` in your terminal (_replace `{exercise-folder-location}` below with your path_).
|
||||
Test files usually end in `_test.py`, and are the same tests that run on the website when a solution is uploaded.
|
||||
|
||||
Linux/MacOS
|
||||
```bash
|
||||
$ cd {path/to/exercise-folder-location}
|
||||
```
|
||||
|
||||
Windows
|
||||
```powershell
|
||||
PS C:\Users\foobar> cd {path\to\exercise-folder-location}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
Next, run the `pytest` command in your terminal, replacing `{exercise_test.py}` with the name of the test file:
|
||||
|
||||
Linux/MacOS
|
||||
```bash
|
||||
$ python3 -m pytest -o markers=task {exercise_test.py}
|
||||
==================== 7 passed in 0.08s ====================
|
||||
```
|
||||
|
||||
Windows
|
||||
```powershell
|
||||
PS C:\Users\foobar> py -m pytest -o markers=task {exercise_test.py}
|
||||
==================== 7 passed in 0.08s ====================
|
||||
```
|
||||
|
||||
|
||||
### Common options
|
||||
- `-o` : override default `pytest.ini` (_you can use this to avoid marker warnings_)
|
||||
- `-v` : enable verbose output.
|
||||
- `-x` : stop running tests on first failure.
|
||||
- `--ff` : run failures from previous test before running other test cases.
|
||||
|
||||
For additional options, use `python3 -m pytest -h` or `py -m pytest -h`.
|
||||
|
||||
|
||||
### Fixing warnings
|
||||
|
||||
If you do not use `pytest -o markers=task` when invoking `pytest`, you might receive a `PytestUnknownMarkWarning` for tests that use our new syntax:
|
||||
|
||||
```bash
|
||||
PytestUnknownMarkWarning: Unknown pytest.mark.task - is this a typo? You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/stable/mark.html
|
||||
```
|
||||
|
||||
To avoid typing `pytest -o markers=task` for every test you run, you can use a `pytest.ini` configuration file.
|
||||
We have made one that can be downloaded from the top level of the Python track directory: [pytest.ini][pytest.ini].
|
||||
|
||||
You can also create your own `pytest.ini` file with the following content:
|
||||
|
||||
```ini
|
||||
[pytest]
|
||||
markers =
|
||||
task: A concept exercise task.
|
||||
```
|
||||
|
||||
Placing the `pytest.ini` file in the _root_ or _working_ directory for your Python track exercises will register the marks and stop the warnings.
|
||||
More information on pytest marks can be found in the `pytest` documentation on [marking test functions][pytest: marking test functions with attributes] and the `pytest` documentation on [working with custom markers][pytest: working with custom markers].
|
||||
|
||||
Information on customizing pytest configurations can be found in the `pytest` documentation on [configuration file formats][pytest: configuration file formats].
|
||||
|
||||
|
||||
### Extending your IDE or Code Editor
|
||||
|
||||
Many IDEs and code editors have built-in support for using `pytest` and other code quality tools.
|
||||
Some community-sourced options can be found on our [Python track tools page][Python track tools page].
|
||||
|
||||
[Pytest: Getting Started Guide]: https://docs.pytest.org/en/latest/getting-started.html
|
||||
[Python track tools page]: https://exercism.org/docs/tracks/python/tools
|
||||
[Python track tests page]: https://exercism.org/docs/tracks/python/tests
|
||||
[pytest-cache]:http://pythonhosted.org/pytest-cache/
|
||||
[pytest-subtests]:https://github.com/pytest-dev/pytest-subtests
|
||||
[pytest.ini]: https://github.com/exercism/python/blob/main/pytest.ini
|
||||
[pytest: configuration file formats]: https://docs.pytest.org/en/6.2.x/customize.html#configuration-file-formats
|
||||
[pytest: marking test functions with attributes]: https://docs.pytest.org/en/6.2.x/mark.html#raising-errors-on-unknown-marks
|
||||
[pytest: working with custom markers]: https://docs.pytest.org/en/6.2.x/example/markers.html#working-with-custom-markers
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit pig_latin.py` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Python track's documentation](https://exercism.org/docs/tracks/python)
|
||||
- The [Python track's programming category on the forum](https://forum.exercism.org/c/programming/python)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
Below are some resources for getting help if you run into trouble:
|
||||
|
||||
- [The PSF](https://www.python.org) hosts Python downloads, documentation, and community resources.
|
||||
- [The Exercism Community on Discord](https://exercism.org/r/discord)
|
||||
- [Python Community on Discord](https://pythondiscord.com/) is a very helpful and active community.
|
||||
- [/r/learnpython/](https://www.reddit.com/r/learnpython/) is a subreddit designed for Python learners.
|
||||
- [#python on Libera.chat](https://www.python.org/community/irc/) this is where the core developers for the language hang out and get work done.
|
||||
- [Python Community Forums](https://discuss.python.org/)
|
||||
- [Free Code Camp Community Forums](https://forum.freecodecamp.org/)
|
||||
- [CodeNewbie Community Help Tag](https://community.codenewbie.org/t/help)
|
||||
- [Pythontutor](http://pythontutor.com/) for stepping through small code snippets visually.
|
||||
|
||||
Additionally, [StackOverflow](http://stackoverflow.com/questions/tagged/python) is a good spot to search for your problem/question to see if it has been answered already.
|
||||
If not - you can always [ask](https://stackoverflow.com/help/how-to-ask) or [answer](https://stackoverflow.com/help/how-to-answer) someone else's question.
|
47
python/pig-latin/README.md
Normal file
47
python/pig-latin/README.md
Normal file
|
@ -0,0 +1,47 @@
|
|||
# Pig Latin
|
||||
|
||||
Welcome to Pig Latin on Exercism's Python Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Instructions
|
||||
|
||||
Implement a program that translates from English to Pig Latin.
|
||||
|
||||
Pig Latin is a made-up children's language that's intended to be confusing.
|
||||
It obeys a few simple rules (below), but when it's spoken quickly it's really difficult for non-children (and non-native speakers) to understand.
|
||||
|
||||
- **Rule 1**: If a word begins with a vowel sound, add an "ay" sound to the end of the word.
|
||||
Please note that "xr" and "yt" at the beginning of a word make vowel sounds (e.g. "xray" -> "xrayay", "yttria" -> "yttriaay").
|
||||
- **Rule 2**: If a word begins with a consonant sound, move it to the end of the word and then add an "ay" sound to the end of the word.
|
||||
Consonant sounds can be made up of multiple consonants, such as the "ch" in "chair" or "st" in "stand" (e.g. "chair" -> "airchay").
|
||||
- **Rule 3**: If a word starts with a consonant sound followed by "qu", move it to the end of the word, and then add an "ay" sound to the end of the word (e.g. "square" -> "aresquay").
|
||||
- **Rule 4**: If a word contains a "y" after a consonant cluster or as the second letter in a two letter word it makes a vowel sound (e.g. "rhythm" -> "ythmrhay", "my" -> "ymay").
|
||||
|
||||
There are a few more rules for edge cases, and there are regional variants too.
|
||||
Check the tests for all the details.
|
||||
|
||||
Read more about [Pig Latin on Wikipedia][pig-latin].
|
||||
|
||||
[pig-latin]: https://en.wikipedia.org/wiki/Pig_latin
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @behrtam
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @akashsara
|
||||
- @cmccandless
|
||||
- @Dog
|
||||
- @ikhadykin
|
||||
- @N-Parsons
|
||||
- @pheanex
|
||||
- @Sukhj1nder
|
||||
- @tqa236
|
||||
- @yawpitch
|
||||
|
||||
### Based on
|
||||
|
||||
The Pig Latin exercise at Test First Teaching by Ultrasaurus - https://github.com/ultrasaurus/test-first-teaching/blob/master/learn_ruby/pig_latin/
|
2
python/pig-latin/pig_latin.py
Normal file
2
python/pig-latin/pig_latin.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
def translate(text):
|
||||
pass
|
77
python/pig-latin/pig_latin_test.py
Normal file
77
python/pig-latin/pig_latin_test.py
Normal file
|
@ -0,0 +1,77 @@
|
|||
# These tests are auto-generated with test data from:
|
||||
# https://github.com/exercism/problem-specifications/tree/main/exercises/pig-latin/canonical-data.json
|
||||
# File last updated on 2023-07-19
|
||||
|
||||
import unittest
|
||||
|
||||
from pig_latin import (
|
||||
translate,
|
||||
)
|
||||
|
||||
|
||||
class PigLatinTest(unittest.TestCase):
|
||||
def test_word_beginning_with_a(self):
|
||||
self.assertEqual(translate("apple"), "appleay")
|
||||
|
||||
def test_word_beginning_with_e(self):
|
||||
self.assertEqual(translate("ear"), "earay")
|
||||
|
||||
def test_word_beginning_with_i(self):
|
||||
self.assertEqual(translate("igloo"), "iglooay")
|
||||
|
||||
def test_word_beginning_with_o(self):
|
||||
self.assertEqual(translate("object"), "objectay")
|
||||
|
||||
def test_word_beginning_with_u(self):
|
||||
self.assertEqual(translate("under"), "underay")
|
||||
|
||||
def test_word_beginning_with_a_vowel_and_followed_by_a_qu(self):
|
||||
self.assertEqual(translate("equal"), "equalay")
|
||||
|
||||
def test_word_beginning_with_p(self):
|
||||
self.assertEqual(translate("pig"), "igpay")
|
||||
|
||||
def test_word_beginning_with_k(self):
|
||||
self.assertEqual(translate("koala"), "oalakay")
|
||||
|
||||
def test_word_beginning_with_x(self):
|
||||
self.assertEqual(translate("xenon"), "enonxay")
|
||||
|
||||
def test_word_beginning_with_q_without_a_following_u(self):
|
||||
self.assertEqual(translate("qat"), "atqay")
|
||||
|
||||
def test_word_beginning_with_ch(self):
|
||||
self.assertEqual(translate("chair"), "airchay")
|
||||
|
||||
def test_word_beginning_with_qu(self):
|
||||
self.assertEqual(translate("queen"), "eenquay")
|
||||
|
||||
def test_word_beginning_with_qu_and_a_preceding_consonant(self):
|
||||
self.assertEqual(translate("square"), "aresquay")
|
||||
|
||||
def test_word_beginning_with_th(self):
|
||||
self.assertEqual(translate("therapy"), "erapythay")
|
||||
|
||||
def test_word_beginning_with_thr(self):
|
||||
self.assertEqual(translate("thrush"), "ushthray")
|
||||
|
||||
def test_word_beginning_with_sch(self):
|
||||
self.assertEqual(translate("school"), "oolschay")
|
||||
|
||||
def test_word_beginning_with_yt(self):
|
||||
self.assertEqual(translate("yttria"), "yttriaay")
|
||||
|
||||
def test_word_beginning_with_xr(self):
|
||||
self.assertEqual(translate("xray"), "xrayay")
|
||||
|
||||
def test_y_is_treated_like_a_consonant_at_the_beginning_of_a_word(self):
|
||||
self.assertEqual(translate("yellow"), "ellowyay")
|
||||
|
||||
def test_y_is_treated_like_a_vowel_at_the_end_of_a_consonant_cluster(self):
|
||||
self.assertEqual(translate("rhythm"), "ythmrhay")
|
||||
|
||||
def test_y_as_second_letter_in_two_letter_word(self):
|
||||
self.assertEqual(translate("my"), "ymay")
|
||||
|
||||
def test_a_whole_phrase(self):
|
||||
self.assertEqual(translate("quick fast run"), "ickquay astfay unray")
|
32
python/raindrops/.exercism/config.json
Normal file
32
python/raindrops/.exercism/config.json
Normal file
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"authors": [],
|
||||
"contributors": [
|
||||
"behrtam",
|
||||
"BethanyG",
|
||||
"bsoyka",
|
||||
"cmccandless",
|
||||
"Dog",
|
||||
"ikhadykin",
|
||||
"kytrinyx",
|
||||
"lowks",
|
||||
"N-Parsons",
|
||||
"pheanex",
|
||||
"sjakobi",
|
||||
"tqa236",
|
||||
"yawpitch"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"raindrops.py"
|
||||
],
|
||||
"test": [
|
||||
"raindrops_test.py"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.py"
|
||||
]
|
||||
},
|
||||
"blurb": "Convert a number into its corresponding raindrop sounds - Pling, Plang and Plong.",
|
||||
"source": "A variation on FizzBuzz, a famous technical interview question that is intended to weed out potential candidates. That question is itself derived from Fizz Buzz, a popular children's game for teaching division.",
|
||||
"source_url": "https://en.wikipedia.org/wiki/Fizz_buzz"
|
||||
}
|
1
python/raindrops/.exercism/metadata.json
Normal file
1
python/raindrops/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"track":"python","exercise":"raindrops","id":"00ec103661614e07b410af1f21c48a65","url":"https://exercism.org/tracks/python/exercises/raindrops","handle":"DanielSiepmann","is_requester":true,"auto_approve":false}
|
130
python/raindrops/HELP.md
Normal file
130
python/raindrops/HELP.md
Normal file
|
@ -0,0 +1,130 @@
|
|||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
We use [pytest][pytest: Getting Started Guide] as our website test runner.
|
||||
You will need to install `pytest` on your development machine if you want to run tests for the Python track locally.
|
||||
You should also install the following `pytest` plugins:
|
||||
|
||||
- [pytest-cache][pytest-cache]
|
||||
- [pytest-subtests][pytest-subtests]
|
||||
|
||||
Extended information can be found in our website [Python testing guide][Python track tests page].
|
||||
|
||||
|
||||
### Running Tests
|
||||
|
||||
To run the included tests, navigate to the folder where the exercise is stored using `cd` in your terminal (_replace `{exercise-folder-location}` below with your path_).
|
||||
Test files usually end in `_test.py`, and are the same tests that run on the website when a solution is uploaded.
|
||||
|
||||
Linux/MacOS
|
||||
```bash
|
||||
$ cd {path/to/exercise-folder-location}
|
||||
```
|
||||
|
||||
Windows
|
||||
```powershell
|
||||
PS C:\Users\foobar> cd {path\to\exercise-folder-location}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
Next, run the `pytest` command in your terminal, replacing `{exercise_test.py}` with the name of the test file:
|
||||
|
||||
Linux/MacOS
|
||||
```bash
|
||||
$ python3 -m pytest -o markers=task {exercise_test.py}
|
||||
==================== 7 passed in 0.08s ====================
|
||||
```
|
||||
|
||||
Windows
|
||||
```powershell
|
||||
PS C:\Users\foobar> py -m pytest -o markers=task {exercise_test.py}
|
||||
==================== 7 passed in 0.08s ====================
|
||||
```
|
||||
|
||||
|
||||
### Common options
|
||||
- `-o` : override default `pytest.ini` (_you can use this to avoid marker warnings_)
|
||||
- `-v` : enable verbose output.
|
||||
- `-x` : stop running tests on first failure.
|
||||
- `--ff` : run failures from previous test before running other test cases.
|
||||
|
||||
For additional options, use `python3 -m pytest -h` or `py -m pytest -h`.
|
||||
|
||||
|
||||
### Fixing warnings
|
||||
|
||||
If you do not use `pytest -o markers=task` when invoking `pytest`, you might receive a `PytestUnknownMarkWarning` for tests that use our new syntax:
|
||||
|
||||
```bash
|
||||
PytestUnknownMarkWarning: Unknown pytest.mark.task - is this a typo? You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/stable/mark.html
|
||||
```
|
||||
|
||||
To avoid typing `pytest -o markers=task` for every test you run, you can use a `pytest.ini` configuration file.
|
||||
We have made one that can be downloaded from the top level of the Python track directory: [pytest.ini][pytest.ini].
|
||||
|
||||
You can also create your own `pytest.ini` file with the following content:
|
||||
|
||||
```ini
|
||||
[pytest]
|
||||
markers =
|
||||
task: A concept exercise task.
|
||||
```
|
||||
|
||||
Placing the `pytest.ini` file in the _root_ or _working_ directory for your Python track exercises will register the marks and stop the warnings.
|
||||
More information on pytest marks can be found in the `pytest` documentation on [marking test functions][pytest: marking test functions with attributes] and the `pytest` documentation on [working with custom markers][pytest: working with custom markers].
|
||||
|
||||
Information on customizing pytest configurations can be found in the `pytest` documentation on [configuration file formats][pytest: configuration file formats].
|
||||
|
||||
|
||||
### Extending your IDE or Code Editor
|
||||
|
||||
Many IDEs and code editors have built-in support for using `pytest` and other code quality tools.
|
||||
Some community-sourced options can be found on our [Python track tools page][Python track tools page].
|
||||
|
||||
[Pytest: Getting Started Guide]: https://docs.pytest.org/en/latest/getting-started.html
|
||||
[Python track tools page]: https://exercism.org/docs/tracks/python/tools
|
||||
[Python track tests page]: https://exercism.org/docs/tracks/python/tests
|
||||
[pytest-cache]:http://pythonhosted.org/pytest-cache/
|
||||
[pytest-subtests]:https://github.com/pytest-dev/pytest-subtests
|
||||
[pytest.ini]: https://github.com/exercism/python/blob/main/pytest.ini
|
||||
[pytest: configuration file formats]: https://docs.pytest.org/en/6.2.x/customize.html#configuration-file-formats
|
||||
[pytest: marking test functions with attributes]: https://docs.pytest.org/en/6.2.x/mark.html#raising-errors-on-unknown-marks
|
||||
[pytest: working with custom markers]: https://docs.pytest.org/en/6.2.x/example/markers.html#working-with-custom-markers
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit raindrops.py` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Python track's documentation](https://exercism.org/docs/tracks/python)
|
||||
- The [Python track's programming category on the forum](https://forum.exercism.org/c/programming/python)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
Below are some resources for getting help if you run into trouble:
|
||||
|
||||
- [The PSF](https://www.python.org) hosts Python downloads, documentation, and community resources.
|
||||
- [The Exercism Community on Discord](https://exercism.org/r/discord)
|
||||
- [Python Community on Discord](https://pythondiscord.com/) is a very helpful and active community.
|
||||
- [/r/learnpython/](https://www.reddit.com/r/learnpython/) is a subreddit designed for Python learners.
|
||||
- [#python on Libera.chat](https://www.python.org/community/irc/) this is where the core developers for the language hang out and get work done.
|
||||
- [Python Community Forums](https://discuss.python.org/)
|
||||
- [Free Code Camp Community Forums](https://forum.freecodecamp.org/)
|
||||
- [CodeNewbie Community Help Tag](https://community.codenewbie.org/t/help)
|
||||
- [Pythontutor](http://pythontutor.com/) for stepping through small code snippets visually.
|
||||
|
||||
Additionally, [StackOverflow](http://stackoverflow.com/questions/tagged/python) is a good spot to search for your problem/question to see if it has been answered already.
|
||||
If not - you can always [ask](https://stackoverflow.com/help/how-to-ask) or [answer](https://stackoverflow.com/help/how-to-answer) someone else's question.
|
75
python/raindrops/README.md
Normal file
75
python/raindrops/README.md
Normal file
|
@ -0,0 +1,75 @@
|
|||
# Raindrops
|
||||
|
||||
Welcome to Raindrops on Exercism's Python Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Introduction
|
||||
|
||||
Raindrops is a slightly more complex version of the FizzBuzz challenge, a classic interview question.
|
||||
|
||||
## Instructions
|
||||
|
||||
Your task is to convert a number into its corresponding raindrop sounds.
|
||||
|
||||
If a given number:
|
||||
|
||||
- is divisible by 3, add "Pling" to the result.
|
||||
- is divisible by 5, add "Plang" to the result.
|
||||
- is divisible by 7, add "Plong" to the result.
|
||||
- **is not** divisible by 3, 5, or 7, the result should be the number as a string.
|
||||
|
||||
## Examples
|
||||
|
||||
- 28 is divisible by 7, but not 3 or 5, so the result would be `"Plong"`.
|
||||
- 30 is divisible by 3 and 5, but not 7, so the result would be `"PlingPlang"`.
|
||||
- 34 is not divisible by 3, 5, or 7, so the result would be `"34"`.
|
||||
|
||||
~~~~exercism/note
|
||||
A common way to test if one number is evenly divisible by another is to compare the [remainder][remainder] or [modulus][modulo] to zero.
|
||||
Most languages provide operators or functions for one (or both) of these.
|
||||
|
||||
[remainder]: https://exercism.org/docs/programming/operators/remainder
|
||||
[modulo]: https://en.wikipedia.org/wiki/Modulo_operation
|
||||
~~~~
|
||||
|
||||
## How this Exercise is Structured in Python
|
||||
|
||||
This exercise is best solved with Python's `%` ([modulo][modulo]) operator, which returns the remainder of positive integer division.
|
||||
It has a method equivalent, `operator.mod()` in the [operator module][operator-mod].
|
||||
|
||||
|
||||
Python also offers additional 'remainder' methods in the [math module][math-module].
|
||||
[`math.fmod()`][fmod] behaves like `%`, but operates on floats.
|
||||
[`math.remainder()`][remainder] implements a "step closest to zero" algorithm for the remainder of division.
|
||||
While we encourage you to get familiar with these methods, neither of these will exactly match the result of `%`, and are not recommended for use with this exercise.
|
||||
|
||||
The built-in function [`divmod()`][divmod] will also give a remainder than matches `%` if used with two positive integers, but returns a `tuple` that needs to be unpacked.
|
||||
|
||||
[divmod]: https://docs.python.org/3/library/functions.html#divmod
|
||||
[fmod]: https://docs.python.org/3/library/math.html#math.fmod
|
||||
[math-module]: https://docs.python.org/3/library/math.html
|
||||
[modulo]: https://www.programiz.com/python-programming/operators#arithmetic
|
||||
[operator-mod]: https://docs.python.org/3/library/operator.html#operator.mod
|
||||
[remainder]: https://docs.python.org/3/library/math.html#math.remainder
|
||||
|
||||
## Source
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @behrtam
|
||||
- @BethanyG
|
||||
- @bsoyka
|
||||
- @cmccandless
|
||||
- @Dog
|
||||
- @ikhadykin
|
||||
- @kytrinyx
|
||||
- @lowks
|
||||
- @N-Parsons
|
||||
- @pheanex
|
||||
- @sjakobi
|
||||
- @tqa236
|
||||
- @yawpitch
|
||||
|
||||
### Based on
|
||||
|
||||
A variation on FizzBuzz, a famous technical interview question that is intended to weed out potential candidates. That question is itself derived from Fizz Buzz, a popular children's game for teaching division. - https://en.wikipedia.org/wiki/Fizz_buzz
|
2
python/raindrops/raindrops.py
Normal file
2
python/raindrops/raindrops.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
def convert(number):
|
||||
pass
|
67
python/raindrops/raindrops_test.py
Normal file
67
python/raindrops/raindrops_test.py
Normal file
|
@ -0,0 +1,67 @@
|
|||
# These tests are auto-generated with test data from:
|
||||
# https://github.com/exercism/problem-specifications/tree/main/exercises/raindrops/canonical-data.json
|
||||
# File last updated on 2023-07-19
|
||||
|
||||
import unittest
|
||||
|
||||
from raindrops import (
|
||||
convert,
|
||||
)
|
||||
|
||||
|
||||
class RaindropsTest(unittest.TestCase):
|
||||
def test_the_sound_for_1_is_1(self):
|
||||
self.assertEqual(convert(1), "1")
|
||||
|
||||
def test_the_sound_for_3_is_pling(self):
|
||||
self.assertEqual(convert(3), "Pling")
|
||||
|
||||
def test_the_sound_for_5_is_plang(self):
|
||||
self.assertEqual(convert(5), "Plang")
|
||||
|
||||
def test_the_sound_for_7_is_plong(self):
|
||||
self.assertEqual(convert(7), "Plong")
|
||||
|
||||
def test_the_sound_for_6_is_pling_as_it_has_a_factor_3(self):
|
||||
self.assertEqual(convert(6), "Pling")
|
||||
|
||||
def test_2_to_the_power_3_does_not_make_a_raindrop_sound_as_3_is_the_exponent_not_the_base(
|
||||
self,
|
||||
):
|
||||
self.assertEqual(convert(8), "8")
|
||||
|
||||
def test_the_sound_for_9_is_pling_as_it_has_a_factor_3(self):
|
||||
self.assertEqual(convert(9), "Pling")
|
||||
|
||||
def test_the_sound_for_10_is_plang_as_it_has_a_factor_5(self):
|
||||
self.assertEqual(convert(10), "Plang")
|
||||
|
||||
def test_the_sound_for_14_is_plong_as_it_has_a_factor_of_7(self):
|
||||
self.assertEqual(convert(14), "Plong")
|
||||
|
||||
def test_the_sound_for_15_is_pling_plang_as_it_has_factors_3_and_5(self):
|
||||
self.assertEqual(convert(15), "PlingPlang")
|
||||
|
||||
def test_the_sound_for_21_is_pling_plong_as_it_has_factors_3_and_7(self):
|
||||
self.assertEqual(convert(21), "PlingPlong")
|
||||
|
||||
def test_the_sound_for_25_is_plang_as_it_has_a_factor_5(self):
|
||||
self.assertEqual(convert(25), "Plang")
|
||||
|
||||
def test_the_sound_for_27_is_pling_as_it_has_a_factor_3(self):
|
||||
self.assertEqual(convert(27), "Pling")
|
||||
|
||||
def test_the_sound_for_35_is_plang_plong_as_it_has_factors_5_and_7(self):
|
||||
self.assertEqual(convert(35), "PlangPlong")
|
||||
|
||||
def test_the_sound_for_49_is_plong_as_it_has_a_factor_7(self):
|
||||
self.assertEqual(convert(49), "Plong")
|
||||
|
||||
def test_the_sound_for_52_is_52(self):
|
||||
self.assertEqual(convert(52), "52")
|
||||
|
||||
def test_the_sound_for_105_is_pling_plang_plong_as_it_has_factors_3_5_and_7(self):
|
||||
self.assertEqual(convert(105), "PlingPlangPlong")
|
||||
|
||||
def test_the_sound_for_3125_is_plang_as_it_has_a_factor_5(self):
|
||||
self.assertEqual(convert(3125), "Plang")
|
Loading…
Reference in a new issue