Last active
February 11, 2025 14:47
-
-
Save mazurkin/ad34b41a534dbcc975669116a00be366 to your computer and use it in GitHub Desktop.
FizzBuzz made with Java exceptions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package fizzbuzz; | |
package com.pulsepoint.datascience.avails; | |
import java.io.EOFException; | |
import java.io.FileNotFoundException; | |
import java.io.IOException; | |
import java.math.BigInteger; | |
import java.util.ArrayList; | |
import java.util.Arrays; | |
import java.util.List; | |
import java.util.concurrent.CompletableFuture; | |
import java.util.concurrent.ExecutorService; | |
import java.util.concurrent.Executors; | |
import java.util.concurrent.ThreadFactory; | |
import java.util.concurrent.ThreadLocalRandom; | |
import java.util.concurrent.TimeUnit; | |
import java.util.concurrent.TimeoutException; | |
import java.util.concurrent.atomic.LongAdder; | |
import java.util.function.Function; | |
public class FizzBuzz { | |
private static final ThreadFactory DAEMON_FACTORY = r -> { | |
Thread thread = new Thread(r); | |
thread.setDaemon(true); | |
thread.setName("FizzBuzz"); | |
return thread; | |
}; | |
public static void main(String[] arguments) throws Exception { | |
ExecutorService executor = Executors.newFixedThreadPool(2, DAEMON_FACTORY); | |
executor.submit(FizzBuzz::process); | |
executor.shutdown(); | |
if (!executor.awaitTermination(3, TimeUnit.SECONDS)) { | |
throw new TimeoutException("For some unknown reason the fizzbuzz algorithm has never finished"); | |
} | |
} | |
private static void process() { | |
LongAdder adder = new LongAdder(); | |
while (true) { | |
try { | |
fizzbuzz(adder); | |
} catch (IOException e) { | |
Arrays.stream(e.getSuppressed()) | |
.map(Throwable::getMessage) | |
.forEach(System.out::println); | |
System.out.println(e.getMessage()); | |
} | |
} | |
} | |
private static void fizzbuzz(LongAdder adder) throws IOException { | |
List<Exception> suppressed = new ArrayList<>(); | |
for (int i = 1; true; i++) { | |
adder.increment(); | |
try { | |
fizzbuzz(new BigInteger(adder.toString())); | |
Thread.sleep(0, 1); | |
CompletableFuture<Boolean> future = fizz(adder); | |
CompletableFuture.allOf(future).join(); | |
buzz(adder); | |
job(adder.longValue()); | |
} catch (InterruptedException e) { | |
break; | |
} catch (Exception e) { | |
suppressed.add(e); | |
} | |
} | |
IOException e = new FileNotFoundException("fizzbuzz"); | |
suppressed.forEach(e::addSuppressed); | |
throw e; | |
} | |
private static void fizzbuzz(BigInteger trial) throws InterruptedException { | |
try { | |
fizz(trial).join(); | |
} catch (Exception e1) { | |
try { | |
buzz(trial); | |
} catch (Exception e2) { | |
Thread.currentThread().interrupt(); | |
} | |
} | |
} | |
private static CompletableFuture<Boolean> fizz(Number trial) { | |
if (trial.longValue() % 3 == 0) { | |
panic(EOFException::new, "fizz"); | |
return CompletableFuture.completedFuture(false); | |
} else { | |
return CompletableFuture.completedFuture(true); | |
} | |
} | |
private static void buzz(Number trial) { | |
String token = trial.toString(); | |
if (token.charAt(token.length() - 1) == '5' || token.charAt(token.length() - 1) == '0') { | |
throw new ArrayIndexOutOfBoundsException("buzz"); | |
} | |
} | |
private static void job(long trial) { | |
if (ThreadLocalRandom.current().nextDouble() < 1.0) { | |
throw new IllegalArgumentException(Long.toString(trial)); | |
} | |
} | |
private static <E extends Exception> void panic(Function<String, ? extends Exception> mapper, String msg) throws E { | |
throw (E) mapper.apply(msg); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment