Wednesday, January 4, 2017

Project Euler #59 XOR decryption - Java

import java.util.Scanner;

public class Solution {

    private static boolean[] FIRST = new boolean['z' - 'a' + 1];
    private static boolean[] SECOND = new boolean['z' - 'a' + 1];
    private static boolean[] THIRD = new boolean['z' - 'a' + 1];

    public static void main(String[] args) {
        for (int i = 0; i < 'z' - 'a' + 1; i++) {
            FIRST[i] = true;
            SECOND[i] = true;
            THIRD[i] = true;
        }
        Scanner scanner = new Scanner(System.in);
        int N = scanner.nextInt();
        for (int i = 0; i < N / 3; i++) {
            int i1 = scanner.nextInt();
            for (char c = 'a'; c <= 'z'; c++) {
                if (!FIRST[c - 'a']) {
                    continue;
                }
                if (!isValid(c, i1)) {
                    FIRST[c - 'a'] = false;
                }
            }
            int i2 = scanner.nextInt();
            for (char c = 'a'; c <= 'z'; c++) {
                if (!SECOND[c - 'a']) {
                    continue;
                }
                if (!isValid(c, i2)) {
                    SECOND[c - 'a'] = false;
                }
            }
            int i3 = scanner.nextInt();
            for (char c = 'a'; c <= 'z'; c++) {
                if (!THIRD[c - 'a']) {
                    continue;
                }
                if (!isValid(c, i3)) {
                    THIRD[c - 'a'] = false;
                }
            }
        }
        scanner.close();
        StringBuilder sb = new StringBuilder();
        for (char c = 'a'; c <= 'z'; c++) {
            if (FIRST[c - 'a']) {
                sb.append(c);
            }
        }
        for (char c = 'a'; c <= 'z'; c++) {
            if (SECOND[c - 'a']) {
                sb.append(c);
            }
        }
        for (char c = 'a'; c <= 'z'; c++) {
            if (THIRD[c - 'a']) {
                sb.append(c);
            }
        }
        System.out.println(sb.toString());
    }

    private static boolean isValid(char c, int i) {
        int xor = (c ^ i);
        if ((xor >= 'a' && xor <= 'z') || (xor >= 'A' && xor <= 'Z') || (xor >= '0' && xor <= '9')
                || (xor == '(' || xor == ')') || (xor == ';' || xor == ':') || (xor == ',' || xor == '.')
                || (xor == '\'' || xor == '?') || (xor == '-' || xor == '!' || xor == ' ')) {
            return true;
        }
        return false;
    }
}

Tuesday, January 3, 2017

Project Euler #58 Spiral primes - Java

import java.math.BigInteger;
import java.util.Scanner;

public class Solution {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        scanner.close();
        if (n < 8 || n > 60) {
            throw new IllegalArgumentException("Invalid percenrage");
        }
        getAnswer(n);
    }

    private static void getAnswer(int n) {
        long primeCount = 0;
        long totalCount = 1;
        long n1 = 1;
        long gap = 2;
        for (int shell = 1;; shell++) {
            // update total count
            totalCount += 4;
            // update primeCount
            for (int i = 0; i < 4; i++) {
                n1 += gap;
                if (isPrime(n1)) {
                    primeCount++;
                }
            }
            gap += 2;
            // System.out.println((double) primeCount / totalCount + " total:" + totalCount);
            double percentage = (primeCount * 100) / totalCount;
            if (percentage < n) {
                System.out.println(2 * shell + 1);
                return;
            }
        }
    }

    private static boolean isPrime(long n) {
        if (n <= 1 || n == 4) {
            return false;
        }
        if (n <= 3) {
            return true;
        }
        for (int i = 3; i <= Math.sqrt(n); i += 2) {
            if (n % i == 0) {
                return false;
            }
        }
        return true;
    }

    private static boolean isPrime(long n, int k) {
        if (n <= 1 || n == 4) {
            return false;
        }
        if (n <= 3) {
            return true;
        }
        long d = n - 1;
        while (d % 2 == 0) {
            d /= 2;
        }
        for (int i = 0; i < k; i++) {
            if (miillerTest(d, n) == false) {
                return false;
            }
        }
        return true;
    }

    private static boolean miillerTest(long dl, long n) {
        long al = (long) (2 + (Math.random() % (n - 4)));
        BigInteger a = BigInteger.valueOf(al);
        BigInteger nMinusOne = BigInteger.valueOf(n - 1);
        BigInteger x = a.modPow(BigInteger.valueOf(dl), BigInteger.valueOf(n));
        if (x.equals(BigInteger.ONE) || x.equals(nMinusOne)) {
            return true;
        }
        BigInteger d = BigInteger.valueOf(dl);
        while (!d.equals(nMinusOne)) {
            x = x.multiply(x);
            x = x.mod(BigInteger.valueOf(n));
            d = d.multiply(BigInteger.valueOf(2l));
            if (x.equals(BigInteger.ONE)) {
                return false;
            }
            if (x.equals(nMinusOne)) {
                return true;
            }
        }
        return false;
    }

}

Project Euler #57 Square root convergents - Java

Fast log10 calculation of BigInteger was borrowed from here
import java.math.BigInteger;
import java.util.Scanner;

public class Solution {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        scanner.close();
        getAnswer(n);
    }

    private static void getAnswer(int n) {
        BigInteger numerator = BigInteger.valueOf(3);
        BigInteger denominator = BigInteger.valueOf(2);
        for (int i = 0; i < n; i++) {
            // if (numerator.toString().length() > denominator.toString().length()) {
            if (log10(numerator) > log10(denominator)) {
                System.out.println((i + 1));
            }
            BigInteger newDenominator = numerator.add(denominator);
            BigInteger newNumerator = newDenominator.add(denominator);
            numerator = newNumerator;
            denominator = newDenominator;
        }
    }

    private static int log10(BigInteger huge) {
        int digits = 0;
        int bits = huge.bitLength();
        // Serious reductions.
        while (bits > 4) {
            // 4 > log[2](10) so we should not reduce it too far.
            int reduce = bits / 4;
            // Divide by 10^reduce
            huge = huge.divide(BigInteger.TEN.pow(reduce));
            // Removed that many decimal digits.
            digits += reduce;
            // Recalculate bitLength
            bits = huge.bitLength();
        }
        // Now 4 bits or less - add 1 if necessary.
        if (huge.intValue() > 9) {
            digits += 1;
        }
        return digits;
    }
}

Project Euler #56 Powerful digit sum - Java

import java.math.BigInteger;
import java.util.Scanner;

public class Solution {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        scanner.close();
        int ret = getAnswer(n);
        System.out.println(ret);
    }

    private static int getAnswer(int n) {
        int ret = Integer.MIN_VALUE;
        for (int i = n - 1; i >= 2; i--) {
            for (int j = n - 1; j >= 2; j--) {
                int base = i;
                BigInteger bi = BigInteger.valueOf(base);
                String str = bi.pow(j).toString();
                char[] cs = str.toCharArray();
                int count = 0;
                for (int k = 0; k < str.length(); k++) {
                    count += cs[k] - '0';
                }
                if (count > ret) {
                    ret = count;
                }
            }
        }
        return ret;
    }
}

Project Euler #55 Lychrel numbers - Java

import java.math.BigInteger;
import java.util.HashMap;
import java.util.Scanner;

public class Solution {

    public static void main(String[] args) {
        HashMap<BigInteger, Integer> answer = new HashMap<BigInteger, Integer>();
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        scanner.close();
        for (int i = 1; i <= n; i++) {
            BigInteger cur = BigInteger.valueOf(i);
            for (int j = 0; j < 60; j++) {
                if (isPanlindrome(cur)) {
                    if (answer.containsKey(cur)) {
                        int count = answer.get(cur);
                        answer.put(cur, count + 1);
                    } else {
                        answer.put(cur, 1);
                    }
                    break;
                }
                cur = cur.add(getReverse(cur));
            }
        }
        int max = Integer.MIN_VALUE;
        BigInteger maxi = BigInteger.ZERO;
        for (BigInteger bi : answer.keySet()) {
            int ans = answer.get(bi);
            if (ans > max) {
                max = ans;
                maxi = bi;
            }
        }
        System.out.println(maxi + " " + max);
    }

    private static BigInteger getReverse(BigInteger n) {
        String ns = String.valueOf(n);
        StringBuilder sb = new StringBuilder(ns);
        return new BigInteger(sb.reverse().toString());
    }

    private static boolean isPanlindrome(BigInteger n) {
        if (n.compareTo(BigInteger.TEN) < 0) {
            return true;
        }
        String ns = String.valueOf(n);
        char[] nsc = ns.toCharArray();
        int start = 0;
        int end = ns.length() - 1;
        while (start < end) {
            if (nsc[start++] != nsc[end--]) {
                return false;
            }
        }
        return true;
    }
}