Skip to content
This repository has been archived by the owner on Aug 31, 2021. It is now read-only.

[Python] Add tuples concept exercise #1824

Merged
merged 27 commits into from
Jul 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
14e16ef
New tuples concept exercise design file.
BethanyG Jul 3, 2020
b6561f0
New tuples concept exercise example implementation file.
BethanyG Jul 3, 2020
4fe62d6
New tuples concept exercise config file.
BethanyG Jul 3, 2020
a96dd0b
New tuples concept exercist after file w TODO.
BethanyG Jul 3, 2020
54b711b
New tuples concept exercist hints file.
BethanyG Jul 3, 2020
ba79077
New tuples concept exercise introduction file.
BethanyG Jul 3, 2020
2dd31c1
New tuples concept exercise instructions file.
BethanyG Jul 3, 2020
3ce1f85
New tuples concept exercise boilerplate file.
BethanyG Jul 3, 2020
92265e4
New tuples concept exercise cleaned boilerplate file.
BethanyG Jul 3, 2020
2323534
New tuples concept exercise tests.
BethanyG Jul 3, 2020
5a432df
Ran prettier to clean up file markdown formatting. Edited language a…
BethanyG Jul 4, 2020
5377eba
Ran prettier to correct markdown formatting and dleted star operator …
BethanyG Jul 4, 2020
c1acea5
Removed tuple multiplication with star operator.
BethanyG Jul 4, 2020
b3bee05
Edited to remove multiply function.
BethanyG Jul 4, 2020
b9815cc
Edited to remove multiply function test case.
BethanyG Jul 4, 2020
debacea
Fixed quoting on Scrimshaw Whale's tooth to match quoting style.
BethanyG Jul 4, 2020
172ba40
Ran prettier for config.json
BethanyG Jul 4, 2020
d7445f0
Edits and adjustments per PR feedback and style guides. Also correct…
BethanyG Jul 9, 2020
72eb276
Edited for clarity and brevity per PR feedback. Removed excess conce…
BethanyG Jul 9, 2020
734793b
Re-worked final task to be a returned report string rather than print…
BethanyG Jul 9, 2020
14a46de
Cleaned up per PR feedback. Removed excess lines.
BethanyG Jul 9, 2020
55f231f
Changed final test to support altered task for report string. Remove…
BethanyG Jul 9, 2020
a2a864d
Corrected terminal output code exxample for task 4.
BethanyG Jul 9, 2020
f70a2ab
Removed print as a prerequisite of the exercise. Added absolute link…
BethanyG Jul 9, 2020
2e00a38
Removed excess PyTest config from test class.
BethanyG Jul 9, 2020
af5736f
Added tuples concept exercise information and uuid.
BethanyG Jul 9, 2020
8416783
Ran prettier on config file, since I forgot to.
BethanyG Jul 10, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions languages/python/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,20 @@
"uuid": "5a9b42fb-ddf4-424b-995d-f9952ea63c37",
"concepts": ["strings"],
"prerequisites": ["functions"]
},
{
"slug": "tuples",
"uuid": "7ecd42c1-2ed5-487a-bc89-71c9cbad9b05",
"concepts": ["tuples"],
"prerequisites": [
"boleans",
"for-loops",
"functions",
"if-keyword",
"in-keyword",
"integers",
"return-keyword"
]
}
],
"practice": []
Expand Down
165 changes: 165 additions & 0 deletions languages/python/exercises/concept/tuples/.docs/after.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
In Python, a [tuple](https://github.com/exercism/v3/blob/master/languages/python/reference/concepts/builtin_types/tuple.md) is an immutable collection of items in _sequence_. Like most collections (_see the built-ins [`list`](https://github.com/exercism/v3/blob/master/languages/python/reference/concepts/builtin_types/list.md), [`dict`](https://github.com/exercism/v3/blob/master/languages/python/reference/concepts/builtin_types/dict.md) and [`set`](https://github.com/exercism/v3/blob/master/languages/python/reference/concepts/builtin_types/set.md)_), tuples can hold any (or multiple) data type(s) -- including other tuples. Like any [sequence](https://docs.python.org/3/library/stdtypes.html#sequence-types-list-tuple-range), items are referenced by 0-based index number, and can be copied in whole or in part via _slice notation_. Tuples support all [common sequence operations](https://docs.python.org/3/library/stdtypes.html#common-sequence-operations).

Tuples take up very little memory space compared to other collection types and have constant (_O(1)_) access time. However, they cannot be resized, sorted, or altered once created, so are less flexible when frequent changes or updates to data are needed.
BethanyG marked this conversation as resolved.
Show resolved Hide resolved

## Tuple Construction

Tuples can be formed in multiple ways, using either the `tuple` class constructor or the `tuple` literal declaration.

### Using the `tuple()` constructor empty or with an _iterable_:

```python
>>> no_elements = tuple()
()

#the string elements (characters) are iterated through and added to the tuple
>>> multiple_elements_string = tuple("Timbuktu")
('T', 'i', 'm', 'b', 'u', 'k', 't', 'u')

>>> multiple_elements_list = tuple(["Parrot", "Bird", 334782])
("Parrot", "Bird", 334782)

>>> multiple_elements_set = tuple({2, 3, 5, 7, 11})
(2,3,5,7,11)


"""
The iteration default for dictionaries is over the keys.
To include both keys and values in a tuple made from a dictionary, use dict.items(),
which returns a list of (key, value) tuples.
"""
source_data = {"fish": "gold", "monkey": "brown"}
>>> multiple_elements_dict_1 = tuple(source_data)
('fish', 'monkey')

>>> multiple_elements_dict_2 = tuple(source_data.items())
(('fish', 'gold'), ('monkey', 'brown'))


"""
because the tuple constructor only takes _iterables_ (or nothing), it is much easier to create
a one-tuple via the literal method.
"""
>>> one_element = tuple([16])
(16,)

```

#### Declaring a tuple as a _literal_ :

```python
>>> no_elements = ()
()

>>> one_element = ("Guava",)
("Guava",)

>>> elements_separated_with_commas = "Parrot", "Bird", 334782
("Parrot", "Bird", 334782)

>>> elements_with_commas_and_parentheses = ("Triangle", 60, 60, 60)
("Triangle", 60, 60, 60)

>>> nested_data_structures = ({"fish": "gold", "monkey": "brown", "parrot" : "grey"}, ("fish", "mammal", "bird"))
({"fish": "gold", "monkey": "brown", "parrot" : "grey"}, ("fish", "mammal", "bird"))

#using the plus + operator unpacks each tuple and creates a new tuple.
>>> new_via_concatenate = ("George", 5) + ("cat", "Tabby")
("George", 5, "cat", "Tabby")

#likewise, using the multiplication operator * is the equvilent of using + n times
>>> first_group = ("cat", "dog", "elephant")

>>> multiplied_group = first_group * 3
('cat', 'dog', 'elephant', 'cat', 'dog', 'elephant', 'cat', 'dog', 'elephant')

```

Note that generally parentheses are not _required_ to create a `tuple` literal - only commas. Parentheses are required in cases of ambiguity, such as an empty or one-item tuple or where a function takes a tuple as an argument.

## Tuples as related information

Tuples are often used as _records_ containing heterogeneous data that is _organizationally_ or _conceptually_ related and treated as a single unit of information.

```python

>>> student_info = ("Alyssa", "grade 3", "female", 8 )

```

Tuples are also used when homogeneous immutable sequences of data are needed for [`hashability`](https://docs.python.org/3/glossary.html#hashable), storage in a set, or creation of keys in a dictionary.

Note that while tuples are in most cases _immutable_, because they can contain _any_ data structure or object they can become mutable if any of their elements is a _mutable type_. Using a mutable data type within a tuple will make the enclosing tuple un-hashable.

```python

>>> cmyk_color_map = {
(.69, .3, .48, .1) : ("Teal 700", (59, 178, 146), 0x3BB292),
(0, .5, 1, 0) : ("Pantone 151", (247, 127, 1), 0xF77F01),
(.37, .89, 0, .44) : ("Pantone 267", (89, 16, 142), 0x59108E),
(0, 1, .46, .45) : ("Pantone 228", (140, 0, 76), 0x8C004C)
}

>>>> unique_rgb_colors = {
(59, 178, 146),
(247, 127, 1),
(89, 16, 142),
(140, 0, 76),
(76, 0, 140)
}

>>> teal_700 = hash((59, 178, 146))

>>> teal_700 = hash(("Pantone 228", [(140, 0, 76), 0x8C004C]))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

```

## Accessing data inside a tuple

Items inside tuples (_like the sequence types `string` and `list`_), can be accessed via 0-based index and _bracket notation_. Indexes can be from **`left`** --> **`right`** (_starting at zero_) or **`right`** --> **`left`** (_starting at -1_).

Items inside tuples can also be _iterated over_ in a loop using `for item in` syntax.

```python

>>> student_info = ("Alyssa", "grade 3", "female", 8 )

#name is at index 0 or index -4
>>> student_name = student_info[0]
Alyssa

>>> student_name = student_info[-4]
Alyssa

#grade is at index 1 or index -3
>>> student_grade = student_info[1]
'grade 3'

>>> student_grade = student_info[-3]
'grade 3'

#age is at index 3 or index -1
>>> student_age_1 = student_info[3]
8

>>> student_age_2 = student_info[-1]
8


>>> for item in student_info:
>>> print(item)

....
Alyssa
grade 3
female
8

```

## Extended tuples and related data types

Tuples are often used as _records_, but the data inside them can only be accessed via _position_/_index_. The [`namedtuple()`](https://docs.python.org/3/library/collections.html#collections.namedtuple) class in the [`collections`](https://docs.python.org/3/library/collections.html#module-collections) module extends basic tuple functionality to allow access of elements by _name_. Additionally, users can adapt a [`dataclass`](https://docs.python.org/3/library/dataclasses.html) to provide similar named attribute functionality, with a some [pros and cons](https://stackoverflow.com/questions/51671699/data-classes-vs-typing-namedtuple-primary-use-cases).
34 changes: 34 additions & 0 deletions languages/python/exercises/concept/tuples/.docs/hints.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
## General

- [Tuples](https://docs.python.org/3/tutorial/datastructures.html#tuples-and-sequences) are immutable.
[Sequence Types](https://docs.python.org/3/library/stdtypes.html#typesseq) that can contain any data type.
ErikSchierboom marked this conversation as resolved.
Show resolved Hide resolved
- Tuples are [iterable](https://docs.python.org/3/glossary.html#term-iterable).
- Elements within tuples can be accessed via [bracket notation](https://stackoverflow.com/questions/30250282/whats-the-difference-between-the-square-bracket-and-dot-notations-in-python), using a zero-based index.
- Other [Common Sequence Operations](https://docs.python.org/3/library/stdtypes.html#common-sequence-operations) can also be used when working with tuples.

## 1. Extract coordinates

- Remember: tuples allow access via _index_, using _brackets_. Indexes start from the left at zero.

## 2. Format coordinates

- Check [`class tuple`](https://docs.python.org/3/library/stdtypes.html#tuple) for more details on tuples.
- Check [`class str`](https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str) for more details on strings.

## 3. Match coordinates

- What methods could be used here for for [testing membership](https://docs.python.org/3/reference/expressions.html#membership-test-operations)?.
- Check [`class tuple`](https://docs.python.org/3/library/stdtypes.html#tuple) for more details on tuples.
- Could you re-use your `convert_coordinate()` function?

## 4. Combine matched records

- Remember that tuples support all [common sequence operations](https://docs.python.org/3/library/stdtypes.html#common-sequence-operations).
- Could you re-use your `compare_records()` function here?

## 5. "Clean up" & format a report of all records

- Remember: tuples are _immutable_, but the contents can be accessed via _index_ using _bracket notation_.
- Tuples don't have to use parentheses unless there is _ambiguity_.
ErikSchierboom marked this conversation as resolved.
Show resolved Hide resolved
- Python has multiple methods of string formatting. [`str.format()`](https://docs.python.org/3/library/stdtypes.html#str.format) and [`f-strings`](https://docs.python.org/3/tutorial/inputoutput.html#formatted-string-literals) are two very common ones.
- There are multiple textual formatting options available via Pythons [`format specification mini-language`](https://docs.python.org/3/library/string.html#format-specification-mini-language).
107 changes: 107 additions & 0 deletions languages/python/exercises/concept/tuples/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
Aazra and Rui are teammates competing in a pirate-themed treasure hunt. One has a list of treasures with map coordinates, the other a list of location names with map coordinates. They've also been given blank maps with a starting place marked YOU ARE HERE.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really nice story!


<br>
<table>
<tr><th>Azara's List</th><th></th><th>Rui's List</th></tr>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The table really helps make things very clear. Good job! 👍

<tr><td>

| Treasure | Coordinates |
| --------------------------- | ----------- |
| Amethyst Octopus | 1F |
| Angry Monkey Figurine | 5B |
| Antique Glass Fishnet Float | 3D |
| Brass Spyglass | 4B |
| Carved Wooden Elephant | 8C |
| Crystal Crab | 6A |
| Glass Starfish | 6D |
| Model Ship in Large Bottle | 8A |
| Pirate Flag | 7F |
| Robot Parrot | 1C |
| Scrimshaw Whale's Tooth | 2A |
| Silver Seahorse | 4E |
| Vintage Pirate Hat | 7E |

</td><td></td><td>

| Location Name | Coordinates | Quandrant |
| ------------------------------------- | ----------- | --------- |
| Seaside Cottages | ("1", "C") | Blue |
| Aqua Lagoon (Island of Mystery) | ("1", "F") | Yellow |
| Deserted Docks | ("2", "A") | Blue |
| Spiky Rocks | ("3", "D") | Yellow |
| Abandoned Lighthouse | ("4", "B") | Blue |
| Hidden Spring (Island of Mystery) | ("4", "E") | Yellow |
| Stormy Breakwater | ("5", "B") | Purple |
| Old Schooner | ("6", "A") | Purple |
| Tangled Seaweed Patch | ("6", "D") | Orange |
| Quiet Inlet (Island of Mystery) | ("7", "E") | Orange |
| Windswept Hilltop (Island of Mystery) | ("7", "F") | Orange |
| Harbor Managers Office | ("8", "A") | Purple |
| Foggy Seacave | ("8", "C") | Purple |

</td></tr>
</table>

<br>

But things are a bit disorganized: Azara's coordinates appear to be formatted and sorted differently from Rui's, and they have to keep looking from one list to the other to figure out which treasures go with which locations. Being budding pythonistas, they've come to you for help in writing a small program (a set of functions, really) to better organize their hunt information.

## 1. Extract coordinates

Implement the `get_cooordinate()` function that takes a `(treasure, coordinate)` pair from Azaras list and returns only the extracted map coordinate.

```python
>>> get_coordinate(("Scrimshaw Whale's Tooth", "2A"))
"2A"
```

## 2. Format coordinates

Implement the `convert_coordinate()` function that takes a coordinate in the format "2A" and returns a tuple in the format `("2", "A")`.

BethanyG marked this conversation as resolved.
Show resolved Hide resolved

```python
>>> convert_coordinate("2A")
("2", "A")
```

## 3. Match coordinates

Implement the `compare_records()` function that takes a `(treasure, coordinate)` pair and a `(location, coordinate, quadrant)` record and compares coordinates from each. Return **`True`** if the coordinates "match", and return **`False`** if they do not. Re-format coordinates as needed for accurate comparison.

```python
>>> compare_records(('Brass Spyglass', '4B'),('Seaside Cottages', ("1", "C"), 'blue'))
False

>>> compare_records(('Model Ship in Large Bottle', '8A'), ('Harbor Managers Office', ("8", "A"), 'purple'))
True
```

## 4. Combine matched records

Implement the `create_record()` function that takes a `(treasure, coordinate)` pair from Azaras list and a `(location, coordinate, quadrant)` record from Ruis list and returns `(treasure, coordinate, location, coordinate, quadrant)` **if the coordinates match**. If the coordinats _do not_ match, return the string "not a match.". Re-format the coordinate as needed for accurate comparison.

```python
>>> create_record(('Brass Spyglass', '4B'),('Abandoned Lighthouse', ("4", "B"), 'Blue'))
('Brass Spyglass', '4B', 'Abandoned Lighthouse', ("4", "B"), 'Blue')

BethanyG marked this conversation as resolved.
Show resolved Hide resolved
>>> create_record(('Brass Spyglass', '4B'),(("1", "C"), 'Seaside Cottages', 'blue'))
"not a match."
```

## 5. "Clean up" & make a report of all records
BethanyG marked this conversation as resolved.
Show resolved Hide resolved

Clean up the combined records from Azara and Rui so that there's only one set of coordinates per record. Make a report so they can see one list of everything they need to put on their maps.
Implement the `clean_up()` function that takes a tuple of tuples (_everything from both lists_), looping through the _outer_ tuple, dropping the unwanted coordinates from each _inner_ tuple and adding each to a 'report'. Format and return the 'report' so that there is one cleaned record on each line.

```python
>>> clean_up((('Brass Spyglass', '4B', 'Abandoned Lighthouse', '("4", "B")', 'Blue'), ('Vintage Pirate Hat', '7E', 'Quiet Inlet (Island of Mystery)', '("7", "E")', 'Orange'), ('Crystal Crab', '6A', 'Old Schooner', '("6", "A")', 'Purple')))

BethanyG marked this conversation as resolved.
Show resolved Hide resolved
"""
('Brass Spyglass', 'Abandoned Lighthouse', '("4", "B")', 'Blue')\n
('Vintage Pirate Hat', 'Quiet Inlet (Island of Mystery)', '("7", "E")', 'Orange')\n
('Crystal Crab', 'Old Schooner', '("6", "A")','Purple')\n
"""
```
55 changes: 55 additions & 0 deletions languages/python/exercises/concept/tuples/.docs/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
In Python, a [tuple](https://docs.python.org/3/library/stdtypes.html#tuple) is an immutable collection of items in _sequence_. Like most collections, tuples can hold any (or multiple) data type(s) -- including other tuples. Like any sequence, items are referenced by 0-based index number. Tuples support all [common sequence operations](https://docs.python.org/3/library/stdtypes.html#common-sequence-operations).

## Tuple Construction

Tuples can be formed in multiple ways, using either the `tuple` class constructor or the `tuple` literal declaration.

#### Using the `tuple()` constructor:

```python
#elements are iterated through and added to the tuple in order
>>> multiple_elements_string = tuple("Timbuktu")
('T', 'i', 'm', 'b', 'u', 'k', 't', 'u')

>>> multiple_elements = tuple(("Parrot", "Bird", 334782))
("Parrot", "Bird", 334782)
```

#### Declaring a tuple _literal_ :

```python
>>> elements_separated_with_commas = "Parrot", "Bird", 334782
("Parrot", "Bird", 334782)

>>> elements_with_commas_and_parentheses = ("Triangle", (60, 60, 60))
("Triangle", (60, 60, 60))
```

## Concatenation

Tuples can be _concatenated_ via the plus `+` operator, which returns a new tuple.

```python
>>> new_via_concatenate = ("George", 5) + ("cat", "Tabby")
("George", 5, "cat", "Tabby")
```

## Accessing data

Items inside tuples can be accessed via 0-based index and _bracket notation_.

```python
student_info = ("Alyssa", "grade 3", "female", 8 )

#gender is at index 2
>>> student_gender = student_info[2]
female
```

## Iterating through a tuple

Items inside tuples can be _iterated over_ in a loop using `for item in` syntax.

## Checking membership

The `in` operator can be used to check membership in a tuple.
8 changes: 8 additions & 0 deletions languages/python/exercises/concept/tuples/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"authors": [
{
"github_username": "bethanyg",
"exercism_username": "BethanyG"
}
]
}
Loading