Skip to content

Commit cfb620d

Browse files
J08KIsaacGmukeshgurpudeynfleBethanyG
authored
[New Concept Exercise] : Generators (Plane Tickets) (#2729)
* Update TESTS.md * Update TESTS.md * Update TESTS.md * Start of TOOLS.md * Finished writing VS Code part * Added Pycharm docs & relative img links * Update TOOLS.md * Added Spyder Docs * Added VENV docs * Added conda environments docs * Wrote Windows tutorial for adding to path * Improved shared test file and added disclaimer to TOOLS.md * Added docs for JupyterLab and Sublime Text * Added Virtualenvwrapper piece. * Cleaned up. * Updated image paths * Fixed Images x2 * Images have absolute path * Update docs/TESTS.md Co-authored-by: Isaac Good <[email protected]> * Update docs/TESTS.md Co-authored-by: Isaac Good <[email protected]> * Update docs/TESTS.md Co-authored-by: Isaac Good <[email protected]> * Update docs/TESTS.md Co-authored-by: Isaac Good <[email protected]> * Update docs/TESTS.md Co-authored-by: Isaac Good <[email protected]> * Update docs/TESTS.md Co-authored-by: Isaac Good <[email protected]> * Update docs/TOOLS.md Co-authored-by: Isaac Good <[email protected]> * Update docs/TOOLS.md Co-authored-by: Isaac Good <[email protected]> * Update docs/TESTS.md Co-authored-by: Isaac Good <[email protected]> * Update docs/TOOLS.md Co-authored-by: Isaac Good <[email protected]> * Update docs/TOOLS.md Co-authored-by: Isaac Good <[email protected]> * Update exercises/shared/.docs/tests.md Co-authored-by: Isaac Good <[email protected]> * Update exercises/shared/.docs/tests.md Co-authored-by: Isaac Good <[email protected]> * Fixed capitalization * Update docs/TOOLS.md Co-authored-by: Isaac Good <[email protected]> * Fixed language Co-authored-by: Isaac Good <[email protected]> * Update docs/TOOLS.md Co-authored-by: Isaac Good <[email protected]> * Update docs/TOOLS.md * Update docs/TOOLS.md * Update docs/TESTS.md * Update docs/TOOLS.md * Update docs/TOOLS.md * Update docs/TESTS.md Co-authored-by: Mukesh Gurpude <[email protected]> * Update docs/TESTS.md Co-authored-by: Mukesh Gurpude <[email protected]> * Update docs/TESTS.md Co-authored-by: Mukesh Gurpude <[email protected]> * Update docs/TOOLS.md Co-authored-by: Mukesh Gurpude <[email protected]> * Layed out ground work * Write introduction * Update docs/TESTS.md Co-authored-by: ynfle <[email protected]> * Added pytest.ini docs * Update docs/TESTS.md Co-authored-by: BethanyG <[email protected]> * Update docs/TESTS.md Co-authored-by: BethanyG <[email protected]> * Update docs/TESTS.md Co-authored-by: BethanyG <[email protected]> * Update docs/TOOLS.md Co-authored-by: BethanyG <[email protected]> * Apply suggestions from code review Co-authored-by: BethanyG <[email protected]> * Update docs/TOOLS.md Co-authored-by: BethanyG <[email protected]> * Update docs/TOOLS.md Co-authored-by: BethanyG <[email protected]> * Update docs/TOOLS.md Co-authored-by: BethanyG <[email protected]> * Update docs/TOOLS.md Co-authored-by: BethanyG <[email protected]> * Start on instructions * Update headers and links * Removed template * Task 1 * sync with PCs * Sync * Task 1 Exemplar * Exemplar now also skips row 13 * Fixed (skip row 13) * Finished Task 1 & 2 * Remove Typing * Cleanup * Add some data in ./concepts * Add exercise to config.json * fixing * Update concepts/generators/.meta/config.json Co-authored-by: BethanyG <[email protected]> * Update concepts/generators/introduction.md * Update exercises/concept/plane-tickets/.docs/instructions.md Co-authored-by: BethanyG <[email protected]> * Update exercises/concept/plane-tickets/.docs/introduction.md Co-authored-by: BethanyG <[email protected]> * Update concepts/generators/introduction.md Co-authored-by: Isaac Good <[email protected]> * Fixed all pylint warnings in Exemplar * Update exercises/concept/plane-tickets/.meta/exemplar.py Co-authored-by: Isaac Good <[email protected]> * Committed suggestions and Added new task 3 * Apply suggestions from code review Co-authored-by: Victor Goff <[email protected]> * Apply suggestions from code review WHOOOOP Co-authored-by: BethanyG <[email protected]> Co-authored-by: Victor Goff <[email protected]> * Add tests for task 3 * Update config.json Co-authored-by: BethanyG <[email protected]> * Better test case 1; add test for type task 3 * Don't you love pytests? * 🤖 Sync org-wide files to upstream repo More info: exercism/org-wide-files@cc4bf90 * Layed out ground work * Write introduction * Start on instructions * Removed template * Task 1 * sync with PCs * Sync * Task 1 Exemplar * Exemplar now also skips row 13 * Fixed (skip row 13) * Finished Task 1 & 2 * Remove Typing * Update TESTS.md * Update TESTS.md * Update TESTS.md * Start of TOOLS.md * Finished writing VS Code part * Added Pycharm docs & relative img links * Update TOOLS.md * Added VENV docs * Wrote Windows tutorial for adding to path * Improved shared test file and added disclaimer to TOOLS.md * Update docs/TOOLS.md Co-authored-by: BethanyG <[email protected]> * Cleanup * Add some data in ./concepts * Add exercise to config.json * fixing * Fixed all pylint warnings in Exemplar * Update concepts/generators/.meta/config.json Co-authored-by: BethanyG <[email protected]> * Update concepts/generators/introduction.md * Update exercises/concept/plane-tickets/.docs/instructions.md Co-authored-by: BethanyG <[email protected]> * Update exercises/concept/plane-tickets/.docs/introduction.md Co-authored-by: BethanyG <[email protected]> * Update concepts/generators/introduction.md Co-authored-by: Isaac Good <[email protected]> * Update exercises/concept/plane-tickets/.meta/exemplar.py Co-authored-by: Isaac Good <[email protected]> * Committed suggestions and Added new task 3 * Apply suggestions from code review Co-authored-by: Victor Goff <[email protected]> * Apply suggestions from code review WHOOOOP Co-authored-by: BethanyG <[email protected]> Co-authored-by: Victor Goff <[email protected]> * Add tests for task 3 * Better test case 1; add test for type task 3 * Don't you love pytests? * Update config.json Co-authored-by: Isaac Good <[email protected]> Co-authored-by: Mukesh Gurpude <[email protected]> Co-authored-by: ynfle <[email protected]> Co-authored-by: BethanyG <[email protected]> Co-authored-by: Victor Goff <[email protected]> Co-authored-by: Exercism Bot <[email protected]>
1 parent b21b0aa commit cfb620d

File tree

14 files changed

+531
-19
lines changed

14 files changed

+531
-19
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"blurb": "TODO: add blurb for this concept",
3-
"authors": ["bethanyg", "cmccandless"],
2+
"blurb": "Learn about generators by assigning seats to passengers.",
3+
"authors": ["J08K"],
44
"contributors": []
55
}

concepts/generators/about.md

Lines changed: 131 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,132 @@
1-
#TODO: Add about for this concept.
1+
# About
22

3+
## Constructing a generator
4+
5+
Generators are constructed much like other looping or recursive functions, but require a [`yield` expression](#the-yield-expression), which we will explore in depth a bit later.
6+
7+
8+
An example is a function that returns the _squares_ from a given list of numbers.
9+
As currently written, all input must be processed before any values can be returned:
10+
11+
12+
```python
13+
>>> def squares(list_of_numbers):
14+
>>> squares = []
15+
>>> for number in list_of_numbers:
16+
>>> squares.append(number ** 2)
17+
>>> return squares
18+
```
19+
20+
You can convert that function into a generator like this:
21+
22+
```python
23+
def squares(list_of_numbers):
24+
for number in list_of_number:
25+
yield number ** 2
26+
```
27+
28+
The rationale behind this is that you use a generator when you do not need all the values _at once_.
29+
30+
This saves memory and processing power, since only the value you are _currently working on_ is calculated.
31+
32+
33+
## Using a generator
34+
35+
Generators may be used in place of most `iterables` in Python. This includes _functions_ or _objects_ that require an `iterable`/`iterator` as an argument.
36+
37+
To use the `squares()` generator:
38+
39+
```python
40+
>>> squared_numbers = squares([1, 2, 3, 4])
41+
42+
>>> for square in squared_numbers:
43+
>>> print(square)
44+
1
45+
4
46+
9
47+
16
48+
```
49+
50+
Values within a generator can also be produced/accessed via the `next()` function.
51+
`next()` calls the `__next__()` method of a generator object, "advancing" or evaluating the generator code up to its `yield` expression, which then "yields" or returns the value.
52+
53+
```python
54+
square_generator = squares([1, 2])
55+
56+
>>> next(square_generator)
57+
1
58+
>>> next(square_generator)
59+
4
60+
```
61+
62+
When a `generator` is fully consumed and has no more values to return, it throws a `StopIteration` error.
63+
64+
```python
65+
>>> next(square_generator)
66+
Traceback (most recent call last):
67+
File "<stdin>", line 1, in <module>
68+
StopIteration
69+
```
70+
71+
### Difference between iterables and generators
72+
73+
Generators are a special sub-set of _iterators_.
74+
`Iterators` are the mechanism/protocol that enables looping over _iterables_.
75+
Generators and and the iterators returned by common Python (`iterables`)[https://wiki.python.org/moin/Iterator] act very similarly, but there are some important differences to note:
76+
77+
78+
- Generators are _one-way_; there is no "backing up" to a previous value.
79+
80+
- Iterating over generators consume the returned values; no resetting.
81+
- Generators (_being lazily evaluated_) are not sortable and can not be reversed.
82+
83+
- Generators do _not_ have `indexes`, so you can't reference a previous or future value using addition or subtraction.
84+
85+
- Generators cannot be used with the `len()` function.
86+
87+
- Generators can be _finite_ or _infinite_, be careful when collecting all values from an _infinite_ generator.
88+
89+
## The yield expression
90+
91+
The [yield expression](https://docs.python.org/3.8/reference/expressions.html#yield-expressions) is very similar to the `return` expression.
92+
93+
_Unlike_ the `return` expression, `yield` gives up values to the caller at a _specific point_, suspending evaluation/return of any additional values until they are requested.
94+
95+
When `yield` is evaluated, it pauses the execution of the enclosing function and returns any values of the function _at that point in time_.
96+
97+
The function then _stays in scope_, and when `__next__()` is called, execution resumes until `yield` is encountered again.
98+
99+
Note: _Using `yield` expressions is prohibited outside of functions._
100+
101+
```python
102+
>>> def infinite_sequence():
103+
>>> current_number = 0
104+
>>> while True:
105+
>>> yield current_number
106+
>>> current_number += 1
107+
108+
>>> lets_try = infinite_sequence()
109+
>>> lets_try.__next__()
110+
0
111+
>>> lets_try.__next__()
112+
1
113+
```
114+
115+
## Why generators?
116+
117+
Generators are useful in a lot of applications.
118+
119+
When working with a large collection, you might not want to put all of its values into `memory`.
120+
A generator can be used to work on larger data piece-by-piece, saving memory and improving performance.
121+
122+
Generators are also very helpful when a process or calculation is _complex_, _expensive_, or _infinite_:
123+
124+
```python
125+
>>> def infinite_sequence():
126+
>>> current_number = 0
127+
>>> while True:
128+
>>> yield current_number
129+
>>> current_number += 1
130+
```
131+
132+
Now whenever `__next__()` is called on the `infinite_sequence` object, it will return the _previous number_ + 1.
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1-
#TODO: Add introduction for this concept.
1+
# Introduction
22

3+
A generator in Python is a _callable function_ that returns a [lazy iterator](https://en.wikipedia.org/wiki/Lazy_evaluation).
4+
5+
_Lazy iterators_ are similar to `lists`, and other `iterators`, but with one key difference: They do not store their `values` in memory, but _generate_ their values when needed.

concepts/generators/links.json

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,10 @@
11
[
22
{
3-
"url": "http://example.com/",
4-
"description": "TODO: add new link (above) and write a short description here of the resource."
3+
"url": "https://docs.python.org/3.8/reference/expressions.html#yield-expressions",
4+
"description": "Official Python 3.8 docs for the yield expression."
55
},
66
{
7-
"url": "http://example.com/",
8-
"description": "TODO: add new link (above) and write a short description here of the resource."
9-
},
10-
{
11-
"url": "http://example.com/",
12-
"description": "TODO: add new link (above) and write a short description here of the resource."
13-
},
14-
{
15-
"url": "http://example.com/",
16-
"description": "TODO: add new link (above) and write a short description here of the resource."
7+
"url": "https://en.wikipedia.org/wiki/Lazy_evaluation",
8+
"description": "Wikipedia page about lazy evaluation"
179
}
1810
]

config.json

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,12 +176,37 @@
176176
"prerequisites": ["basics", "dicts", "lists", "loops", "tuples"],
177177
"status": "beta"
178178
},
179+
{
180+
"slug": "plane-tickets",
181+
"name": "Plane Tickets",
182+
"uuid": "3ba3fc89-3e1b-48a5-aff0-5aeaba8c8810",
183+
"concepts": [
184+
"generators"
185+
],
186+
"prerequisites": [
187+
"conditionals",
188+
"dicts",
189+
"lists",
190+
"loops"
191+
],
192+
"status": "wip"
193+
},
179194
{
180195
"slug": "ellens-alien-game",
181196
"name": "Ellen's Alien Game",
182197
"uuid": "3550ec07-f6c6-48bd-b2b4-086e75faf9e7",
183198
"concepts": ["classes"],
184-
"prerequisites": ["basics", "bools", "comparisons", "loops", "dicts", "lists", "numbers", "sets", "strings", "tuples"],
199+
"prerequisites": ["basics",
200+
"bools",
201+
"comparisons",
202+
"loops",
203+
"dicts",
204+
"lists",
205+
"numbers",
206+
"sets",
207+
"strings",
208+
"tuples"
209+
],
185210
"status": "beta"
186211
}
187212
],

docs/TOOLS.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ To create a virtual environment, `cd` to the directory you want to store your en
3737
```bash
3838
$ python3 -m venv {name_of_virtualenv}
3939
created virtual environment ... in 8568ms
40-
```
4140

4241
#### Activating your virtual environment
4342

@@ -181,7 +180,7 @@ Sublime Text comes with a lot of tools already, but some of these tools could ma
181180
182181
### JupyterLab
183182
184-
[Jupyter lab](https://jupyter.org/install) is an in-browser code editor that runs on your machine, combining the ability to write Markdown along side executable code and data. Jupyter supports multiple programming languages via `kernels` and can display graphs and tables as well as code and text.
183+
[Jupyter lab](https://jupyter.org/install) is an in-browser code editor that runs on your machine, combining the ability to write Markdown along side executable code and data. Jupyter supports multiple programming languages via `kernels` and can display graphs and tables as well as code and text.
185184
186185
Jupyter comes pre-packaged with Anaconda. You can also install it in a **virtual environment** using `pip` or `conda`. Jupyter will use that environment and its Python version. Jupyter is most well-known for its code "notebooks". It is commonly used among data-scientists.
187186
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Hints
2+
3+
## 1. Generate an amount of seats
4+
5+
- The returned value should be of _type_ `generator`.
6+
- Row `13` should be skipped, so go from `12` to `14`.
7+
- Keep in mind that the returned values should be ordered from low to high. `1A, 1B, 2A, ...`
8+
9+
## 2. Assign seats to passengers
10+
11+
- Make sure your seat numbers do not have any space in them.
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Instructions
2+
3+
Conda airlines is the programming-world's biggest airline, with over 10.000 flights a day!
4+
5+
They are currently assigning all seats to passengers by hand, this will need to automated.
6+
7+
They have asked _you_ to create software to automate the assigning of seats to passengers. They require your software to be memory efficient and performant.
8+
9+
Conda's airplanes have up to _4 seats_ in each row, and each airplane has many rows.
10+
11+
While the rows are defined using numbers, seats in each row are defined using letters from the alphabet, with `seat A` being the first _seat_ in the row.
12+
13+
You can use this table as a guide:
14+
15+
| x | 1 | 2 |
16+
| :----: | :----: | :----:|
17+
| Row | 5 | 21 |
18+
| Seat letter | A | D |
19+
| Result | 5A | 21D |
20+
21+
## 1. Generate an amount of seats
22+
23+
Implement the `generate_seats()` function that returns an _iterable_ of seats given the following variable:
24+
25+
`amount`: The amount of seats to be generated.
26+
27+
Many airlines do not have _row_ number 13 on their flights, due to superstition amongst passengers.
28+
Conda Airlines also follows this convention, so make sure you _don't_ generate seats for _row_ number 13.
29+
30+
_Note: The returned seats should be ordered, like: 1A 1B 1C._
31+
32+
```python
33+
>>> seats = generate_seats(10)
34+
>>> next(seats)
35+
"1A"
36+
>>> next(seats)
37+
"1B"
38+
```
39+
40+
## 2. Assign seats to passengers
41+
42+
Implement the `assign_seats()` function that returns a _dictionary_ of `passenger` as _key_, and `seat_number` as _value_. Given is the following _list_:
43+
44+
`passengers`: A list containing passenger names.
45+
46+
```python
47+
>>> passengers = ['Jerimiah', 'Eric', 'Bethaney', 'Byte', 'SqueekyBoots', 'Bob']
48+
49+
>>> assign_seats(passengers)
50+
{'Jerimiah': '1A', 'Eric': '1B', 'Bethaney': '1C', 'Byte': '1D', 'SqueekyBoots': '2A', 'Bob': '2B'}
51+
```
52+
53+
## 3. Ticket codes
54+
55+
Each ticket has a _12_ character long string code for identification.
56+
57+
This code begins with the `assigned_seat` followed by the `flight_id`. The rest of the code is appended by `0s`.
58+
59+
Implement a `generator` that yields a `ticket_number` given the following arguments:
60+
61+
`seat_numbers`: A _list_ of *seat_numbers*.
62+
`flight_id`: A string containing the flight identification.
63+
64+
```python
65+
>>> seat_numbers = ['1A', '17D']
66+
>>> flight_id = 'CO1234'
67+
>>> ticket_ids = generate_codes(seat_numbers, flight_id)
68+
69+
>>> next(ticket_ids)
70+
'1ACO12340000'
71+
>>> next(ticket_ids)
72+
'17DCO1234000'
73+
```
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Introduction
2+
3+
A generator in Python is a _callable function_ that returns a [lazy iterator](https://en.wikipedia.org/wiki/Lazy_evaluation).
4+
5+
_Lazy iterators_ are similar to iterables such as `lists`, and other types of `iterators` in Python -- but with one key difference: `generators` do not store their `values` in memory, but _generate_ their values as needed or when called.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"blurb": "Learn about generators by assigning seats to passengers.",
3+
"authors": ["J08K"],
4+
"icon": "poker",
5+
"contributors": ["BethanyG"],
6+
"files": {
7+
"solution": ["plane_tickets.py"],
8+
"test": ["plane_tickets_test.py"],
9+
"exemplar": [".meta/exemplar.py"]
10+
}
11+
}

0 commit comments

Comments
 (0)