Блог пользователя mason_24

Автор mason_24, история, 2 года назад, По-английски

If you are a Java programmer interesting in Competitive Programmer, you do not have time to learn C++ yet and you are facing some issues reading inputs and writing outputs quickly and safely or your programs usually ran into TLE (Time Limit Exceeded), because of the slowness while reading inputs and writing outputs, I have a quick solution for you from now on.

1) In order to read faster, the basic class Scanner is really slow and it consumes lot of memory. You will need to implement a class like following to enable a faster way to scan inputs from your input stream. Here is the class.

import java.util.StringTokenizer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class FastScanner {
    private BufferedReader reader = null;
    private StringTokenizer tokenizer = null;

    public FastScanner(InputStream in) {
        reader = new BufferedReader(new InputStreamReader(in));
        tokenizer = null;
    }

    public String next() {
        if (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }

    public String nextLine() {
        if (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                return reader.readLine();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        return tokenizer.nextToken("\n");
    }

    public long nextLong() {
        return Long.parseLong(next());
    }
     
    public int nextInt() {
        return Integer.parseInt(next());
    }
    
    public double nextDouble() {
    	 return Double.parseDouble(next());
	 }
    
    public int[] nextIntArray(int n) {
        int[] a = new int[n];
        for (int i = 0; i < n; i++)
            a[i] = nextInt();
        return a;
    }
    
    public long[] nextLongArray(int n) {
        long[] a = new long[n];
        for (int i = 0; i < n; i++)
            a[i] = nextLong();
        return a;
    } 
}

2) In order to write outputs, you will need to use the class PrintWriter from the java.io package of the Java libraries. No need to use System.out.println, which is also slow. Here is the details about PrintWriter class.

3) Here is an example of code on how to use it. 3.1) sample input: fast-scanner-test-sample.in

```
12345678901234
This is just a test of the FastScanner class.
```

3.2) sample input: fast-scanner-test-sample.in

```
12345678901234
This is just a test of the FastScanner class.
```

3.3) sample code on how to use FastScanner, PrintWriter

import java.io.PrintWriter;

public class FastScannerTest {
 
    public static void main(String[] args) throws Exception {
        FastScanner scanner = new FastScanner(System.in);
        long val = scanner.nextLong();
        String str = scanner.nextLine();
 
        PrintWriter printWriter = new PrintWriter(System.out);
        printWriter.printf("%d\n", val);
        printWriter.printf("%s\n", str);
        printWriter.close();
    }
}

3.4) How to compile

```
javac FastScanner.java
javac FastScannerTest.java
```

3.5) How to run

```
java FastScannerTest < fast-scanner-test-sample.in > fast-scanner-test-sample.out
```

References:

A part of credit of this blog is given to the author of the following article.

Полный текст и комментарии »

  • Проголосовать: нравится
  • -10
  • Проголосовать: не нравится

Автор mason_24, история, 2 года назад, По-английски

Hi Coders,

I recently solved the problem called "Permutations" on CSES Problem set. It is the 5th problem in the list.

I started by writing the solution in Java, because I'm more proficient in Java. Here is the solution that I have written. For some reasons, my Java solution failed some test with TLE(Time Limit Exceeded) for the following inputs : 11542, 1000000, 906819, 898673, 719525, etc.

import java.util.Scanner;

public class Permutations {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();

		if (n == 1) {
			System.out.println("1");
		} else if (n < 4) {
			System.out.println("NO SOLUTION");
		} else if (n == 4) {
			System.out.println("2 4 1 3");
		} else {
			for (int i = 1; i <= n; i += 2) {
				System.out.print(i + " ");
			}
			for (int i = 2; i <= n; i += 2) {
				System.out.print(i);
				if (i + 2 <= n) {
					System.out.print(" ");
				} else {
					System.out.println();
				}
			}
		}
	}
}

Now, because I'm learning C++ to become really good at Competitive programming, I wrtethe following code in C++ to address the same problem. Here is my C++ code:

#include <iostream>

using namespace std;

int main() {
    int n;
    cin >> n;
    
    if (n == 1) {
        cout << 1 << endl;
    } else if (n < 4) {
        cout << "NO SOLUTION" << endl;
    } else if (n == 4) { 
        cout << "2 4 1 3" << "\n";
    } else {
        for (int i = 1; i <= n; i += 2) {
            cout << i << " ";
        }
        for (int i = 2; i <= n; i += 2) {
            cout << i;
            if (i + 2 <= n) {
                cout << " ";
            } else {
                cout << endl;
            }
        }
    }
}

At my surprise, all the tests passed with C++ code. Now I would like to understand the main reason behind why almost the same code passed all the tests in C++ and not in Java. I thought may I should have use the type long in Java, but I did not need that in C++.

Is there something that I need to understand? Please your advice is welcome to make me understand what happened.

Полный текст и комментарии »

  • Проголосовать: нравится
  • -8
  • Проголосовать: не нравится

Автор mason_24, история, 3 года назад, По-английски

Experiment

Let suppose you have million of digits that you want to print on the screen one next to each other using Java. There are two approaches that I identified :

  • You can either choose to print each digit at the time (one digit next to each other) like so :
import java.util.Random;
public class Generate_Million_Digits {
	public static void main(String[] args) {
		Random rand = new Random();
		long start = System.currentTimeMillis();
		for (int i = 1; i <= 1000000; i++) {
			System.out.print(rand.nextInt(10));
		}	
		System.out.println();
		long end = System.currentTimeMillis();
		System.out.println("Elapsed Time in milli seconds: " + (end - start));
	}
}

The elapsed Time in milli seconds is : 5248

  • Or you can decide to concatenate all the digit you want to print in a special dat structure like a String or String Builder and then just print the string builder once like so :
import java.util.Random;
public class Generate_Million_Digits {
	public static void main(String[] args) {
		Random rand = new Random();
		long start = System.currentTimeMillis();
		StringBuilder sb = new StringBuilder();
		for (int i = 1; i <= 1000000; i++) {
			sb.append(rand.nextInt(10));
		}	
		System.out.println(sb.toString());
		long end = System.currentTimeMillis();
		System.out.println("Elapsed Time in milli seconds: "+ (end - start));
	}
}

The elapsed Time in milli seconds: 53

Story

The story is that I was recently solving a problem on Codeforces.com using Java 1.8.0_241. As part of my solution I needed to print a series of digits. My first intuition was to use the first approach I described above because it avoided me using additional data structures. It felt into the Time limit Exceeded issue with one of the test case. So, I asked myself how to fix the TLE. I then tried the second approach. Here, the test that was failing with TLE passed with the second approach. Therefore, I was able to solve the problem. The good thing is that in order to solve the problem, I had to introduce a data structure (here a StringBuilder) to avoid making many prints. There could be many more interesting technics out there.

Lesson

In Java, when you have to print many digits one next to each other, please prioritize concatenating all the digits into a data structure (StringBuilder, it is mutable) and print the bulk once, instead of printing one digit at the time one after each other.

Based on the conversation that is currently going on this article, you can also consider using the OutputStream I/O for the printing matter, because OutputStream is proved to give better result in terms of time of printing. Check the comments sections to get more insights.

Happy Coding !!!

Полный текст и комментарии »

  • Проголосовать: нравится
  • +31
  • Проголосовать: не нравится