Skip to content

Commit 641ae34

Browse files
Add Modular Arithmetic approach to RaindropConverter (#3144)
1 parent 0443ae5 commit 641ae34

4 files changed

Lines changed: 75 additions & 0 deletions

File tree

exercises/practice/raindrops/.approaches/config.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,15 @@
2222
"authors": [
2323
"bobahop"
2424
]
25+
},
26+
{
27+
"uuid": "d16d4056-2434-44ff-aae6-2bd57eb53dd7",
28+
"slug": "modulus",
29+
"title": "Modulus",
30+
"blurb": "Use modular arithmetic to generalize.",
31+
"authors": [
32+
"habere-et-dispertire"
33+
]
2534
}
2635
]
2736
}

exercises/practice/raindrops/.approaches/introduction.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,32 @@ class RaindropConverter {
5454

5555
For more information, check the [`Map` approach][approach-map].
5656

57+
## Approach: `Modulus`
58+
59+
```java
60+
import java.math.BigInteger;
61+
import static java.math.BigInteger.valueOf;
62+
63+
class RaindropConverter {
64+
65+
String convert (int n) {
66+
return switch ( valueOf(n).modPow( valueOf(12), valueOf(105) ).intValue() ) {
67+
case 36 -> "Pling";
68+
case 85 -> "Plang";
69+
case 91 -> "Plong";
70+
case 15 -> "PlingPlang";
71+
case 21 -> "PlingPlong";
72+
case 70 -> "PlangPlong";
73+
case 0 -> "PlingPlangPlong";
74+
default -> String.valueOf(n); // 1
75+
};
76+
}
77+
78+
}
79+
```
80+
81+
For more information, check the [Modulus approach][approach-modulus].
82+
5783
## Which approach to use?
5884

5985
Benchmarking with the [Java Microbenchmark Harness][jmh] is currently outside the scope of this document,
@@ -64,4 +90,5 @@ and no other code would need to be added.
6490
[remainder-operator]: https://www.geeksforgeeks.org/modulo-or-remainder-operator-in-java/
6591
[approach-if-statements]: https://exercism.org/tracks/java/exercises/raindrops/approaches/if-statements
6692
[approach-map]: https://exercism.org/tracks/java/exercises/raindrops/approaches/map
93+
[approach-modulus]: https://exercism.org/tracks/java/exercises/raindrops/approaches/modulus
6794
[jmh]: https://github.com/openjdk/jmh
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Modulus
2+
3+
```java
4+
import java.math.BigInteger;
5+
import static java.math.BigInteger.valueOf;
6+
7+
class RaindropConverter {
8+
9+
String convert (int n) {
10+
return switch ( valueOf(n).modPow( valueOf(12), valueOf(105) ).intValue() ) {
11+
case 36 -> "Pling";
12+
case 85 -> "Plang";
13+
case 91 -> "Plong";
14+
case 15 -> "PlingPlang";
15+
case 21 -> "PlingPlong";
16+
case 70 -> "PlangPlong";
17+
case 0 -> "PlingPlangPlong";
18+
default -> String.valueOf(n); // 1
19+
};
20+
}
21+
22+
}
23+
```
24+
25+
We can generalize raindrops to any factors if they are [co-prime][co-prime].
26+
In raindrops, the factors 3, 5 and 7 are co-prime (all sets of prime numbers are co-prime), so we can use [Euler's totient function][euler-totient] to calculate `n¹² mod 105`, giving us unique values for the various sounds.
27+
The math behind how we find the right exponent and modulus is explained in an article on the related problem of [Fizz-Buzz][fizz-buzz].
28+
29+
[co-prime]: https://en.wikipedia.org/wiki/Coprime_integers
30+
[euler-totient]: https://en.wikipedia.org/wiki/Euler's_totient_function
31+
[fizz-buzz]: https://philcrissman.net/posts/eulers-fizzbuzz/
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
String convert (int n) {
2+
return switch (BigInteger.valueOf(n).modPow(BigInteger.valueOf(12),BigInteger.valueOf(105)).intValue()) {
3+
case 0 -> "PlingPlangPlong";
4+
case 36 -> "Pling";
5+
// other cases
6+
default -> String.valueOf(n); // 1
7+
};
8+
}

0 commit comments

Comments
 (0)