Skip to content

[New Concept Exercise] : Generators (Plane Tickets) #2729

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 138 commits into from
Mar 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
138 commits
Select commit Hold shift + click to select a range
81a7c22
Update TESTS.md
J08K Sep 20, 2021
6548ec9
Update TESTS.md
J08K Sep 21, 2021
2b51829
Update TESTS.md
J08K Sep 22, 2021
d447645
Start of TOOLS.md
J08K Sep 24, 2021
60b84f3
Finished writing VS Code part
J08K Sep 27, 2021
1a72ef0
Added Pycharm docs & relative img links
J08K Sep 27, 2021
7b87a4f
Update TOOLS.md
J08K Sep 27, 2021
1021bb8
Added Spyder Docs
J08K Sep 28, 2021
3d66c2b
Added VENV docs
J08K Sep 28, 2021
09b1813
Added conda environments docs
J08K Sep 28, 2021
9c1d1a9
Wrote Windows tutorial for adding to path
J08K Sep 28, 2021
3c18af3
Improved shared test file and added disclaimer to TOOLS.md
J08K Sep 28, 2021
5ac3fa2
Added docs for JupyterLab and Sublime Text
J08K Sep 30, 2021
ae2de41
Added Virtualenvwrapper piece.
J08K Sep 30, 2021
b8c8a9a
Cleaned up.
J08K Sep 30, 2021
553b6d7
Updated image paths
J08K Sep 30, 2021
68eca1f
Fixed Images x2
J08K Sep 30, 2021
430bac3
Images have absolute path
J08K Sep 30, 2021
a433864
Update docs/TESTS.md
J08K Oct 2, 2021
d2612d9
Update docs/TESTS.md
J08K Oct 2, 2021
584fd07
Update docs/TESTS.md
J08K Oct 2, 2021
2e15fac
Update docs/TESTS.md
J08K Oct 2, 2021
782c5df
Update docs/TESTS.md
J08K Oct 2, 2021
d00a764
Update docs/TESTS.md
J08K Oct 2, 2021
5400ae3
Update docs/TOOLS.md
J08K Oct 2, 2021
3e9b506
Update docs/TOOLS.md
J08K Oct 2, 2021
fcc43f9
Update docs/TESTS.md
J08K Oct 2, 2021
7dc6c9c
Update docs/TOOLS.md
J08K Oct 2, 2021
15ae0db
Update docs/TOOLS.md
J08K Oct 2, 2021
d6d57f5
Update exercises/shared/.docs/tests.md
J08K Oct 2, 2021
d770ab8
Update exercises/shared/.docs/tests.md
J08K Oct 2, 2021
994ad50
Fixed capitalization
J08K Oct 2, 2021
f4224c0
Update docs/TOOLS.md
J08K Oct 2, 2021
75b0ad6
Fixed language
J08K Oct 2, 2021
cb990e3
Update docs/TOOLS.md
J08K Oct 2, 2021
092a25b
Update docs/TOOLS.md
J08K Oct 2, 2021
95b28cc
Update docs/TOOLS.md
J08K Oct 2, 2021
1ff0be9
Update docs/TESTS.md
J08K Oct 2, 2021
6c1328c
Update docs/TOOLS.md
J08K Oct 2, 2021
170d298
Update docs/TOOLS.md
J08K Oct 2, 2021
92c6c4e
Update docs/TESTS.md
J08K Oct 4, 2021
85ae17e
Update docs/TESTS.md
J08K Oct 4, 2021
f053a22
Update docs/TESTS.md
J08K Oct 4, 2021
b8ad4b5
Update docs/TOOLS.md
J08K Oct 4, 2021
568de19
Layed out ground work
J08K Oct 6, 2021
f2d797a
Write introduction
J08K Oct 7, 2021
e6b8588
Update docs/TESTS.md
J08K Oct 7, 2021
c913f75
Added pytest.ini docs
J08K Oct 13, 2021
81abb80
Update docs/TESTS.md
J08K Oct 13, 2021
3684cdd
Update docs/TESTS.md
J08K Oct 13, 2021
3d66a5c
Update docs/TESTS.md
J08K Oct 13, 2021
8f2692b
Update docs/TOOLS.md
J08K Oct 14, 2021
822a54b
Apply suggestions from code review
J08K Oct 14, 2021
0ee4359
Update docs/TOOLS.md
J08K Oct 14, 2021
0c53083
Update docs/TOOLS.md
J08K Oct 14, 2021
cde80ca
Update docs/TOOLS.md
J08K Oct 14, 2021
f2ea08d
Update docs/TOOLS.md
J08K Oct 14, 2021
4cc8d6e
Start on instructions
J08K Oct 14, 2021
1db4ce9
Update headers and links
J08K Oct 14, 2021
5d20728
Removed template
J08K Oct 14, 2021
6e937d0
Task 1
J08K Oct 14, 2021
d9dc03d
Merge branch 'exercism:main' into main
J08K Oct 21, 2021
5fda574
Merge branch 'exercism:main' into main
J08K Oct 25, 2021
176a1a3
Merge branch 'exercism:main' into main
J08K Oct 30, 2021
924c083
sync with PCs
J08K Nov 3, 2021
ac50632
Sync
J08K Nov 3, 2021
d999678
Task 1 Exemplar
J08K Nov 4, 2021
79b9fb6
Exemplar now also skips row 13
J08K Nov 4, 2021
5bfd965
Fixed (skip row 13)
J08K Nov 4, 2021
4650a4a
Finished Task 1 & 2
J08K Nov 4, 2021
5c3940a
Remove Typing
J08K Nov 4, 2021
c5fb961
Merge remote-tracking branch 'upstream/main'
J08K Nov 4, 2021
3c47c4c
Merge branch 'main' into J08K-New-Concept-Exercise
J08K Nov 4, 2021
b8ea390
Cleanup
J08K Nov 4, 2021
8cafa69
Add some data in ./concepts
J08K Nov 4, 2021
19c471c
Add exercise to config.json
J08K Nov 4, 2021
fedabbe
fixing
J08K Nov 4, 2021
1394f9a
Update concepts/generators/.meta/config.json
J08K Nov 4, 2021
0859ccc
Update concepts/generators/introduction.md
J08K Nov 4, 2021
46ca557
Update exercises/concept/plane-tickets/.docs/instructions.md
J08K Nov 4, 2021
81aef4c
Update exercises/concept/plane-tickets/.docs/introduction.md
J08K Nov 4, 2021
87dbc72
Update concepts/generators/introduction.md
J08K Nov 5, 2021
38e4351
Fixed all pylint warnings in Exemplar
J08K Nov 5, 2021
7f9f6b3
Merge branch 'J08K-New-Concept-Exercise' of https://github.com/J08K/p…
J08K Nov 5, 2021
74fc18a
Update exercises/concept/plane-tickets/.meta/exemplar.py
J08K Nov 5, 2021
69e96c2
Merge branch 'exercism:main' into J08K-New-Concept-Exercise
J08K Dec 3, 2021
7ea0eb4
Committed suggestions and Added new task 3
J08K Dec 9, 2021
6557816
Apply suggestions from code review
BethanyG Dec 10, 2021
e20949c
Apply suggestions from code review WHOOOOP
J08K Dec 13, 2021
d751ec4
Add tests for task 3
J08K Dec 13, 2021
cdc58be
Update config.json
J08K Dec 13, 2021
997c30f
Merge remote-tracking branch 'origin/J08K-New-Concept-Exercise' into …
J08K Dec 13, 2021
b5ac150
Better test case 1; add test for type task 3
J08K Dec 13, 2021
0060913
Don't you love pytests?
J08K Dec 13, 2021
b809473
Merge branch 'main' into pr/2729
BethanyG Mar 9, 2022
b21b0aa
🤖 Sync org-wide files to upstream repo
exercism-bot Mar 9, 2022
324e499
Layed out ground work
J08K Oct 6, 2021
8694216
Write introduction
J08K Oct 7, 2021
fabe7c4
Start on instructions
J08K Oct 14, 2021
96bee10
Removed template
J08K Oct 14, 2021
ca21760
Task 1
J08K Oct 14, 2021
9b554a4
sync with PCs
J08K Nov 3, 2021
c086767
Sync
J08K Nov 3, 2021
191b57c
Task 1 Exemplar
J08K Nov 4, 2021
a38f8f3
Exemplar now also skips row 13
J08K Nov 4, 2021
e329bff
Fixed (skip row 13)
J08K Nov 4, 2021
3159215
Finished Task 1 & 2
J08K Nov 4, 2021
9a60e00
Remove Typing
J08K Nov 4, 2021
5ea95df
Update TESTS.md
J08K Sep 20, 2021
46923d8
Update TESTS.md
J08K Sep 21, 2021
ccee77f
Update TESTS.md
J08K Sep 22, 2021
be697ad
Start of TOOLS.md
J08K Sep 24, 2021
177aba2
Finished writing VS Code part
J08K Sep 27, 2021
6db7b17
Added Pycharm docs & relative img links
J08K Sep 27, 2021
385b8bd
Update TOOLS.md
J08K Sep 27, 2021
1675034
Added VENV docs
J08K Sep 28, 2021
6400263
Wrote Windows tutorial for adding to path
J08K Sep 28, 2021
a3ba686
Improved shared test file and added disclaimer to TOOLS.md
J08K Sep 28, 2021
f619980
Update docs/TOOLS.md
J08K Oct 14, 2021
823737f
Cleanup
J08K Nov 4, 2021
48f0a79
Add some data in ./concepts
J08K Nov 4, 2021
f658f95
Add exercise to config.json
J08K Nov 4, 2021
d4a5d54
fixing
J08K Nov 4, 2021
7c420d0
Fixed all pylint warnings in Exemplar
J08K Nov 5, 2021
ca6047d
Update concepts/generators/.meta/config.json
J08K Nov 4, 2021
fdf30cb
Update concepts/generators/introduction.md
J08K Nov 4, 2021
a992d8c
Update exercises/concept/plane-tickets/.docs/instructions.md
J08K Nov 4, 2021
29fd11b
Update exercises/concept/plane-tickets/.docs/introduction.md
J08K Nov 4, 2021
5291c3a
Update concepts/generators/introduction.md
J08K Nov 5, 2021
09f6e29
Update exercises/concept/plane-tickets/.meta/exemplar.py
J08K Nov 5, 2021
6e3f4bf
Committed suggestions and Added new task 3
J08K Dec 9, 2021
17c25b1
Apply suggestions from code review
BethanyG Dec 10, 2021
35744f1
Apply suggestions from code review WHOOOOP
J08K Dec 13, 2021
07f3535
Add tests for task 3
J08K Dec 13, 2021
85cfc47
Better test case 1; add test for type task 3
J08K Dec 13, 2021
6ee6ccc
Don't you love pytests?
J08K Dec 13, 2021
cf56cce
Merge branch 'J08K-New-Concept-Exercise' of https://github.com/J08K/p…
BethanyG Mar 10, 2022
abf417f
Update config.json
BethanyG Mar 10, 2022
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
23 changes: 11 additions & 12 deletions .github/workflows/configlet.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
name: Configlet CI
name: Configlet

on: [push, pull_request, workflow_dispatch]
on:
pull_request:
push:
branches:
- main
workflow_dispatch:

permissions:
contents: read

jobs:
configlet:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Fetch configlet
uses: exercism/github-actions/configlet-ci@main

- name: Configlet Linter
run: configlet lint
uses: exercism/github-actions/.github/workflows/configlet.yml@main
18 changes: 8 additions & 10 deletions .github/workflows/sync-labels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,18 @@ name: Tools

on:
push:
branches: [main]
branches:
- main
paths:
- .github/labels.yml
- .github/workflows/sync-labels.yml
schedule:
- cron: 0 0 1 * *
workflow_dispatch:
schedule:
- cron: 0 0 1 * * # First day of each month

permissions:
issues: write

jobs:
sync-labels:
name: Sync labels
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: micnncim/action-label-syncer@3abd5ab72fda571e69fffd97bd4e0033dd5f495c
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: exercism/github-actions/.github/workflows/labels.yml@main
4 changes: 2 additions & 2 deletions concepts/generators/.meta/config.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"blurb": "TODO: add blurb for this concept",
"authors": ["bethanyg", "cmccandless"],
"blurb": "Learn about generators by assigning seats to passengers.",
"authors": ["J08K"],
"contributors": []
}
132 changes: 131 additions & 1 deletion concepts/generators/about.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,132 @@
#TODO: Add about for this concept.
# About

## Constructing a generator

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.


An example is a function that returns the _squares_ from a given list of numbers.
As currently written, all input must be processed before any values can be returned:


```python
>>> def squares(list_of_numbers):
>>> squares = []
>>> for number in list_of_numbers:
>>> squares.append(number ** 2)
>>> return squares
```

You can convert that function into a generator like this:

```python
def squares(list_of_numbers):
for number in list_of_number:
yield number ** 2
```

The rationale behind this is that you use a generator when you do not need all the values _at once_.

This saves memory and processing power, since only the value you are _currently working on_ is calculated.


## Using a generator

Generators may be used in place of most `iterables` in Python. This includes _functions_ or _objects_ that require an `iterable`/`iterator` as an argument.

To use the `squares()` generator:

```python
>>> squared_numbers = squares([1, 2, 3, 4])

>>> for square in squared_numbers:
>>> print(square)
1
4
9
16
```

Values within a generator can also be produced/accessed via the `next()` function.
`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.

```python
square_generator = squares([1, 2])

>>> next(square_generator)
1
>>> next(square_generator)
4
```

When a `generator` is fully consumed and has no more values to return, it throws a `StopIteration` error.

```python
>>> next(square_generator)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
```

### Difference between iterables and generators

Generators are a special sub-set of _iterators_.
`Iterators` are the mechanism/protocol that enables looping over _iterables_.
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:


- Generators are _one-way_; there is no "backing up" to a previous value.

- Iterating over generators consume the returned values; no resetting.
- Generators (_being lazily evaluated_) are not sortable and can not be reversed.

- Generators do _not_ have `indexes`, so you can't reference a previous or future value using addition or subtraction.

- Generators cannot be used with the `len()` function.

- Generators can be _finite_ or _infinite_, be careful when collecting all values from an _infinite_ generator.

## The yield expression

The [yield expression](https://docs.python.org/3.8/reference/expressions.html#yield-expressions) is very similar to the `return` expression.

_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.

When `yield` is evaluated, it pauses the execution of the enclosing function and returns any values of the function _at that point in time_.

The function then _stays in scope_, and when `__next__()` is called, execution resumes until `yield` is encountered again.

Note: _Using `yield` expressions is prohibited outside of functions._

```python
>>> def infinite_sequence():
>>> current_number = 0
>>> while True:
>>> yield current_number
>>> current_number += 1

>>> lets_try = infinite_sequence()
>>> lets_try.__next__()
0
>>> lets_try.__next__()
1
```

## Why generators?

Generators are useful in a lot of applications.

When working with a large collection, you might not want to put all of its values into `memory`.
A generator can be used to work on larger data piece-by-piece, saving memory and improving performance.

Generators are also very helpful when a process or calculation is _complex_, _expensive_, or _infinite_:

```python
>>> def infinite_sequence():
>>> current_number = 0
>>> while True:
>>> yield current_number
>>> current_number += 1
```

Now whenever `__next__()` is called on the `infinite_sequence` object, it will return the _previous number_ + 1.
5 changes: 4 additions & 1 deletion concepts/generators/introduction.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
#TODO: Add introduction for this concept.
# Introduction

A generator in Python is a _callable function_ that returns a [lazy iterator](https://en.wikipedia.org/wiki/Lazy_evaluation).

_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.
16 changes: 4 additions & 12 deletions concepts/generators/links.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
[
{
"url": "http://example.com/",
"description": "TODO: add new link (above) and write a short description here of the resource."
"url": "https://docs.python.org/3.8/reference/expressions.html#yield-expressions",
"description": "Official Python 3.8 docs for the yield expression."
},
{
"url": "http://example.com/",
"description": "TODO: add new link (above) and write a short description here of the resource."
},
{
"url": "http://example.com/",
"description": "TODO: add new link (above) and write a short description here of the resource."
},
{
"url": "http://example.com/",
"description": "TODO: add new link (above) and write a short description here of the resource."
"url": "https://en.wikipedia.org/wiki/Lazy_evaluation",
"description": "Wikipedia page about lazy evaluation"
}
]
27 changes: 26 additions & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -176,12 +176,37 @@
"prerequisites": ["basics", "dicts", "lists", "loops", "tuples"],
"status": "beta"
},
{
"slug": "plane-tickets",
"name": "Plane Tickets",
"uuid": "3ba3fc89-3e1b-48a5-aff0-5aeaba8c8810",
"concepts": [
"generators"
],
"prerequisites": [
"conditionals",
"dicts",
"lists",
"loops"
],
"status": "wip"
},
{
"slug": "ellens-alien-game",
"name": "Ellen's Alien Game",
"uuid": "3550ec07-f6c6-48bd-b2b4-086e75faf9e7",
"concepts": ["classes"],
"prerequisites": ["basics", "bools", "comparisons", "loops", "dicts", "lists", "numbers", "sets", "strings", "tuples"],
"prerequisites": ["basics",
"bools",
"comparisons",
"loops",
"dicts",
"lists",
"numbers",
"sets",
"strings",
"tuples"
],
"status": "beta"
}
],
Expand Down
3 changes: 1 addition & 2 deletions docs/TOOLS.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ To create a virtual environment, `cd` to the directory you want to store your en
```bash
$ python3 -m venv {name_of_virtualenv}
created virtual environment ... in 8568ms
```

#### Activating your virtual environment

Expand Down Expand Up @@ -181,7 +180,7 @@ Sublime Text comes with a lot of tools already, but some of these tools could ma

### JupyterLab

[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.
[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.

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.

Expand Down
11 changes: 11 additions & 0 deletions exercises/concept/plane-tickets/.docs/hints.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Hints

## 1. Generate an amount of seats

- The returned value should be of _type_ `generator`.
- Row `13` should be skipped, so go from `12` to `14`.
- Keep in mind that the returned values should be ordered from low to high. `1A, 1B, 2A, ...`

## 2. Assign seats to passengers

- Make sure your seat numbers do not have any space in them.
73 changes: 73 additions & 0 deletions exercises/concept/plane-tickets/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Instructions

Conda airlines is the programming-world's biggest airline, with over 10.000 flights a day!

They are currently assigning all seats to passengers by hand, this will need to automated.

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.

Conda's airplanes have up to _4 seats_ in each row, and each airplane has many rows.

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.

You can use this table as a guide:

| x | 1 | 2 |
| :----: | :----: | :----:|
| Row | 5 | 21 |
| Seat letter | A | D |
| Result | 5A | 21D |

## 1. Generate an amount of seats

Implement the `generate_seats()` function that returns an _iterable_ of seats given the following variable:

`amount`: The amount of seats to be generated.

Many airlines do not have _row_ number 13 on their flights, due to superstition amongst passengers.
Conda Airlines also follows this convention, so make sure you _don't_ generate seats for _row_ number 13.

_Note: The returned seats should be ordered, like: 1A 1B 1C._

```python
>>> seats = generate_seats(10)
>>> next(seats)
"1A"
>>> next(seats)
"1B"
```

## 2. Assign seats to passengers

Implement the `assign_seats()` function that returns a _dictionary_ of `passenger` as _key_, and `seat_number` as _value_. Given is the following _list_:

`passengers`: A list containing passenger names.

```python
>>> passengers = ['Jerimiah', 'Eric', 'Bethaney', 'Byte', 'SqueekyBoots', 'Bob']

>>> assign_seats(passengers)
{'Jerimiah': '1A', 'Eric': '1B', 'Bethaney': '1C', 'Byte': '1D', 'SqueekyBoots': '2A', 'Bob': '2B'}
```

## 3. Ticket codes

Each ticket has a _12_ character long string code for identification.

This code begins with the `assigned_seat` followed by the `flight_id`. The rest of the code is appended by `0s`.

Implement a `generator` that yields a `ticket_number` given the following arguments:

`seat_numbers`: A _list_ of *seat_numbers*.
`flight_id`: A string containing the flight identification.

```python
>>> seat_numbers = ['1A', '17D']
>>> flight_id = 'CO1234'
>>> ticket_ids = generate_codes(seat_numbers, flight_id)

>>> next(ticket_ids)
'1ACO12340000'
>>> next(ticket_ids)
'17DCO1234000'
```
5 changes: 5 additions & 0 deletions exercises/concept/plane-tickets/.docs/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Introduction

A generator in Python is a _callable function_ that returns a [lazy iterator](https://en.wikipedia.org/wiki/Lazy_evaluation).

_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.
11 changes: 11 additions & 0 deletions exercises/concept/plane-tickets/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"blurb": "Learn about generators by assigning seats to passengers.",
"authors": ["J08K"],
"icon": "poker",
"contributors": ["BethanyG"],
"files": {
"solution": ["plane_tickets.py"],
"test": ["plane_tickets_test.py"],
"exemplar": [".meta/exemplar.py"]
}
}
Loading