You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: exercises/practice/leap/.approaches/boolean-chain/content.md
+10-10Lines changed: 10 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,11 +8,11 @@ def leap_year(year):
8
8
9
9
This might be considered the "most idiomatic" or "most Pythonic" solution, as it is exactly the same as the code implemented by the maintainers of the Python language for the [`calendar.isleap()`][isleap-source] method.
10
10
11
-
The first boolean expression uses the [modulo operator][modulo-operator] to check if the year is evenly divided by `4`.
12
-
- If the year is _not_ evenly divisible by `4`, then the chain will [short circuit][short-ciruiting] due to the next operator being a [logical AND][logical-and]{`and`), and will return `False`.
11
+
The first boolean expression uses the [modulo operator][modulo-operator] to check if the year is evenly divisible by `4`.
12
+
- If the year is _not_ evenly divisible by `4`, then the chain will [short circuit][short-ciruiting] due to the next operator being a [logical AND][logical-and](`and`), and will return `False`.
13
13
- If the year _is_ evenly divisible by `4`, then the year is checked to _not_ be evenly divisible by `100`.
14
-
- If the year is not evenly divisible by `100`, then the expression is `True` and the interpreter will stop the evaluation to return `True`, since the next operator is a [logical OR][logical-or] (`or`).
15
-
- If the year _is_ evenly divisible by `100`, then the expression is `False`, and the returned value from the chain will be if the year is evenly divisible by `400`.
14
+
- If the year is not evenly divisible by `100`, the expression is `True` and the chain will short circuit and return `True`, since the next operator is a [logical OR][logical-or] (`or`).
15
+
- If the year _is_ evenly divisible by `100`, then the expression is `False`, and the returned value from the chain will be `True`if the year is evenly divisible by `400`.
16
16
17
17
18
18
| year | year % 4 == 0 | year % 100 != 0 | year % 400 == 0 | is leap year |
@@ -37,10 +37,10 @@ In Python, `a and b or c` is interpreted as `(a and b) or c`, which would give t
37
37
If in doubt, it is always permissible to add extra parentheses for clarity.
38
38
39
39
40
-
## Refactoring
40
+
## Variation 1
41
+
42
+
By using the [falsiness][falsiness] of `0`, the [`not` operator][not-operator] can be used instead of comparing equality to `0`:
41
43
42
-
By using the [falsiness][falsiness] of `0`, the [`not` operator][not-operator] can be used instead of comparing equality to `0`.
43
-
For example:
44
44
45
45
```python
46
46
defleap_year(year):
@@ -50,10 +50,10 @@ def leap_year(year):
50
50
51
51
It can be thought of as the expression _not_ having a remainder.
This approach may be considered a "cheat" for this exercise, which is intended to practice Boolean operators and logic.
11
+
This approach may be considered a "cheat" for this exercise, which is intended to practice Boolean operators and Boolean logic.
12
12
~~~~
13
13
14
14
15
15
The Python standard library includes a [`calendar`][calendar] module for working with many aspects of dates in the [Gregorian calendar][gregorian-calendar].
16
-
17
16
One of the methods provided is [`isleap()`][isleap], which implements exactly the same functionality as this exercise.
18
17
19
18
This is not a good way to practice the use of Booleans, as the exercise intends.
20
-
However, it may be convenient (_and better tested_) if you are working with calendar functions more broadly.
19
+
However, it may be convenient (_and better tested_) if you are working with `calendar` functions more broadly.
20
+
21
21
22
22
## The library function
23
23
24
-
This is the [implementation][implementation]:
24
+
This is the actual [implementation][implementation] in the CPython code:
25
25
26
26
```python
27
27
defisleap(year):
28
28
"""Return True for leap years, False for non-leap years."""
29
29
return year %4==0and (year %100!=0or year %400==0)
30
30
```
31
31
32
-
We can see that `calendar.isleap()` is just syntactic sugar for the `boolean-chain` approach.
33
-
32
+
We can see that `calendar.isleap()` is just syntactic sugar for the [`boolean-chain`][approach-boolean-chain] approach.
This approach may be considered a "cheat" for this exercise, which is intended to practice Boolean operators and logic.
15
-
It also adds a tremendous amount of overhead in both performance and memory, as it imports all of the `datetime` module and requires the instantiation of both a `datetime` object and a `datetime.timedelta` object.
12
+
~~~~exercism/note
13
+
This approach may be considered a "cheat" for this exercise, which is intended to practice Boolean operators and boolean logic.
14
+
It also adds overhead in both performance and memory, as it imports methods from the `datetime` module and requires the instantiation of both a `datetime` object and a `timedelta` object.
16
15
17
-
For more information, see this exercises performance article.
16
+
For more information, see the performance article for this exercise.
18
17
~~~~
19
18
20
-
By adding a day to February 28th for a given year, you can see if the new day falls on the 29th of February, or the 1st of March.
19
+
20
+
By adding a day to February 28th for a given year, you can see if the new day falls on the 29th of February or the 1st of March.
21
21
If it is February 29th, then the function returns `True` for the year being a leap year.
22
22
23
-
- A new [datetime][datetime] object is created for February 28th of the year.
24
-
-Then the [timedelta][timedelta] of one day is added to that `datetime`,
25
-
and the function returns if the [day][day] property of the resulting `datetime` object is the 29th.
23
+
- A new [`datetime`][datetime] object is created for February 28th of the year.
24
+
-A [`timedelta`][timedelta] of one day is added to that `datetime`,
25
+
- The function returns if the [`day`][day] property of the resulting `datetime` object is the 29th.
Copy file name to clipboardExpand all lines: exercises/practice/leap/.approaches/introduction.md
+41-17Lines changed: 41 additions & 17 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,17 +1,19 @@
1
1
# Introduction
2
2
3
-
There are multiple idiomatic approaches to solving the Leap exercise.
4
-
You can use a chain of boolean expressions to test the conditions, a [ternary operator][ternary-operator], or built-in methods from the `datetime` or `calendar` modules.
3
+
There are multiple approaches to solving the Leap exercise in Python.
4
+
You can use a chain of boolean expressions or a [`ternary operator`][ternary-operator] to test conditions.
5
+
You can also utilize built-in methods from the `datetime` or `calendar` modules.
5
6
6
7
7
8
## General Guidance
8
9
9
10
The key to efficiently solving Leap is to calculate if the year is evenly divisible by `4`, `100` and `400`.
10
-
For determining that, you will use the [modulo operator][modulo-operator].
11
+
Using the [modulo operator][modulo-operator] is a good way of determining that.
11
12
12
13
13
14
## Approach: Chain of Boolean Expressions
14
15
16
+
15
17
```python
16
18
defleap_year(year):
17
19
return year %4==0and (year %100!=0or year %400==0)
@@ -34,45 +36,67 @@ For more information, see the [Ternary operator approach][approach-ternary-opera
34
36
35
37
## Other Approaches
36
38
37
-
Besides the aforementioned, idiomatic approaches, you could also approach the exercise as follows:
39
+
Besides the aforementioned and idiomatic approaches, you could also approach the exercise as follows:
38
40
39
41
40
-
### Approach: `datetime` Addition
42
+
### Approach: Using `datetime` Addition
41
43
42
44
Add a day to February 28th for the year and see if the new day is the 29th.
43
45
However, this approach may trade speed for convenience.
For more information, see the [`datetime` addition approach][approach-datetime-addition].
45
55
46
56
47
-
### Approach: The`calendar` module
57
+
### Approach: Using the`calendar` module
48
58
49
-
It is possible to use `calendar.isleap(year)` from the standard library, which solves this exact problem.
59
+
It is possible to use [`calendar.isleap(<year>)`][isleap] from the standard library, which solves this exact problem:
50
60
51
-
This is self-defeating in an Exercism practice exercise intended to explore ways to use booleans.
52
-
In a wider context, anyone testing for leap years may already be using `calendar` or related modules, and it is good to know what library functions are available.
61
+
62
+
```python
63
+
from calendar import isleap
64
+
65
+
defleap_year(year):
66
+
return isleap(year)
67
+
```
68
+
69
+
This is self-defeating in the context of Exercism.
70
+
This practice exercise was designed to explore ways to use `booleans` and boolean logic.
71
+
The point is not _really_ leap year determination.
72
+
In a wider context, anyone testing for leap years is likely using `calendar` or related modules (_hand rolling your own test is likely to introduce bugs_), so it is good to know what library functions are available.
73
+
74
+
For more discussion, see the [`calendar.isleap()` approach][approach-calendar-isleap].
53
75
54
76
55
77
## Which approach to use?
56
78
57
-
- The chain of boolean expressions should be the most efficient, as it proceeds from the most to least likely conditions and takes advantage of short-circuiting.
79
+
- The chain of `boolean expressions` should be the most efficient, as it proceeds from most to least likely conditions and takes advantage of [`short-circuiting`][short-circuting].
58
80
It has a maximum of three checks.
59
81
It is the fastest approach when testing a year that is not evenly divisible by `100` that is not a leap year.
60
82
Since most years fit those conditions, it is overall the most efficient approach.
61
83
It also happens to be the approach taken by the maintainers of the Python language in [implementing `calendar.isleap()`][calendar_isleap-code].
62
84
63
-
64
-
- The ternary operator approach has a maximum of only two checks, but it starts from a less likely condition.
65
-
The ternary operator was faster in benchmarking when the year was a leap year or was evenly divisible by `100`,
66
-
but those are the _least likely_ conditions.
67
-
- Using `datetime` addition may be considered a "cheat" for the exercise, and it was slower by far than the other approaches in benchmarking.
85
+
- The `ternary operator` approach has a maximum of only two checks, but it starts from a less likely condition.
86
+
The `ternary operator` was faster in benchmarking when the year was a leap year or was evenly divisible by `100`,
87
+
but those are the _least likely_ conditions!
88
+
- Using `datetime` addition may be considered a "cheat" for the exercise, and it was slower by far than the other approaches in benchmarking, due to import and method overhead.
68
89
69
90
For more information, check out the [Performance article][article-performance].
Copy file name to clipboardExpand all lines: exercises/practice/leap/.approaches/ternary-operator/content.md
+9-7Lines changed: 9 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,14 +6,15 @@ def leap_year(year):
6
6
7
7
```
8
8
9
-
A [ternary operator][ternary-operator] uses a maximum of two checks to determine if a year is a leap year.
9
+
A [`ternary operator`][ternary-operator] uses a maximum of two checks to determine if a year is a leap year.
10
10
11
11
It starts by testing the outlier condition of the year being evenly divisible by `100`.
12
12
It does this by using the [modulo operator][modulo-operator].
13
13
Also, by using the [falsiness][falsiness] of `0`, the [`not` operator][not-operator] can be used instead of comparing equality to `0`.
14
14
15
-
- If the year is evenly divisible by `100`, then the expression is `True`, and the ternary operator returns if the year is evenly divisible by `400`.
16
-
- If the year is _not_ evenly divisible by `100`, then the expression is `False`, and the ternary operator returns if the year is evenly divisible by `4`.
15
+
- If the year is evenly divisible by `100`, then the ternary operator returns `True` if the year is evenly divisible by `400`.
16
+
- If the year is _not_ evenly divisible by `100`, the ternary operator returns `True` if the year is evenly divisible by `4`.
17
+
17
18
18
19
| year | year % 100 == 0 | year % 400 == 0 | year % 4 == 0 | is leap year |
@@ -22,13 +23,14 @@ Also, by using the [falsiness][falsiness] of `0`, the [`not` operator][not-opera
22
23
| 2000 | True | True | not evaluated | True |
23
24
| 1900 | True | False | not evaluated | False |
24
25
26
+
25
27
Although it uses a maximum of only two checks, the ternary operator tests an outlier condition first,
26
-
making it less efficient than another approach that would first test if the year is evenly divisible by `4`,
27
-
which is more likely than the year being evenly divisible by `100`.
28
+
making it less efficient than the [boolean chain approach][approach-boolean-chain] that first tests if the year is evenly divisible by `4` (_which is more likely than the year being evenly divisible by `100`_).
28
29
The ternary operator was fastest in benchmarking when the year was a leap year or was evenly divisible by `100`,
0 commit comments