Created
May 4, 2019 16:37
-
-
Save FerusGrim/9a2ca09090916e11224ef5741e241a03 to your computer and use it in GitHub Desktop.
This file contains 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 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