Skip to content

Commit 12e5ad5

Browse files
authored
Leap approaches (exercism#2233)
* Create config.json * Update config.json * Create introduction.md * Create snippet.md * Create content.md * Create snippet.md * Create content.md * Update snippet.md * Update introduction.md * Create snippet.md * Update introduction.md * Create content.md * Create snippet.md * Create content.md * Update introduction.md * Update and rename snippet.md to snippet.txt * Update and rename snippet.md to snippet.txt * Update and rename snippet.md to snippet.txt * Update and rename snippet.md to snippet.txt
1 parent 5da95d3 commit 12e5ad5

10 files changed

Lines changed: 211 additions & 0 deletions

File tree

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Chain of boolean expressions
2+
3+
```java
4+
boolean isLeapYear(int year) {
5+
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
6+
}
7+
```
8+
9+
The first boolean expression uses the [remainder operator][remainder-operator] to check if the year is evenly divided by `4`.
10+
- If the year is not evenly divisible by `4`, then the chain will "short circuit" due to the next operator being a [logical AND][logical-and] (`&&`), and will return `false`.
11+
- If the year _is_ evenly divisible by `4`, then the year is checked to _not_ be evenly divisible by `100`.
12+
- If the year is not evenly divisible by `100`, then the expression is `true` and the chain will "short-circuit" to return `true`,
13+
since the next operator is a [logical OR][logical-or] (`||`).
14+
- 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`.
15+
16+
| year | year % 4 == 0 | year % 100 != 0 | year % 400 == 0 | is leap year |
17+
| ---- | ------------- | --------------- | --------------- | ------------ |
18+
| 2020 | true | true | not evaluated | true |
19+
| 2019 | false | not evaluated | not evaluated | false |
20+
| 2000 | true | false | true | true |
21+
| 1900 | true | false | false | false |
22+
23+
24+
The chain of boolean expressions is efficient, as it proceeds from testing the most likely to least likely conditions.
25+
26+
[remainder-operator]: https://www.geeksforgeeks.org/modulo-or-remainder-operator-in-java/
27+
[logical-and]: https://www.geeksforgeeks.org/java-logical-operators-with-examples/
28+
[logical-or]: https://www.geeksforgeeks.org/java-logical-operators-with-examples/
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
boolean isLeapYear(int year) {
2+
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
3+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# `isLeap()`
2+
3+
```java
4+
import java.time.Year;
5+
6+
class Leap {
7+
8+
boolean isLeapYear(int year) {
9+
return Year.of(year).isLeap();
10+
}
11+
}
12+
```
13+
14+
This may be considered a "wicked cheat" for this exercise, by simply passing the year into the [isLeap()][is-leap] method of the [Year][year] class.
15+
Although it is not in the spirit of this exercise, `isLeap()` would be the idiomatic way to determine if a year is a leap year in the "real world".
16+
17+
[is-leap]: https://docs.oracle.com/javase/8/docs/api/java/time/Year.html#isLeap--
18+
[year]: https://docs.oracle.com/javase/8/docs/api/java/time/Year.html
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import java.time.Year;
2+
3+
class Leap {
4+
5+
boolean isLeapYear(int year) {
6+
return Year.of(year).isLeap();
7+
}
8+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"introduction": {
3+
"authors": ["bobahop"],
4+
"contributors": []
5+
},
6+
"approaches": [
7+
{
8+
"uuid": "588b8946-b46b-4ba2-81c7-09651f78d5bd",
9+
"slug": "boolean-chain",
10+
"title": "Boolean chain",
11+
"blurb": "Use a chain of boolean expressions.",
12+
"authors": ["bobahop"]
13+
},
14+
{
15+
"uuid": "5af62bf0-1b7e-4091-9f2f-c4e61328389e",
16+
"slug": "ternary-operator",
17+
"title": "Ternary operator",
18+
"blurb": "Use a ternary operator of boolean expressions.",
19+
"authors": ["bobahop"]
20+
},
21+
{
22+
"uuid": "fd01895e-2a15-453a-889a-b6db88047b07",
23+
"slug": "plusdays",
24+
"title": "plusDays method",
25+
"blurb": "Use the plusDays method.",
26+
"authors": ["bobahop"]
27+
},
28+
{
29+
"uuid": "fc2d7749-1fe2-4df3-b121-b7c4f25dd103",
30+
"slug": "built-in-method",
31+
"title": "Built-in method",
32+
"blurb": "Use the built-in method.",
33+
"authors": ["bobahop"]
34+
}
35+
]
36+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Introduction
2+
3+
There are various idiomatic approaches to solve Leap.
4+
You can use a chain of boolean expressions to test the conditions.
5+
Or you can use a [ternary operator][ternary-operator].
6+
7+
## General guidance
8+
9+
The key to solving Leap is to know if the year is evenly divisible by `4`, `100` and `400`.
10+
For determining that, you will use the [remainder operator][remainder-operator].
11+
12+
## Approach: Chain of Boolean expressions
13+
14+
```java
15+
boolean isLeapYear(int year) {
16+
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
17+
}
18+
```
19+
20+
For more information, check the [Boolean chain approach][approach-boolean-chain].
21+
22+
## Approach: Ternary operator of Boolean expressions
23+
24+
```java
25+
boolean isLeapYear(int year) {
26+
return year % 100 == 0 ? year % 400 == 0 : year % 4 == 0;
27+
}
28+
```
29+
30+
For more information, check the [Ternary operator approach][approach-ternary-operator].
31+
32+
## Other approaches
33+
34+
Besides the aforementioned, idiomatic approaches, you could also approach the exercise as follows:
35+
36+
## `plusDays()` approach:
37+
38+
Add a day to February 28th for the year and see if the new day is the 29th. For more information, see the [`plusDays()` approach][approach-plusdays].
39+
40+
## Built-in method approach:
41+
42+
Use the built-in method for the [Year][year]. For more information, see the [`isLeap()` approach][approach-isleap].
43+
44+
## Which approach to use?
45+
46+
- The chain of boolean expressions is most efficient, as it proceeds from the most likely to least likely conditions.
47+
It has a maximum of three checks.
48+
- The ternary operator has a maximum of only two checks, but it starts from a less likely condition.
49+
- Using `plusDays()` or using the built-in `isLeap()` method may be considered "cheats" for the exercise,
50+
but `isLeap()` would be the idiomatic way to check if a year is a leap year in Java.
51+
52+
[remainder-operator]: https://www.geeksforgeeks.org/modulo-or-remainder-operator-in-java/
53+
[ternary-operator]: https://www.geeksforgeeks.org/java-ternary-operator-with-examples/
54+
[approach-boolean-chain]: https://exercism.org/tracks/java/exercises/leap/approaches/boolean-chain
55+
[approach-ternary-operator]: https://exercism.org/tracks/java/exercises/leap/approaches/ternary-operator
56+
[approach-plusdays]: https://exercism.org/tracks/java/exercises/leap/approaches/plusdays
57+
[year]: https://docs.oracle.com/javase/8/docs/api/java/time/Year.html
58+
[approach-isleap]: https://exercism.org/tracks/java/exercises/leap/approaches/built-in-method
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# `plusDays()` method
2+
3+
```java
4+
import java.time.*;
5+
6+
class Leap {
7+
8+
boolean isLeapYear(int year) {
9+
return LocalDate.of(year, Month.FEBRUARY, 28).plusDays(1).getDayOfMonth() == 29;
10+
}
11+
}
12+
```
13+
14+
This approach may be considered a "cheat" for this exercise.
15+
By adding a day to February 28th for the year, you can see if the new day is the 29th or the 1st.
16+
If it is the 29th, then the year is a leap year.
17+
This is done by using the [`plusDays()`][plusdays] and [`getDayOfMonth()`][getdayofmonth] methods of the [LocalDate][localdate] class.
18+
19+
[plusdays]: https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/time/LocalDate.html#plusDays(long)
20+
[getdayofmonth]: https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/time/LocalDate.html#getDayOfMonth()
21+
[localdate]: https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/time/LocalDate.html
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import java.time.*;
2+
3+
class Leap {
4+
5+
boolean isLeapYear(int year) {
6+
return LocalDate.of(year, Month.FEBRUARY, 28).plusDays(1).getDayOfMonth() == 29;
7+
}
8+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Ternary operator
2+
3+
```java
4+
boolean isLeapYear(int year) {
5+
return year % 100 == 0 ? year % 400 == 0 : year % 4 == 0;
6+
}
7+
```
8+
9+
A [ternary operator][ternary-operator] uses a maximum of two checks to determine if a year is a leap year.
10+
11+
It starts by testing the outlier condition of the year being evenly divisible by `100`.
12+
It does this by using the [remainder operator][remainder-operator].
13+
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`.
14+
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+
16+
| year | year % 100 == 0 | year % 400 == 0 | year % 4 == 0 | is leap year |
17+
| ---- | --------------- | --------------- | -------------- | ------------ |
18+
| 2020 | false | not evaluated | true | true |
19+
| 2019 | false | not evaluated | false | false |
20+
| 2000 | true | true | not evaluated | true |
21+
| 1900 | true | false | not evaluated | false |
22+
23+
Although it uses a maximum of only two checks, the ternary operator tests an outlier condition first,
24+
making it less efficient than another approach that would first test if the year is evenly divisible by `4`,
25+
which is more likely than the year being evenly divisible by `100`.
26+
27+
[ternary-operator]: https://www.geeksforgeeks.org/java-ternary-operator-with-examples/
28+
[remainder-operator]: https://www.geeksforgeeks.org/modulo-or-remainder-operator-in-java/
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
boolean isLeapYear(int year) {
2+
return year % 100 == 0 ? year % 400 == 0 : year % 4 == 0;
3+
}

0 commit comments

Comments
 (0)