Skip to content

Commit

Permalink
Merge branch 'master' of github.com:hanze-hbo-ict/programmeren
Browse files Browse the repository at this point in the history
  • Loading branch information
misja committed Oct 10, 2023
2 parents 5e4af6f + 8f43bb5 commit 31f5d4b
Show file tree
Hide file tree
Showing 23 changed files with 2,152 additions and 206 deletions.
2 changes: 1 addition & 1 deletion lectures/4_errors.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
" if len(s) == 0:\n",
" return\n",
" print(s[0])\n",
" blaat(s[:1])\n",
" blaat(s[1:])\n",
"\n",
"blaat(\"test\")\n",
"```\n"
Expand Down
9 changes: 7 additions & 2 deletions lectures/9_lussen.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -1139,7 +1139,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
Expand All @@ -1153,7 +1153,12 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.0"
"version": "3.11.2 (tags/v3.11.2:878ead1, Feb 7 2023, 16:38:35) [MSC v.1934 64 bit (AMD64)]"
},
"vscode": {
"interpreter": {
"hash": "7321d1f7eabf315803f0fbeb0be0427ff6d045140e09c9efe7edcc325df00e23"
}
}
},
"nbformat": 4,
Expand Down
9 changes: 7 additions & 2 deletions lectures/old topics/15_lussen.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -1689,7 +1689,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
Expand All @@ -1703,7 +1703,12 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.0"
"version": "3.11.2 (tags/v3.11.2:878ead1, Feb 7 2023, 16:38:35) [MSC v.1934 64 bit (AMD64)]"
},
"vscode": {
"interpreter": {
"hash": "7321d1f7eabf315803f0fbeb0be0427ff6d045140e09c9efe7edcc325df00e23"
}
}
},
"nbformat": 4,
Expand Down
231 changes: 231 additions & 0 deletions practicals/8a_list_comprehensions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
# List Comprehensions


## Voorbereiding

Download [Python sounds](https://github.com/hanze-hbo-ict/programmeren/raw/master/problems/assets/wk4ex1.zip).

Dit bestand moet ergens uitgepakt worden. Het bevat een aantal bestanden die allemaal in **dezelfde map** moeten staan:

- `wk4ex1.py` (het bestand dat je gaat uitvoeren!)
- `swfaith.wav`
- `swnotry.wav`
- `spam.wav`
- `audio.py`

### Werk vanuit deze directory!

Je moet deze week vanuit de directory `wk4ex1` werken, je zal hiervoor moeten `cd`'en naar de map `wk4ex1`. Houd alle bestanden in `wk4ex1` bij elkaar, als je het bestand `wk4ex1.py` verplaatst zonder de andere bestanden werkt het **niet**!

## Opdracht 1

Je gaat een aantal functies schrijven met behulp van list comprehensions. List comprehensions zijn een flexibele manier om een functie (of handeling, bijvoorbeeld een berekening) uit te voeren (te "mappen") op alle elementen van een lijst.

**a.** Bekijk de functie `three_ize` vrijwel aan het begin van `wk4ex1.py`:

```python
def three_ize(L):
"""three_ize is a function that accepts a list and
returns a list of elements each three times as large.
"""
# lc, een voorbeeld van een list comprehension
lc = [3 * x for x in L]
return lc
```

Deze functie voert de berekening `3 * x` uit op de waarden `x` in de lijst `L`. Probeer het uit met dit voorbeeld:

```ipython
In [1]: three_ize([13, 14, 15])
Out[1]: [39, 42, 45]
```



**b.** Gebruik de bovenstaande functie `three_ize` als voorbeeld om de functie `scale` te schrijven met onderstaande *signature*:

```python
def scale(L, scale_factor):
...
```

Deze functie geeft een lijst terug die vergelijkbaar is met `L`, behalve dat elk element is vermenigvuldigd met `scale_factor`. Maak gebruik van list comprehensions! Een voorbeeld:

```ipython
In [1]: scale([70, 80, 420], 0.1)
Out[1]: [7.0, 8.0, 42.0]
```

## Opdracht 2

De volgende stap is het schrijven van een functie `three_ize_by_index` met list comprehensions waar je gebruik gaat maken van de *index* (of positie) van elementen in een lijst.

**a** Controleer dat de onderstaande functie `three_ize_by_index` in jouw bestand `wk4ex1.py` aanwezig is.

```python
def three_ize_by_index(L):
"""three_ize_by_index has the same behavior as three_ize
but it uses the INDEX of each element, instead of
using the elements themselves -- this is much more flexible!
"""
# nog een voorbeeld van een list comprehension
n = len(L)
lc = [3 * L[i] for i in range(n)]
return lc
```

Deze functie doet *exact hetzelfde* als `three_ize`, maar gebruikt nu de *index* van elk element. Dat wil zeggen, nu is het de **locatie** van elk element in een lijst, we noemen deze hier `i`, die steeds verandert.

Het gebruik van een index maakt list comprehensions nog flexibeler dan wanneer we de elementen rechtstreeks gebruiken, zoals we gaan zien in de volgende opdrachten.

**b** : `add_2`

Gebruik de bovenstaande functie gebaseerd op *index* als richtlijn om de functie `add_2(L, m)` te schrijven met onderstaande signature:

```python
def add_2(L, m):
...
```

Deze functie krijgt twee lijsten `L` en `m` mee en geeft een enkele lijst terug die de elementen van de twee lijsten elementsgewijs bij elkaar optelt. Als de twee lijsten een andere lengte hebben, moet `add_2` een lijst teruggeven die even lang is als de *kortste* van de twee. Je kan de extra elementen van de langere lijst negeren.

Je kan dit bijvoorbeeld doen door `min`, `len(L)` en `len(m)` te combineren. Als voorbeeld zal de regel

```python
n = min(len(L), len(m))
```

de kleinste van de lengtes van `L` en `m` aan `n` toekennen.

Het is handig om hier een aanpak gebaseerd op *index* te gebruiken. Je kan de functie `three_ize_by_index` als voorbeeld gebruiken. Bekijk ook hoe je de onderstaande list comprehension hiervoor zou kunnen gebruiken:

```python
lc = [L[i] + m[i] for ...]
```

Hieronder zie je twee voorbeelden van het gebruik van `add_2`:

```ipython
In [1]: add_2([10, 11, 12], [20, 25, 30])
Out[1]: [30, 36, 42]

In [2]: add_2([10, 11], [20, 25, 30])
Out[2]: [30, 36]
```

**c** : `add_3`

Schrijf nu een vergelijkbare functie `add_3` met drie argumenten volgens de onderstaande signature:

```python
def add_3(L, m, p):
...
```

waar `L`, `m` en `p` lijsten zijn en `add_3` de som van de drie lijsten teruggeeft, maar met evenveel elementen als de *kortste* van de drie. De aanpak zal erg lijken op die voor `add_2`.

## Opdracht 3

Schrijf nu een functie `add_scale_2` met de onderstaande signature:

```python
def add_scale_2(L, m, L_scale, m_scale):
...
```

Deze functie krijgt twee lijsten `L` en `m` mee en twee floating-point getallen `L_scale` en `m_scale`. Deze staan respectievelijk voor *schaalfactor voor `L`* en *schaalfactor voor `m`*.

De functie `add_scale_2` moet een enkele lijst teruggeven die een elementsgewijze optelling is van de twee lijsten, maar *ieder vermenigvuldigd met zijn respectievelijke floating-point getallen*. Als de lijsten niet dezelfde lengte hebben, moet de functie een lijst met de lengte van de *kortste* lijst teruggeven. Je kan extra elementen negeren.

Hier zie je twee voorbeelden:

```ipython
In [1]: add_scale_2([10, 20, 30], [7, 8, 9], 0.1, 10)
Out[1]: [71.0, 82.0, 93.0]

In [2]: add_scale_2([10, 20, 30], [7, 8], 0.1, 10)
Out[2]: [71.0, 82.0]
```

Dit zal nogal lijken op de vorige opdrachten!

## Opdracht 4

**a** Bekijk deze hulpfunctie in het bestand `wk4ex1.py`:

```python
def randomize(x, chance_of_replacing):
"""randomize accepts an original value, x
and a fraction named chance_of_replacing.
With the "chance_of_replacing" chance, it
should return a random float from -32767 to 32767.
Otherwise, it should return x (not replacing it).
"""
r = random.uniform(0, 1)
if r < chance_of_replacing:
return random.uniform(-32768, 32767)
else:
return x
```

Lees de docstring en probeer de functie uit.

Het enige dat we hier van jou vragen is om te *begrijpen* wat deze functie doet: hoe vaak wordt de *oorspronkelijke* waarde teruggegeven en hoe vaak een *willekeurige* waarde. Deze willekeurige waarde valt binnen het bereik van de drukgolven van een geluid.

De functie geeft een willekeurige waarde terug, maar hier is een voorbeeld van een aantal keer dat de functie wordt uitgevoerd:

```ipython
In [1]: randomize(42, .5)
Out[1]: 42

In [2]: randomize(42, .5)
Out[2]: 42

In [3]: randomize(42, .5)
Out[3]: 29209.30669767395

In [4]: randomize(42, .5)
Out[4]: 42

In [5]: randomize(42, .5)
Out[5]: 17751.221299744262
```


**b** Schrijf nu een functie `replace_some` met de volgende signature:

```python
def replace_some(L, chance_of_replacing):
...
```

De functie krijgt een lijst `L` en een floating-point getal `chance_of_replacing` mee. `replace_some` moet onafhankelijk van elkaar elk element in L vervangen (of niet vervangen) door gebruik te maken van de hulpfunctie `randomize`.

:::{admonition} Gebruik `randomize`
:class: tip

Gebruik `randomize` in een list comprehension, meer hoef je niet te doen! Bedenk hoe je onderstaand statement kan aanvullen (en vergeet niet om `lc` terug te geven):

```python
lc = [randomize(..., ...) for x in L]
```
:::

Aangezien de functie willekeurig is, zal de uitvoer op jouw systeem niet gelijk zijn, maar probeer of het ongeveer als volgt werkt:

```ipython
In [1]: replace_some(range(40, 50), .5) # vervang ongeveer de helft (hopelijk blijft de 42 staan!)
Out[1]: [40, 41, 42, -17461.09350529409, 44, -13989.513742241645, 46, -26247.774200304026, 48, 49]

In [2]: replace_some(range(20, 30), .1) # vervang ongeveer een tiende (maar het is wel willekeurig: hier zijn er twee vervangen)
Out[2]: [20, 21, 16774.26240973895, 23, 24, 25, -18184.919872079583, 27, 28, 29]
```

Om je te helpen met testen zijn hier een paar `assert` statements om in je code over te nemen. Merk op dat de tweede assertion stelt dat het resultaat *ongelijk* is aan 42!

```python
assert replace_some(range(40, 50), 0) == list(range(40, 50))
assert replace_some([42], 1.0) != [42]
```
Loading

0 comments on commit 31f5d4b

Please sign in to comment.