5 Commits
p312 ... p323

Author SHA1 Message Date
56df7a6c40 add p323 solution 2025-04-21 12:31:47 -07:00
e05095f6bf add 323 scratch 2025-04-21 12:31:38 -07:00
b1d9a282e7 Merge branch 'p29'
* p29:
  add p29 solution
2025-04-21 11:56:49 -07:00
89c6cbe9b8 add p29 solution 2025-04-21 11:56:24 -07:00
f4174b8898 Merge branch 'p312'
* p312:
  add final version of problem 312 solution
  312 solved
  add 312 versions
2025-04-20 14:16:06 -07:00
3 changed files with 190 additions and 2 deletions

View File

@@ -1,4 +1,4 @@
iimport java.math.BigInteger;
import java.math.BigInteger;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit; // Optional: for more readable time output
@@ -8,7 +8,7 @@ import java.util.concurrent.TimeUnit; // Optional: for more readable time output
* for 2 <= a <= 100 and 2 <= b <= 100.
* This implementation runs on a single core/thread.
*/
public class DistinctPowers {
public class Problem029 {
// Define the inclusive range for base 'a'
private static final int MIN_A = 2;

94
java/Problem323.java Normal file
View File

@@ -0,0 +1,94 @@
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
/**
* Calculates the expected number of steps N until a 32-bit integer,
* initially zero, becomes all ones (2^32 - 1) by repeatedly performing
* a bitwise OR with a sequence of random 32-bit integers.
*
* The expected value is calculated using the formula:
* E[N] = sum_{j=0 to infinity} (1 - (1 - (1/2)^j)^M)
* where M = 32.
*
* This program approximates the sum by summing a fixed number of terms
* using high-precision BigDecimal arithmetic.
*/
public class Problem323 {
public static void main(String[] args) {
// --- Configuration ---
final int M = 32; // Exponent (number of bits)
// Number of terms in the sum (j=0 to ITERATIONS-1).
// Chosen based on analysis to provide sufficient precision.
final int ITERATIONS = 70;
// Precision for BigDecimal calculations (number of significant digits)
// Chosen to be >> 10
final int PRECISION = 50;
// Final scale for the result (decimal places)
final int FINAL_SCALE = 10;
// Rounding mode for calculations and final result
final RoundingMode ROUNDING_MODE = RoundingMode.HALF_UP;
// --- Setup High Precision ---
// MathContext defines precision and rounding rules for operations
MathContext mc = new MathContext(PRECISION, ROUNDING_MODE);
// BigDecimal constants for efficiency and clarity
final BigDecimal ZERO = BigDecimal.ZERO;
final BigDecimal ONE = BigDecimal.ONE;
final BigDecimal TWO = new BigDecimal("2");
// --- Calculation ---
BigDecimal expectedValueSum = ZERO;
// Initialize halfPowerJ to (1/2)^0 = 1
BigDecimal halfPowerJ = ONE;
System.out.println("Calculating E[N] using " + ITERATIONS + " terms with precision " + PRECISION + "...");
for (int j = 0; j < ITERATIONS; j++) {
// Calculate the term Tj = 1 - (1 - (1/2)^j)^M
// 1. Calculate base: (1 - (1/2)^j)
BigDecimal termBase = ONE.subtract(halfPowerJ);
// 2. Calculate base^M: (1 - (1/2)^j)^M
// Use pow(int n, MathContext mc) for controlled precision during exponentiation
BigDecimal termBasePowM = termBase.pow(M, mc);
// 3. Calculate Tj = 1 - base^M
BigDecimal termTj = ONE.subtract(termBasePowM);
// 4. Add Tj to the running sum
expectedValueSum = expectedValueSum.add(termTj, mc);
// 5. Prepare (1/2)^j for the *next* iteration (j+1)
// (1/2)^(j+1) = (1/2)^j / 2
halfPowerJ = halfPowerJ.divide(TWO, mc);
// Optional: Print progress every 10 iterations
// if ((j + 1) % 10 == 0) {
// System.out.println("j=" + j + ", Current Sum=" + expectedValueSum.round(new MathContext(FINAL_SCALE + 2)));
// }
}
// System.out.println("Calculation complete.");
// --- Round final result ---
BigDecimal finalResult = expectedValueSum.setScale(FINAL_SCALE, ROUNDING_MODE);
// --- Output ---
System.out.println("\nCalculated Expected Value E[N]:");
// Use toPlainString() to avoid potential scientific notation
System.out.println(finalResult.toPlainString());
// --- Sanity Check (Approximate value based on theoretical analysis) ---
double log2_M = Math.log(M) / Math.log(2.0);
double gamma = 0.57721566490153286060; // Euler-Mascheroni constant
double ln2 = Math.log(2.0);
double approxExpectedValue = log2_M + gamma / ln2 + 0.5;
System.out.println("\nApproximate theoretical value (for comparison): " + String.format("%.10f", approxExpectedValue));
}
}

View File

@@ -0,0 +1,94 @@
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
/**
* Calculates the expected number of steps N until a 32-bit integer,
* initially zero, becomes all ones (2^32 - 1) by repeatedly performing
* a bitwise OR with a sequence of random 32-bit integers.
*
* The expected value is calculated using the formula:
* E[N] = sum_{j=0 to infinity} (1 - (1 - (1/2)^j)^M)
* where M = 32.
*
* This program approximates the sum by summing a fixed number of terms
* using high-precision BigDecimal arithmetic.
*/
public class ExpectedValueN {
public static void main(String[] args) {
// --- Configuration ---
final int M = 32; // Exponent (number of bits)
// Number of terms in the sum (j=0 to ITERATIONS-1).
// Chosen based on analysis to provide sufficient precision.
final int ITERATIONS = 70;
// Precision for BigDecimal calculations (number of significant digits)
// Chosen to be >> 10
final int PRECISION = 50;
// Final scale for the result (decimal places)
final int FINAL_SCALE = 10;
// Rounding mode for calculations and final result
final RoundingMode ROUNDING_MODE = RoundingMode.HALF_UP;
// --- Setup High Precision ---
// MathContext defines precision and rounding rules for operations
MathContext mc = new MathContext(PRECISION, ROUNDING_MODE);
// BigDecimal constants for efficiency and clarity
final BigDecimal ZERO = BigDecimal.ZERO;
final BigDecimal ONE = BigDecimal.ONE;
final BigDecimal TWO = new BigDecimal("2");
// --- Calculation ---
BigDecimal expectedValueSum = ZERO;
// Initialize halfPowerJ to (1/2)^0 = 1
BigDecimal halfPowerJ = ONE;
System.out.println("Calculating E[N] using " + ITERATIONS + " terms with precision " + PRECISION + "...");
for (int j = 0; j < ITERATIONS; j++) {
// Calculate the term Tj = 1 - (1 - (1/2)^j)^M
// 1. Calculate base: (1 - (1/2)^j)
BigDecimal termBase = ONE.subtract(halfPowerJ);
// 2. Calculate base^M: (1 - (1/2)^j)^M
// Use pow(int n, MathContext mc) for controlled precision during exponentiation
BigDecimal termBasePowM = termBase.pow(M, mc);
// 3. Calculate Tj = 1 - base^M
BigDecimal termTj = ONE.subtract(termBasePowM);
// 4. Add Tj to the running sum
expectedValueSum = expectedValueSum.add(termTj, mc);
// 5. Prepare (1/2)^j for the *next* iteration (j+1)
// (1/2)^(j+1) = (1/2)^j / 2
halfPowerJ = halfPowerJ.divide(TWO, mc);
// Optional: Print progress every 10 iterations
// if ((j + 1) % 10 == 0) {
// System.out.println("j=" + j + ", Current Sum=" + expectedValueSum.round(new MathContext(FINAL_SCALE + 2)));
// }
}
// System.out.println("Calculation complete.");
// --- Round final result ---
BigDecimal finalResult = expectedValueSum.setScale(FINAL_SCALE, ROUNDING_MODE);
// --- Output ---
System.out.println("\nCalculated Expected Value E[N]:");
// Use toPlainString() to avoid potential scientific notation
System.out.println(finalResult.toPlainString());
// --- Sanity Check (Approximate value based on theoretical analysis) ---
double log2_M = Math.log(M) / Math.log(2.0);
double gamma = 0.57721566490153286060; // Euler-Mascheroni constant
double ln2 = Math.log(2.0);
double approxExpectedValue = log2_M + gamma / ln2 + 0.5;
System.out.println("\nApproximate theoretical value (for comparison): " + String.format("%.10f", approxExpectedValue));
}
}