Skip to content

Commit 963215e

Browse files
neenjawcmccandlessErikSchierboom
committed
new concept exercise - bools
Introduces the bools concept, see design and .docs for more details. Co-authored-by: Corey McCandless <[email protected]> Co-authored-by: Erik Schierboom <[email protected]>
1 parent a1e18e3 commit 963215e

File tree

9 files changed

+316
-0
lines changed

9 files changed

+316
-0
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
Python represents True and False values with the [boolean][boolean] type. There are only two [boolean][boolean] values: _True_ and _False_. These values can be assigned to a variable and combined with [boolean operators][boolean-operators] (`and`, `or`, `not`):
2+
3+
```python
4+
true_variable = True and True
5+
false_variable = True and False
6+
7+
true_variable = False or True
8+
false_variable = False or False
9+
10+
true_variable = not False
11+
false_variable = not True
12+
```
13+
14+
[Boolean operators][boolean-operators] use _short-circuit evaluation_, which means that expression on the right-hand side of the operator is only evaluated if needed.
15+
16+
Each of the operators has a different precedence, where `not` is evaluated before `and` and `or`. Brackets can be used to evaluate one part of the expression before the others:
17+
18+
```python
19+
not True and True # => False
20+
not (True and False) # => True
21+
```
22+
23+
## Type Coercion and Truthiness
24+
25+
The [`bool` function][bool-function] converts any type to a Boolean value. By default all values return `True` unless defined to return `False`.
26+
27+
Some built-ins already defined to be considered `False`:
28+
29+
- constants like `None` and `False`
30+
- zero of any _numeric type_
31+
- empty _sequences_ and _collections_
32+
33+
```python
34+
bool(1) # => True
35+
bool(0) # => False
36+
```
37+
38+
When a value is used in a boolean context, it is used as a _truthy_ or _falsey_ value by transparently using the `bool` function.
39+
40+
```python
41+
a = "is this true?"
42+
if a:
43+
print("True")
44+
# => This will print "True", as a non-empty string is a truthy value
45+
```
46+
47+
Classes may define how they are evaluated in truthy situations if they override and implement a `__bool__` method.
48+
49+
## How Booleans work under the hood
50+
51+
The Boolean type is a _sub-type_ of the _int_ type. `True` is numerically equal to `1`. `False` is numerically equal to `0`. This is observable when comparing them:
52+
53+
```python
54+
1 == True # => True
55+
0 == False # => True
56+
```
57+
58+
However, they are still different as noted when checking for a Boolean identity:
59+
60+
```python
61+
1 is True # => False
62+
0 is False # => False
63+
```
64+
65+
> Note: in python >= 3.8, using a literal value on the left side of `is` will raise a warning.
66+
67+
[bool-function]: https://docs.python.org/3/library/functions.html#bool
68+
[boolean]: https://docs.python.org/3/library/stdtypes.html#truth
69+
[boolean-operators]: https://docs.python.org/3/library/stdtypes.html#boolean-operations-and-or-not
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
## General
2+
3+
- Don't worry about how the arguments are derived, just focus on combining the arguments to return the intended result.
4+
5+
## 1. Define if Pac-Man can eat a ghost
6+
7+
- You can use the [boolean][boolean] [operators][boolean-operators] to combine the arguments for a result.
8+
9+
## 2. Define if Pac-Man scores
10+
11+
- You can use the [boolean][boolean] [operator][boolean-operators] to combine the arguments for a result.
12+
13+
## 3. Define if Pac-Man loses
14+
15+
- You can use the [boolean][boolean] [operator][boolean-operators] to combine the arguments for a result.
16+
17+
## 4. Define if Pac-Man wins
18+
19+
- You can use the [boolean][boolean] [operator][boolean-operators] to combine the arguments for a result.
20+
21+
[boolean]: https://docs.python.org/3/library/stdtypes.html#truth
22+
[boolean-operators]: https://docs.python.org/3/library/stdtypes.html#boolean-operations-and-or-not
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
In this exercise, you need to implement some rules from [Pac-Man, the classic arcade-game](https://en.wikipedia.org/wiki/Pac-Man).
2+
3+
You have four rules to implement, all related to the game states.
4+
5+
> Don't worry about how the arguments are derived, just focus on combining the arguments to return the intended result.
6+
7+
## 1. Define if Pac-Man eats a ghost
8+
9+
Define the `eat_ghost()` function that takes two parameters (_if Pac-Man has a power pellet active_ and _if Pac-Man is touching a ghost_) and returns a boolean value if Pac-Man is able to eat the ghost. The function should return `True` only if Pac-Man has a power pellet active and is touching a ghost.
10+
11+
```python
12+
eat_ghost(False, True)
13+
# => False
14+
```
15+
16+
## 2. Define if Pac-Man scores
17+
18+
Define the `score()` function that takes two parameters (_if Pac-Man is touching a power pellet_ and _if Pac-Man is touching a dot_) and returns a boolean value if Pac-Man scored. The function should return `True` if Pac-Man is touching a power pellet or a dot.
19+
20+
```python
21+
score(True, True)
22+
# => True
23+
```
24+
25+
## 3. Define if Pac-Man loses
26+
27+
Define the `lose()` function that takes two parameters (_if Pac-Man has a power pellet active_ and _if Pac-Man is touching a ghost_) and returns a boolean value if Pac-Man loses. The function should return `True` if Pac-Man is touching a ghost and does not have a power pellet active.
28+
29+
```python
30+
lose(False, True)
31+
# => True
32+
```
33+
34+
## 4. Define if Pac-Man wins
35+
36+
Define the `win()` function that takes three parameters (_if Pac-Man has eaten all of the dots_, _if Pac-Man has a power pellet active_, and _if Pac-Man is touching a ghost_) and returns a boolean value if Pac-Man wins. The function should return `True` if Pac-Man has eaten all of the dots and has not lost based on the parameters defined in part 3.
37+
38+
```python
39+
win(False, True, False)
40+
# => False
41+
```
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Python represents true and false values with the boolean type. There are only two values: `True` and `False`. These values can be bound to a variable:
2+
3+
```python
4+
true_variable = True
5+
false_variable = False
6+
```
7+
8+
We can evaluate boolean expressions using the `and`, `or`, and `not` operators.
9+
10+
```python
11+
true_variable = True and True
12+
false_variable = True and False
13+
14+
true_variable = False or True
15+
false_variable = False or False
16+
17+
true_variable = not False
18+
false_variable = not True
19+
```
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"authors": [
3+
{
4+
"github_username": "neenjaw",
5+
"exercism_username": "neenjaw"
6+
}
7+
],
8+
"contributors": [
9+
{
10+
"github_username": "cmccandless",
11+
"exercism_username": "cmccandless"
12+
}
13+
],
14+
"forked_from": ["elixir/booleans"],
15+
"language_versions": ">=3.5"
16+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
## Goal
2+
3+
The goal of this exercise is to teach the student how [`bool`](https://github.com/exercism/v3/blob/master/languages/python/reference/concepts/builtin_types/bool.md) is implemented and used in Python. We will teach the `bool` type by showing the student how to use it.
4+
5+
## Learning objectives
6+
7+
- create a `bool` object via literal declaration
8+
- obtain a `bool` object from using [logical operators](https://docs.python.org/3/reference/expressions.html#boolean-operations) (`and`, `or`, `not`)
9+
10+
## Out of scope
11+
12+
- obtain a `bool` object from [comparison operators](https://docs.python.org/3/reference/expressions.html#value-comparisons) (`>`, `<`, `==`)
13+
- obtain a `bool` object from [membership operators](https://docs.python.org/3/reference/expressions.html#membership-test-operations) (`in`, `not in`)
14+
- obtain a `bool` object from [identity operators](https://docs.python.org/3/reference/expressions.html#is-not) (`is`, `is not`)
15+
- 'truthyness' and 'falsyness'
16+
- create a `bool` object from other objects (`collections`, `integers`, `strings`) with the the `bool()` constructor.
17+
- catching/raising Exceptions
18+
- covering that `bool` is a subtype of `int`
19+
- bitwise logical operators
20+
- orders of evaluation
21+
22+
## Concepts
23+
24+
- **booleans:** know of the existence of the bool type and its two values; know about boolean operators and how to build logical expressions with them; know of the boolean operator precedence rules.
25+
26+
## Prerequisites
27+
28+
- `builtin-types`
29+
- `comparison-operators`
30+
31+
## Resources
32+
33+
- [Boolean Operations — and, or, not](https://docs.python.org/3/library/stdtypes.html#boolean-operations-and-or-not)
34+
- [Built-in Functions - bool](https://docs.python.org/3/library/functions.html#bool)
35+
- [Truth Value Testing](https://docs.python.org/3/library/stdtypes.html#truth)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
def eat_ghost(power_pellet_active, touching_ghost):
2+
return power_pellet_active and touching_ghost
3+
4+
5+
def score(touching_power_pellet, touching_dot):
6+
return touching_power_pellet or touching_dot
7+
8+
9+
def lose(power_pellet_active, touching_ghost):
10+
return not power_pellet_active and touching_ghost
11+
12+
13+
def win(has_eaten_all_dots, power_pellet_active, touching_ghost):
14+
return has_eaten_all_dots and not lose(power_pellet_active, touching_ghost)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
def eat_ghost(power_pellet_active, touching_ghost):
2+
pass
3+
4+
def score(touching_power_pellet, touching_dot):
5+
pass
6+
7+
def lose(power_pellet_active, touching_ghost):
8+
pass
9+
10+
def win(has_eaten_all_dots, power_pellet_active, touching_ghost):
11+
pass
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import unittest
2+
from arcade_game import eat_ghost, score, lose, win
3+
4+
5+
class TestArcadeGame(unittest.TestCase):
6+
7+
def test_ghost_gets_eaten(self):
8+
self.assertIs(
9+
eat_ghost(True, True),
10+
True,
11+
msg="ghost should get eaten"
12+
)
13+
14+
def test_ghost_does_not_get_eaten_because_no_power_pellet_active(self):
15+
self.assertIs(
16+
eat_ghost(False, True),
17+
False,
18+
msg="ghost does not get eaten because no power pellet active"
19+
)
20+
21+
def test_ghost_does_not_get_eaten_because_not_touching_ghost(self):
22+
self.assertIs(
23+
eat_ghost(True, False),
24+
False,
25+
msg="ghost does not get eaten because not touching ghost"
26+
)
27+
28+
def test_score_when_eating_dot(self):
29+
self.assertIs(
30+
score(False, True),
31+
True,
32+
msg="score when eating dot"
33+
)
34+
35+
def test_score_when_eating_power_pellet(self):
36+
self.assertIs(
37+
score(True, False),
38+
True,
39+
msg="score when eating power pellet"
40+
)
41+
42+
def test_no_score_when_nothing_eaten(self):
43+
self.assertIs(
44+
score(False, False),
45+
False,
46+
msg="no score when nothing eaten"
47+
)
48+
49+
def test_lose_if_touching_a_ghost_without_a_power_pellet_active(self):
50+
self.assertIs(
51+
lose(False, True),
52+
True,
53+
msg="lose if touching a ghost without a power pellet active"
54+
)
55+
56+
def test_dont_lose_if_touching_a_ghost_with_a_power_pellet_active(self):
57+
self.assertIs(
58+
lose(True, True),
59+
False,
60+
msg="don't lose if touching a ghost with a power pellet active"
61+
)
62+
63+
def test_dont_lose_if_not_touching_a_ghost(self):
64+
self.assertIs(
65+
lose(True, False),
66+
False,
67+
msg="don't lose if not touching a ghost"
68+
)
69+
70+
def test_win_if_all_dots_eaten(self):
71+
self.assertIs(
72+
win(True, False, False),
73+
True,
74+
msg="win if all dots eaten"
75+
)
76+
77+
def test_dont_win_if_all_dots_eaten_but_touching_a_ghost(self):
78+
self.assertIs(
79+
win(True, False, True),
80+
False,
81+
msg="don't win if all dots eaten, but touching a ghost"
82+
)
83+
84+
def test_win_if_all_dots_eaten_and_touching_a_ghost_with_a_power_pellet_active(self):
85+
self.assertIs(
86+
win(True, True, True),
87+
True,
88+
msg="win if all dots eaten and touching a ghost with a power pellet active"
89+
)

0 commit comments

Comments
 (0)