Skip to content

Instantly share code, notes, and snippets.

@FerusGrim
Created May 4, 2019 16:37
Show Gist options
  • Save FerusGrim/9a2ca09090916e11224ef5741e241a03 to your computer and use it in GitHub Desktop.
Save FerusGrim/9a2ca09090916e11224ef5741e241a03 to your computer and use it in GitHub Desktop.
package xyz.ferus.thf;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.DecimalFormat;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ThanosHatesFemales {
private static final long PROGRAM_START = System.currentTimeMillis();
private static final Path RESULTS = Paths.get("").resolve("results");
private static final DecimalFormat FORMAT = new DecimalFormat("#0.000");
private static final long GENDER_MAX = 3_500_000_000L;
public static void main(String[] args) {
final int processors = Runtime.getRuntime().availableProcessors() - 1; // Save one for reporting progress.
final Set<SnapThread> threads = getSnapThreads(processors);
final ExecutorService service = Executors.newFixedThreadPool(processors);
threads.forEach(service::submit);
while (threads.stream().anyMatch(SnapThread::isNotComplete)) {
final long processed = threads.stream().mapToLong(SnapThread::getNumberProcessed).sum();
System.out.println("Processed: " + processed + " (" + FORMAT.format(((double) processed / (double) GENDER_MAX * 100D)) + "%) " + getElapsedTime());
try {
Thread.sleep(15_000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
BigDecimal probability = null;
for (final SnapThread thread : threads) {
probability = createProbability(probability, thread.getProbability());
}
reportProbability(probability);
try {
System.out.println("Attempting to shutdown ExecutorService...");
service.shutdown();
service.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
System.err.println("Interrupted Tasks. =/");
} finally {
if (!service.isTerminated()) {
System.err.println("Forcefully cancelling non-finished tasks...");
}
service.shutdownNow();
System.out.println("ExecutorService shutdown finished!");
}
}
private static String getElapsedTime() {
long milliseconds = System.currentTimeMillis() - PROGRAM_START;
long seconds = milliseconds / 1000;
long minutes = seconds / 60;
final long hours = minutes / 60;
if (hours > 0) {
minutes = milliseconds % 60;
seconds = seconds % 60 % 60;
} else if (minutes > 0) {
seconds = seconds % 60;
}
return "("
+ (hours > 0 ? hours + "h " : "")
+ (hours > 0 || minutes > 0 ? minutes + "m " : "")
+ seconds + "s)";
}
private static Set<SnapThread> getSnapThreads(int processors) {
final Set<SnapThread> threads = new HashSet<>();
final long chunkSize = GENDER_MAX / processors;
for (int i = 0; i < processors; i++) {
threads.add(new SnapThread(chunkSize * i + chunkSize, chunkSize * i + 1));
}
return threads;
}
private static BigDecimal createProbability(BigDecimal current, BigDecimal factor) {
return current == null ? factor : current.multiply(factor);
}
private static void reportProbability(BigDecimal probability) {
System.out.println("Reporting probability...");
final Path plain = RESULTS.resolve("plain.bd");
final Path engineering = RESULTS.resolve("engineering.bd");
try {
if (!Files.exists(plain)) {
Files.createDirectories(plain.getParent());
Files.createFile(plain);
}
if (!Files.exists(engineering)) {
Files.createDirectories(engineering.getParent());
Files.createFile(engineering);
}
} catch (IOException e) {
e.printStackTrace();
}
try (PrintStream out = new PrintStream(new FileOutputStream(plain.toFile()))) {
out.print(probability.toPlainString());
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try (PrintStream out = new PrintStream(new FileOutputStream(engineering.toFile()))) {
out.print(probability.toEngineeringString());
} catch (FileNotFoundException e) {
e.printStackTrace();
}
System.out.println("Done!");
System.out.println("Plain Results: " + plain.toString());
System.out.println("Engineering Results: " + engineering.toString());
}
public static class SnapThread extends Thread {
private final long start;
private final long end;
private long current;
private BigDecimal probability;
private boolean completed = false;
SnapThread(long start, long end) {
this.start = start;
this.end = end;
this.current = this.start;
this.probability = null;
}
BigDecimal getProbability() {
return this.probability;
}
long getNumberProcessed() {
return this.start - this.current;
}
boolean isNotComplete() {
return !this.completed;
}
@Override
public void run() {
while (this.current >= this.end) {
probability = probability == null ? newProbability(this.current) : probability.multiply(newProbability(this.current));
this.current--;
}
this.completed = true;
}
private static BigDecimal newProbability(double current) {
return BigDecimal.valueOf(current / (current + ThanosHatesFemales.GENDER_MAX));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment