{"id":18700901,"url":"https://github.com/rabestro/fizzbuzz-filter","last_synced_at":"2025-06-20T11:37:13.378Z","repository":{"id":203800809,"uuid":"689283428","full_name":"rabestro/fizzbuzz-filter","owner":"rabestro","description":"Small exercises for programming Stream API  predicates.","archived":false,"fork":false,"pushed_at":"2023-11-02T07:30:40.000Z","size":45,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-19T03:41:17.495Z","etag":null,"topics":["filtering","integer-sequences","integers","predicate-functions","predicate-logic","predicates","stream-api"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rabestro.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-09T10:25:13.000Z","updated_at":"2024-02-15T22:04:21.000Z","dependencies_parsed_at":"2024-11-07T11:43:40.300Z","dependency_job_id":"956ef9c4-f414-464d-a2ab-7769a83d3bdb","html_url":"https://github.com/rabestro/fizzbuzz-filter","commit_stats":null,"previous_names":["rabestro/fizzbuzz-filter"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/rabestro/fizzbuzz-filter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rabestro%2Ffizzbuzz-filter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rabestro%2Ffizzbuzz-filter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rabestro%2Ffizzbuzz-filter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rabestro%2Ffizzbuzz-filter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rabestro","download_url":"https://codeload.github.com/rabestro/fizzbuzz-filter/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rabestro%2Ffizzbuzz-filter/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260938249,"owners_count":23085852,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["filtering","integer-sequences","integers","predicate-functions","predicate-logic","predicates","stream-api"],"created_at":"2024-11-07T11:39:44.241Z","updated_at":"2025-06-20T11:37:08.365Z","avatar_url":"https://github.com/rabestro.png","language":"Java","readme":"# FizzBuzz and the art of filtering\n\n#### Stream API-based Tasks Inspired by the Classic Problem\n\nThe FizzBuzz problem is a classic coding challenge often used in programming interviews. It is usually presented as follows:\n\n\u003e Create a program that prints numbers from 1 to n. - If the number is divisible by 3, print ‘Fizz’; - If the number is divisible by 5, print ‘Buzz’; - If the number is divisible by both 3 and 5, print ‘FizzBuzz’.\n\u003e\n\nThis problem inspired me to work with Stream API using predefined `fizz` and `buzz` predicates. We aim to create various filters for a stream of integers using these predicates.\n\nWe will cover solutions for several basic tasks, while a more interesting and challenging one will be left for you to solve.\n\nFirst, let’s define the `fizz` and `buzz` predicates:\n\n```java\nIntPredicate fizz = i -\u003e i % 3 == 0;\nIntPredicate buzz = i -\u003e i % 5 == 0;\n```\n\nWe can create a stream of integers from 1 to 20 using the `IntStream::rangeClosed` method:\n\n```java\nvar numbers = IntStream.rangeClosed(1, 20);\n```\n\nThe goal for all the following tasks is to filter the integer stream by creating a `fizzBuzz` predicate based on the defined `fizz` and `buzz` predicates.\n\n### Task 1: Filter out numbers divisible by 3 and 5\n\nWe need to filter numbers that are exactly divisible by both 3 and 5. There are two ways to accomplish this. For instance, we can use the logical operator `\u0026\u0026`:\n\n```java\nIntPredicate fizzBuzz = i -\u003e fizz.test(i) \u0026\u0026 buzz.test(i);\n```\n\nHowever, a more convenient and preferable approach would be to use the `and` method from the `IntPredicate` interface:\n\n```java\nIntPredicate fizzBuzz = fizz.and(buzz);\n\nassertThat(numbers.filter(fizzBuzz))        \n\t\t.as(\"Numbers divisible by three and five\")        \n\t\t.containsExactly(15);\n```\n\n### Task 2: Filter out numbers divisible by 3 or 5\n\nThis solution is similar to the previous one but uses the `or` method instead of `and`:\n\n```java\nIntPredicate fizzBuzz = fizz.or(buzz);\n\nassertThat(numbers.filter(fizzBuzz))        \n\t\t.as(\"Numbers divisible by three or five\")        \n\t\t.containsExactly(3, 5, 6, 9, 10, 12, 15, 18, 20);\n```\n\n### Task 3: Filter out numbers not divisible by 3 and 5\n\nIn order to filter numbers that are not divisible by 3 or 5, we can use the `IntStream::negate` method. The solution looks like this:\n\n```java\nIntPredicate fizzBuzz = fizz.or(buzz).negate();\n\nassertThat(numbers.filter(fizzBuzz))        \n\t\t.as(\"Numbers not divisible by three or five\")        \n\t\t.containsExactly(1, 2, 4, 7, 8, 11, 13, 14, 16, 17, 19);\n```\n\n### Task 4: Filter out numbers Divisible by 3 or 5 but Not Both\n\nThe next task is to filter numbers that are divisible by either 3 or 5, but not both simultaneously. While it is possible to use all the methods from the `IntStream` interface, the optimal choice would be the exclusive OR (XOR):\n\n```java\nIntPredicate fizzBuzz = i -\u003e fizz.test(i) ^ buzz.test(i);\n\nassertThat(numbers.filter(fizzBuzz))        \n\t\t.as(\"Numbers divisible by either three or five\")        \n\t\t.containsExactly(3, 5, 6, 9, 10, 12, 18, 20);\n```\n\n### Task 5: Filter out numbers down to a number divisible by 3 and 5\n\nThis problem is very similar to the first one. However, our task is now to filter the numbers down to a divisible number by 3 and 5. We should stop processing numbers as soon as we come across such a number.\n\nWe define the predicate fizzBuzz precisely the same way as in the first problem. However, we use the `takeWhile` method instead of `filter`.\n\n```java\nvar fizzBuzz = fizz.and(buzz);\n\nvar result = numbers.takeWhile(fizzBuzz.negate());\n\nassertThat(result)\n\t\t.as(\"Numbers down to a number divisible by three and five\")\n\t\t.containsExactly(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);\n```\n\n### Task 6: Filtering Numbers out to a number divisible by 3 and 5\n\nThis is the opposite task to the previous one. We must throw out all the numbers up to the divisible number by three and five. All we need to solve this problem is to replace the `takeWhile` method with the `dropWhile` method.\n\n```java\nvar fizzBuzz = fizz.and(buzz);\n\nvar result = numbers.dropWhile(fizzBuzz.negate());\n\nassertThat(result)\n\t\t.as(\"Numbers after a number divisible by three and five\")\n\t\t.containsExactly(15, 16, 17, 18, 19, 20);\n```\n\n### Bonus Task: FizzBuzz as a Flip-Flop predicate\n\nProgramming languages like Ruby or Raku have a [flip-flop operator](https://en.wikipedia.org/wiki/Flip-flop_(programming)), which is not available in Java by default. However, we can create it from scratch.\n\nAs a final task, I invite you to test your predicate-building skills. Create a method that takes two predicates, `fizz` and `buzz` as input and returns a flip-flop predicate. This predicate must filter down a series of numbers, starting with a number satisfying the predicate `fizz` and ending with a number satisfying the predicate `buzz`. The method signature looks like this:\n\n```java\nIntPredicate flipFlop(IntPredicate fizz, IntPredicate buzz) {\n\t\t// TODO: Define the predicate\n}\n```\n\nTo define the flip-flop predicate, we call the method as follows.\n\n```java\nvar fizzBuzz = flipFlop(fizz, buzz);\n\nassertThat(numbers.filter(fizzBuzz))\n        .as(\"Numbers between numbers divisible by three and by five\")\n        .containsExactly(3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 18, 19, 20);\n```\n\nTo demonstrate the operation of this predicate, I enclosed the number sequences in square brackets.\n\n```\n1, 2, [3, 4, 5], [6, 7, 8, 9, 10], 11, [12, 13, 14, 15], 16, 17, [18, 19, 20]\n```\n\nWe get a completely different sequence if we swap the predicates `fizz` and `buzz`.\n\n```java\nIntPredicate buzzFizz = flipFlop(buzz, fizz);\n\nassertThat(numbers.filter(buzzFizz))\n\t\t.as(\"Numbers between numbers divisible by five and by three\")\n\t\t.containsExactly(5, 6, 10, 11, 12, 15, 20);\n```\n\nPlease note that in this case, the number 15 begins and ends the sequence, and the number 20 starts the series, but we don’t have its completion. At the same time, we ignore the number 3, which should end the sequence since our sequence has not yet begun.\n\n```\n1, 2, 3, 4, [5, 6], 7, 8, 9, [10, 11, 12], 13, 14, [15], 16, 17, 18, 19, [20\n```\n\nI hope you're willing to give the final problem a shot.\n\n### Conclusion\n\nThe topic of predicates is extensive, and covering all the issues in a tiny article is impossible. Nevertheless, I wanted to show how many possibilities we have, even limited to integer predicates and elementary initial data.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frabestro%2Ffizzbuzz-filter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frabestro%2Ffizzbuzz-filter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frabestro%2Ffizzbuzz-filter/lists"}