Search code examples
javaalgorithmmathoptimizationfactorial

Count number of digits in factorial - Input/Ouput performance issue


I am solving task on spoj platform - count number of digits in factorial. I found Kamenetsky Formula and implemented it:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        int numOfTests = Integer.parseInt(in.readLine());

        for(int i = 0; i < numOfTests; i++) {
            System.out.println(KamenetskyFormula(Integer.parseInt(in.readLine())));
        }

        /*
        in.lines()
                .limit(numOfTests)
                .map(n -> Integer.parseInt(n))
                .forEach(n -> System.out.println(KamenetskyFormula(n)));*/
    }

    private static long KamenetskyFormula(int n) {
        if (n < 2) {
            return 1;
        }
        double x = n * Math.log10(n / Math.E) + Math.log10(2 * Math.PI * n) / 2.0;
        return (long) (Math.floor(x) + 1);
    }
}

first I used commented code (streams) and as I thought it's slower than actual one (without comments) so I changed but still getting exceed time limit. How can I make it faster?

Example input is (first line is number of tests):

3
1
10
100

and expected output:

1
7
158

Solution

  • I think the time limit is exceeding because of the slow I/O. This is mainly because of System.out.println's underlying PrintStream. Find more details in this post why-is-system-out-println-so-slow. You can refer to the below Fast I/O template which will help solve this problem.

    Reference - Fast I/O in java

    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.io.PrintWriter;
    import java.util.InputMismatchException;
    
    public class YourClassName {
        public static void main(String[] args) {
            InputStream inputStream = System.in;
            OutputStream outputStream = System.out;
            InputReader in = new InputReader(inputStream);
            PrintWriter out = new PrintWriter(outputStream);
            TaskA solver = new TaskA();
            int testCount = Integer.parseInt(in.next());
            for (int i = 1; i <= testCount; i++)
                solver.solve(i, in, out);
            out.close();
        }
    
        static class TaskA {
            public void solve(int testNumber, InputReader sc, PrintWriter w) {
                /*your logic goes here
                use w.println here to print the output which is usually faster
                */
            }
    
        }
    
        static class InputReader {
            private InputStream stream;
            private byte[] buf = new byte[1024];
            private int curChar;
            private int numChars;
            private InputReader.SpaceCharFilter filter;
    
            public InputReader(InputStream stream) {
                this.stream = stream;
            }
    
            public int read() {
                if (numChars == -1)
                    throw new InputMismatchException();
    
                if (curChar >= numChars) {
                    curChar = 0;
                    try {
                        numChars = stream.read(buf);
                    } catch (IOException e) {
                        throw new InputMismatchException();
                    }
    
                    if (numChars <= 0)
                        return -1;
                }
                return buf[curChar++];
            }
    
            public int nextInt() {
                int c = read();
    
                while (isSpaceChar(c))
                    c = read();
    
                int sgn = 1;
    
                if (c == '-') {
                    sgn = -1;
                    c = read();
                }
    
                int res = 0;
                do {
                    if (c < '0' || c > '9')
                        throw new InputMismatchException();
                    res *= 10;
                    res += c - '0';
                    c = read();
                } while (!isSpaceChar(c));
    
                return res * sgn;
            }
    
            public long nextLong() {
                int c = read();
                while (isSpaceChar(c))
                    c = read();
                int sgn = 1;
                if (c == '-') {
                    sgn = -1;
                    c = read();
                }
                long res = 0;
    
                do {
                    if (c < '0' || c > '9')
                        throw new InputMismatchException();
                    res *= 10;
                    res += c - '0';
                    c = read();
                } while (!isSpaceChar(c));
                return res * sgn;
            }
    
            public String readString() {
                int c = read();
                while (isSpaceChar(c))
                    c = read();
                StringBuilder res = new StringBuilder();
                do {
                    res.appendCodePoint(c);
                    c = read();
                } while (!isSpaceChar(c));
    
                return res.toString();
            }
    
            public boolean isSpaceChar(int c) {
                if (filter != null)
                    return filter.isSpaceChar(c);
                return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
            }
    
            public String next() {
                return readString();
            }
    
            public interface SpaceCharFilter {
                public boolean isSpaceChar(int ch);
    
            }
    
        }
    }