Skip to content
Open
9 changes: 9 additions & 0 deletions exercises/practice/raindrops/.approaches/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@
"authors": [
"bobahop"
]
},
{
"uuid": "d16d4056-2434-44ff-aae6-2bd57eb53dd7",
"slug": "modular-arithmetic",
Comment thread
habere-et-dispertire marked this conversation as resolved.
Outdated
"title": "Modular Arithmetic",
"blurb": "Use modular arithmetic to generalize.",
"authors": [
"habere-et-dispertire"
]
}
]
}
27 changes: 27 additions & 0 deletions exercises/practice/raindrops/.approaches/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,32 @@ class RaindropConverter {

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

## Approach: `Modular Arithmetic`

```java
import java.math.BigInteger;
import static java.math.BigInteger.valueOf;

class RaindropConverter {

String convert (int n) {
return switch ( valueOf(n).modPow( valueOf(12), valueOf(105) ).intValue() ) {
case 36 -> "Pling";
case 85 -> "Plang";
case 91 -> "Plong";
case 15 -> "PlingPlang";
case 21 -> "PlingPlong";
case 70 -> "PlangPlong";
case 0 -> "PlingPlangPlong";
default -> String.valueOf(n); // 1
};
}

}
```

For more information, check the [Modular Arithmetic approach][approach-modulus].

## Which approach to use?

Benchmarking with the [Java Microbenchmark Harness][jmh] is currently outside the scope of this document,
Expand All @@ -64,4 +90,5 @@ and no other code would need to be added.
[remainder-operator]: https://www.geeksforgeeks.org/modulo-or-remainder-operator-in-java/
[approach-if-statements]: https://exercism.org/tracks/java/exercises/raindrops/approaches/if-statements
[approach-map]: https://exercism.org/tracks/java/exercises/raindrops/approaches/map
[approach-modulus]: https://exercism.org/tracks/java/exercises/raindrops/approaches/modulus

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The last part of the URL should match the slug in the config

Suggested change
[approach-modulus]: https://exercism.org/tracks/java/exercises/raindrops/approaches/modulus
[approach-modulus]: https://exercism.org/tracks/java/exercises/raindrops/approaches/modular-arithmetic

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be okay now no (since I changed the slug) ?

[jmh]: https://github.com/openjdk/jmh
31 changes: 31 additions & 0 deletions exercises/practice/raindrops/.approaches/modulus/content.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# modular arithmetic

```java
import java.math.BigInteger;
import static java.math.BigInteger.valueOf;

class RaindropConverter {

String convert (int n) {
return switch ( valueOf(n).modPow( valueOf(12), valueOf(105) ).intValue() ) {
case 36 -> "Pling";
case 85 -> "Plang";
case 91 -> "Plong";
case 15 -> "PlingPlang";
case 21 -> "PlingPlong";
case 70 -> "PlangPlong";
case 0 -> "PlingPlangPlong";
default -> String.valueOf(n); // 1
};
}

}
```

We can generalize raindrops to any factors if they are [co-prime][co-prime].
In raindrops the factors 3, 5 and 7 are co-prime (sets of prime numbers are all co-prime) and so we can use [Euler's totient function][euler-totient] to calculate `n¹² mod 105` to give us unique values for the various sounds.
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].

[co-prime]: https://en.wikipedia.org/wiki/Coprime_integers
[euler-totient]: https://en.wikipedia.org/wiki/Euler's_totient_function
[fizz-buzz]: https://philcrissman.net/posts/eulers-fizzbuzz/
12 changes: 12 additions & 0 deletions exercises/practice/raindrops/.approaches/modulus/snippet.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
String convert (int n) {
return switch ( valueOf(n).modPow( valueOf(12), valueOf(105) ).intValue() ) {
case 36 -> "Pling";
case 85 -> "Plang";
case 91 -> "Plong";
case 15 -> "PlingPlang";
case 21 -> "PlingPlong";
case 70 -> "PlangPlong";
case 0 -> "PlingPlangPlong";
default -> String.valueOf(n); // 1
};
}
Loading