From 80ccb9219d019b47c43acef0ae7dea7c6f85ac9c Mon Sep 17 00:00:00 2001 From: habere-et-dispertire <18032974+habere-et-dispertire@users.noreply.github.com> Date: Mon, 22 Jun 2026 20:12:46 +0100 Subject: [PATCH 01/10] Add Modular Arithmetic approach to RaindropConverter --- .../raindrops/.approaches/introduction.md | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/exercises/practice/raindrops/.approaches/introduction.md b/exercises/practice/raindrops/.approaches/introduction.md index 48b7d6b07..a860542d5 100644 --- a/exercises/practice/raindrops/.approaches/introduction.md +++ b/exercises/practice/raindrops/.approaches/introduction.md @@ -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) { + switch ( valueOf(n).modPow( valueOf(12), valueOf(105) ).intValue() ) { + case ( 1): { return String.valueOf(n); } + case (36): { return "Pling"; } + case (85): { return "Plang"; } + case (91): { return "Plong"; } + case (15): { return "PlingPlang"; } + case (21): { return "PlingPlong"; } + case (70): { return "PlangPlong"; } + default : { return "PlingPlangPlong"; } // 0 + } + } + +} +``` + +For more information, check the [`Modular arithmetic` approach][approach-modular]. + ## Which approach to use? 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. [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-modular]: https://philcrissman.net/posts/eulers-fizzbuzz/ [jmh]: https://github.com/openjdk/jmh From c5802d2d3780a164461e3d3f86fa582e51f15ee0 Mon Sep 17 00:00:00 2001 From: habere-et-dispertire <18032974+habere-et-dispertire@users.noreply.github.com> Date: Tue, 23 Jun 2026 09:01:46 +0100 Subject: [PATCH 02/10] Refactor RaindropConverter default case --- exercises/practice/raindrops/.approaches/introduction.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/practice/raindrops/.approaches/introduction.md b/exercises/practice/raindrops/.approaches/introduction.md index a860542d5..ade18fe66 100644 --- a/exercises/practice/raindrops/.approaches/introduction.md +++ b/exercises/practice/raindrops/.approaches/introduction.md @@ -64,14 +64,14 @@ class RaindropConverter { String convert (int n) { switch ( valueOf(n).modPow( valueOf(12), valueOf(105) ).intValue() ) { - case ( 1): { return String.valueOf(n); } case (36): { return "Pling"; } case (85): { return "Plang"; } case (91): { return "Plong"; } case (15): { return "PlingPlang"; } case (21): { return "PlingPlong"; } case (70): { return "PlangPlong"; } - default : { return "PlingPlangPlong"; } // 0 + case ( 0): { return "PlingPlangPlong"; } + default : { return String.valueOf(n); } } } From 28466a0aa2983485ef957589293d141c4b480bd3 Mon Sep 17 00:00:00 2001 From: habere-et-dispertire <18032974+habere-et-dispertire@users.noreply.github.com> Date: Wed, 24 Jun 2026 09:01:32 +0100 Subject: [PATCH 03/10] Refactor with suggestions Refactor switch statement to use enhanced switch expression syntax. Note similarity to Fizz Buzz. --- .../raindrops/.approaches/introduction.md | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/exercises/practice/raindrops/.approaches/introduction.md b/exercises/practice/raindrops/.approaches/introduction.md index ade18fe66..278785921 100644 --- a/exercises/practice/raindrops/.approaches/introduction.md +++ b/exercises/practice/raindrops/.approaches/introduction.md @@ -57,28 +57,28 @@ For more information, check the [`Map` approach][approach-map]. ## Approach: `Modular Arithmetic` ```java -import java.math.BigInteger; +import java.math.BigInteger; import static java.math.BigInteger.valueOf; class RaindropConverter { String convert (int n) { - switch ( valueOf(n).modPow( valueOf(12), valueOf(105) ).intValue() ) { - case (36): { return "Pling"; } - case (85): { return "Plang"; } - case (91): { return "Plong"; } - case (15): { return "PlingPlang"; } - case (21): { return "PlingPlong"; } - case (70): { return "PlangPlong"; } - case ( 0): { return "PlingPlangPlong"; } - default : { return String.valueOf(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-modular]. +Fizz-Buzz is a related problem to raindrops. Both can be solved in the general case using Euler's totient theorem as long as all the sounds/factors are co-prime. For more information, check this article on a [`modular arithmetic` approach][approach-modular]. ## Which approach to use? From f4aedf7064b1dfcc895b897c5dcd18ee9fb6846e Mon Sep 17 00:00:00 2001 From: habere-et-dispertire <18032974+habere-et-dispertire@users.noreply.github.com> Date: Wed, 24 Jun 2026 20:19:53 +0100 Subject: [PATCH 04/10] Create content.md for modular arithmetic approach Add content for modular arithmetic approach in RaindropConverter. --- .../.approaches/modular-arithmetic/content.md | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 exercises/practice/raindrops/.approaches/modular-arithmetic/content.md diff --git a/exercises/practice/raindrops/.approaches/modular-arithmetic/content.md b/exercises/practice/raindrops/.approaches/modular-arithmetic/content.md new file mode 100644 index 000000000..58025ad7b --- /dev/null +++ b/exercises/practice/raindrops/.approaches/modular-arithmetic/content.md @@ -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/ From 92267d93fd1f5eb8a857a0ca297be96ebb06d2e8 Mon Sep 17 00:00:00 2001 From: habere-et-dispertire <18032974+habere-et-dispertire@users.noreply.github.com> Date: Wed, 24 Jun 2026 20:20:30 +0100 Subject: [PATCH 05/10] Add modular arithmetic conversion function --- .../.approaches/modular-arithmetic/snippet.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 exercises/practice/raindrops/.approaches/modular-arithmetic/snippet.txt diff --git a/exercises/practice/raindrops/.approaches/modular-arithmetic/snippet.txt b/exercises/practice/raindrops/.approaches/modular-arithmetic/snippet.txt new file mode 100644 index 000000000..7d6ba77f1 --- /dev/null +++ b/exercises/practice/raindrops/.approaches/modular-arithmetic/snippet.txt @@ -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 + }; +} From 565eaa2baa42a7c9626bf6ff9de5f44689df413f Mon Sep 17 00:00:00 2001 From: habere-et-dispertire <18032974+habere-et-dispertire@users.noreply.github.com> Date: Wed, 24 Jun 2026 20:21:10 +0100 Subject: [PATCH 06/10] Add modular arithmetic approach to config.json --- exercises/practice/raindrops/.approaches/config.json | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/exercises/practice/raindrops/.approaches/config.json b/exercises/practice/raindrops/.approaches/config.json index a74c828a5..f87b3a09d 100644 --- a/exercises/practice/raindrops/.approaches/config.json +++ b/exercises/practice/raindrops/.approaches/config.json @@ -22,6 +22,15 @@ "authors": [ "bobahop" ] + }, + { + "uuid": "d16d4056-2434-44ff-aae6-2bd57eb53dd7", + "slug": "modular-arithmetic", + "title": "Modular Arithmetic", + "blurb": "Use modular arithmetic to generalize.", + "authors": [ + "habere-et-dispertire" + ] } ] } From 66846bea6502da73c2352e22e2ce60d46bedbfd2 Mon Sep 17 00:00:00 2001 From: habere-et-dispertire <18032974+habere-et-dispertire@users.noreply.github.com> Date: Wed, 24 Jun 2026 20:25:55 +0100 Subject: [PATCH 07/10] Fix link to Modular Arithmetic approach Updated the reference link for the modular arithmetic approach in the introduction section. --- exercises/practice/raindrops/.approaches/introduction.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/practice/raindrops/.approaches/introduction.md b/exercises/practice/raindrops/.approaches/introduction.md index 278785921..bdaa32d91 100644 --- a/exercises/practice/raindrops/.approaches/introduction.md +++ b/exercises/practice/raindrops/.approaches/introduction.md @@ -78,7 +78,7 @@ class RaindropConverter { } ``` -Fizz-Buzz is a related problem to raindrops. Both can be solved in the general case using Euler's totient theorem as long as all the sounds/factors are co-prime. For more information, check this article on a [`modular arithmetic` approach][approach-modular]. +For more information, check the [Modular Arithmetic approach][approach-modulus]. ## Which approach to use? @@ -90,5 +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-modular]: https://philcrissman.net/posts/eulers-fizzbuzz/ +[approach-modulus]: https://exercism.org/tracks/java/exercises/raindrops/approaches/modulus [jmh]: https://github.com/openjdk/jmh From c5232dcfc4d262d3d8adc21e5b36731ff2468a5d Mon Sep 17 00:00:00 2001 From: habere-et-dispertire <18032974+habere-et-dispertire@users.noreply.github.com> Date: Wed, 24 Jun 2026 20:29:14 +0100 Subject: [PATCH 08/10] Move to modulus folder --- .../.approaches/{modular-arithmetic => modulus}/content.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename exercises/practice/raindrops/.approaches/{modular-arithmetic => modulus}/content.md (100%) diff --git a/exercises/practice/raindrops/.approaches/modular-arithmetic/content.md b/exercises/practice/raindrops/.approaches/modulus/content.md similarity index 100% rename from exercises/practice/raindrops/.approaches/modular-arithmetic/content.md rename to exercises/practice/raindrops/.approaches/modulus/content.md From 447856629838313ad7f58f86a987e70b4ff5104a Mon Sep 17 00:00:00 2001 From: habere-et-dispertire <18032974+habere-et-dispertire@users.noreply.github.com> Date: Wed, 24 Jun 2026 20:29:52 +0100 Subject: [PATCH 09/10] Move snippet.txt to modulus folder --- .../.approaches/{modular-arithmetic => modulus}/snippet.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename exercises/practice/raindrops/.approaches/{modular-arithmetic => modulus}/snippet.txt (100%) diff --git a/exercises/practice/raindrops/.approaches/modular-arithmetic/snippet.txt b/exercises/practice/raindrops/.approaches/modulus/snippet.txt similarity index 100% rename from exercises/practice/raindrops/.approaches/modular-arithmetic/snippet.txt rename to exercises/practice/raindrops/.approaches/modulus/snippet.txt From e321a48e4804868247c89eedf74d688b7641fe77 Mon Sep 17 00:00:00 2001 From: habere-et-dispertire <18032974+habere-et-dispertire@users.noreply.github.com> Date: Thu, 25 Jun 2026 16:04:58 +0100 Subject: [PATCH 10/10] Rename slug from 'modular-arithmetic' to 'modulus' --- exercises/practice/raindrops/.approaches/config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/practice/raindrops/.approaches/config.json b/exercises/practice/raindrops/.approaches/config.json index f87b3a09d..6e437adec 100644 --- a/exercises/practice/raindrops/.approaches/config.json +++ b/exercises/practice/raindrops/.approaches/config.json @@ -25,7 +25,7 @@ }, { "uuid": "d16d4056-2434-44ff-aae6-2bd57eb53dd7", - "slug": "modular-arithmetic", + "slug": "modulus", "title": "Modular Arithmetic", "blurb": "Use modular arithmetic to generalize.", "authors": [