Package

Source Code of Fraction

/*
* Shared code for solutions to Project Euler problems
* By Nayuki Minase
*
* http://nayuki.eigenstate.org/page/project-euler-solutions
* https://github.com/nayuki/Project-Euler-solutions
*/

import java.math.BigInteger;


final class Library {
 
  // Returns the reverse of the given string.
  public static String reverse(String s) {
    return new StringBuilder(s).reverse().toString();
  }
 
 
  // Tests whether the given string is a palindrome.
  public static boolean isPalindrome(String s) {
    return s.equals(reverse(s));
  }
 
 
  // Tests whether the given integer is a palindrome in decimal.
  public static boolean isPalindrome(int x) {
    return isPalindrome(Integer.toString(x));
  }
 
 
  // Returns floor(sqrt(x)).
  public static int sqrt(int x) {
    if (x < 0)
      throw new IllegalArgumentException("Square root of negative number");
    int y = 0;
    for (int i = 32768; i != 0; i >>>= 1) {
      y |= i;
      if (y > 46340 || y * y > x)
        y ^= i;
    }
    return y;
  }
 
 
  // Returns floor(sqrt(x)).
  public static long sqrt(long x) {
    if (x < 0)
      throw new IllegalArgumentException("Square root of negative number");
    long y = 0;
    for (long i = 1L << 31; i != 0; i >>>= 1) {
      y |= i;
      if (y > 3037000499L || y * y > x)
        y ^= i;
    }
    return y;
  }
 
 
  // Tests whether x is a perfect square.
  public static boolean isSquare(int x) {
    if (x < 0)
      return false;
    int sqrt = Library.sqrt(x);
    return sqrt * sqrt == x;
  }
 
 
  // Returns x to the power of y.
  public static int pow(int x, int y) {
    if (y < 0)
      throw new IllegalArgumentException("Negative exponent");
    int z = 1;
    for (int i = 0; i < y; i++) {
      if (Integer.MAX_VALUE / z < x)
        throw new ArithmeticException("Overflow");
      z *= x;
    }
    return z;
  }
 
 
  // Returns x^y mod m.
  public static int powMod(int x, int y, int m) {
    if (x < 0)
      throw new IllegalArgumentException("Negative base not handled");
    if (y < 0)
      throw new IllegalArgumentException("Reciprocal not handled");
    if (m <= 0)
      throw new IllegalArgumentException("Invalid modulus");
    if (m == 1)
      return 0;
   
    // Exponentiation by squaring
    int z = 1;
    while (y != 0) {
      if ((y & 1) != 0)
        z = (int)((long)z * x % m);
      x = (int)((long)x * x % m);
      y >>>= 1;
    }
    return z;
  }
 
 
  // Returns x^-1 mod m. Note that x * x^-1 mod m = x^-1 * x mod m = 1.
  public static int reciprocalMod(int x, int m) {
    if (m < 0 || x < 0 || x >= m)
      throw new IllegalArgumentException();
   
    // Based on a simplification of the extended Euclidean algorithm
    int y = x;
    x = m;
    int a = 0;
    int b = 1;
    while (y != 0) {
      int z = x % y;
      int c = a - x / y * b;
      x = y;
      y = z;
      a = b;
      b = c;
    }
    if (x == 1)
      return (a + m) % m;
    else
      throw new IllegalArgumentException("Reciprocal does not exist");
  }
 
 
  // Returns n!.
  public static BigInteger factorial(int n) {
    if (n < 0)
      throw new IllegalArgumentException("Factorial of negative number");
    BigInteger prod = BigInteger.ONE;
    for (int i = 2; i <= n; i++)
      prod = prod.multiply(BigInteger.valueOf(i));
    return prod;
  }
 
 
  // Returns n choose k.
  public static BigInteger binomial(int n, int k) {
    return factorial(n).divide(factorial(n - k).multiply(factorial(k)));
  }
 
 
  // Returns the largest non-negative integer that divides both x and y.
  public static int gcd(int x, int y) {
    while (y != 0) {
      int z = x % y;
      x = y;
      y = z;
    }
    return x;
  }
 
 
  // Tests whether the given integer is prime.
  public static boolean isPrime(int x) {
    if (x < 0)
      throw new IllegalArgumentException("Negative number");
    if (x == 0 || x == 1)
      return false;
    else if (x == 2)
      return true;
    else {
      if (x % 2 == 0)
        return false;
      for (int i = 3, end = sqrt(x); i <= end; i += 2) {
        if (x % i == 0)
          return false;
      }
      return true;
    }
  }
 
 
  // Returns a Boolean array 'isPrime' where isPrime[i] indicates whether i is prime, for 0 <= i <= n.
  // For a large batch of queries, this is faster than calling isPrime() for each integer.
  // For example: listPrimality(100) = {false, false, true, true, false, true, false, true, false, false, ...}.
  public static boolean[] listPrimality(int n) {
    if (n < 0)
      throw new IllegalArgumentException("Negative size");
    boolean[] prime = new boolean[n + 1];
    if (n >= 2)
      prime[2] = true;
    for (int i = 3; i <= n; i += 2)
      prime[i] = true;
    // Sieve of Eratosthenes
    for (int i = 3, end = sqrt(n); i <= end; i += 2) {
      if (prime[i]) {
        for (int j = i * i; j <= n; j += i << 1)
          prime[j] = false;
      }
    }
    return prime;
  }
 
 
  // Returns all the prime numbers less than or equal to n, in ascending order.
  // For example: listPrimes(100) = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, ..., 83, 89, 97}.
  public static int[] listPrimes(int n) {
    if (n < 0)
      throw new IllegalArgumentException("Negative size");
    boolean[] isPrime = listPrimality(n);
    int count = 0;
    for (boolean b : isPrime) {
      if (b)
        count++;
    }
    int[] primes = new int[count];
    for (int i = 0, j = 0; i < isPrime.length; i++) {
      if (isPrime[i]) {
        primes[j] = i;
        j++;
      }
    }
    return primes;
  }
 
 
  // Returns an array spf where spf[k] is the smallest prime factor of k, valid for 0 <= k <= n.
  // For example: listSmallestPrimeFactors(10) = {0, 0, 2, 3, 2, 5, 2, 7, 2, 3, 2}.
  public static int[] listSmallestPrimeFactors(int n) {
    int[] result = new int[n + 1];
    for (int i = 2; i < result.length; i++) {
      if (result[i] == 0) {
        result[i] = i;
        if ((long)i * i <= n) {
          for (int j = i * i; j <= n; j += i) {
            if (result[j] == 0)
              result[j] = i;
          }
        }
      }
    }
    return result;
  }
 
 
  // Returns the number of integers in the range [1, n] that are coprime with n.
  // For example, totient(12) = 4 because these integers are coprime with 12: 1, 5, 7, 11.
  public static int totient(int n) {
    if (n <= 0)
      throw new IllegalArgumentException("Totient of non-positive integer");
    int p = 1;
    for (int i = 2, end = Library.sqrt(n); i <= end; i++) {  // Trial division
      if (n % i == 0) {  // Found a factor
        p *= i - 1;
        n /= i;
        while (n % i == 0) {
          p *= i;
          n /= i;
        }
        end = Library.sqrt(n);
      }
    }
    if (n != 1)
      p *= n - 1;
    return p;
  }
 
 
  // Returns an array 'totients' where totients[i] == totient(i), for 0 <= i <= n.
  // For a large batch of queries, this is faster than calling totient() for each integer.
  public static int[] listTotients(int n) {
    if (n < 0)
      throw new IllegalArgumentException("Negative size");
    int[] totients = new int[n + 1];
    for (int i = 0; i <= n; i++)
      totients[i] = i;
   
    for (int i = 2; i <= n; i++) {
      if (totients[i] == i) {  // i is prime
        for (int j = i; j <= n; j += i)
          totients[j] = totients[j] / i * (i - 1);
      }
    }
    return totients;
  }
 
 
  // Returns the same result as x.multiply(y), but is faster for large integers.
  public static BigInteger multiply(BigInteger x, BigInteger y) {
    final int CUTOFF = 1536;
    if (x.bitLength() <= CUTOFF || y.bitLength() <= CUTOFF) {  // Base case
      return x.multiply(y);
     
    } else // Karatsuba fast multiplication
      int n = Math.max(x.bitLength(), y.bitLength());
      int half = (n + 32) / 64 * 32;
      BigInteger mask = BigInteger.ONE.shiftLeft(half).subtract(BigInteger.ONE);
      BigInteger xlow = x.and(mask);
      BigInteger ylow = y.and(mask);
      BigInteger xhigh = x.shiftRight(half);
      BigInteger yhigh = y.shiftRight(half);
     
      BigInteger a = multiply(xhigh, yhigh);
      BigInteger b = multiply(xlow.add(xhigh), ylow.add(yhigh));
      BigInteger c = multiply(xlow, ylow);
      BigInteger d = b.subtract(a).subtract(c);
      return a.shiftLeft(half).add(d).shiftLeft(half).add(c);
    }
  }
 
 
  // Advances the given sequence to the next permutation and returns whether a permutation was performed.
  // If no permutation was performed, then the input state was already the last possible permutation (a non-ascending sequence).
  // For example:
  // - nextPermutation({0,0,1}) changes the argument array to {0,1,0} and returns true.
  // - nextPermutation({1,0,0}) leaves the argument array unchanged and returns false.
  public static boolean nextPermutation(int[] a) {
    int i, n = a.length;
    for (i = n - 2; ; i--) {
      if (i < 0)
        return false;
      if (a[i] < a[i + 1])
        break;
    }
    for (int j = 1; i + j < n - j; j++) {
      int tp = a[i + j];
      a[i + j] = a[n - j];
      a[n - j] = tp;
    }
    int j;
    for (j = i + 1; a[j] <= a[i]; j++);
    int tp = a[i];
    a[i] = a[j];
    a[j] = tp;
    return true;
  }
 
}



// Immutable unlimited precision fraction
final class Fraction {
 
  public final BigInteger numerator;    // Always coprime with denominator
  public final BigInteger denominator;  // Always positive
 
 
  public Fraction(BigInteger numer, BigInteger denom) {
    if (denom.signum() == 0)
      throw new ArithmeticException("Division by zero");
   
    // Reduce to canonical form
    if (denom.signum() == -1) {
      numer = numer.negate();
      denom = denom.negate();
    }
    BigInteger gcd = numer.gcd(denom);
    if (!gcd.equals(BigInteger.ONE)) {
      numer = numer.divide(gcd);
      denom = denom.divide(gcd);
    }
   
    numerator = numer;
    denominator = denom;
  }
 
 
  public Fraction add(Fraction other) {
    return new Fraction(numerator.multiply(other.denominator).add(other.numerator.multiply(denominator)), denominator.multiply(other.denominator));
  }
 
 
  public Fraction subtract(Fraction other) {
    return new Fraction(numerator.multiply(other.denominator).subtract(other.numerator.multiply(denominator)), denominator.multiply(other.denominator));
  }
 
 
  public Fraction multiply(Fraction other) {
    return new Fraction(numerator.multiply(other.numerator), denominator.multiply(other.denominator));
  }
 
 
  public Fraction divide(Fraction other) {
    return new Fraction(numerator.multiply(other.denominator), denominator.multiply(other.numerator));
  }
 
 
  public boolean equals(Object obj) {
    if (obj instanceof Fraction) {
      Fraction other = (Fraction)obj;
      return numerator.equals(other.numerator) && denominator.equals(other.denominator);
    } else
      return false;
  }
 
 
  public int hashCode() {
    return numerator.hashCode() + denominator.hashCode();
  }
 
 
  public String toString() {
    return numerator + "/" + denominator;
  }
 
}
TOP

Related Classes of Fraction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.