์ฝ๋ฉ ๋ฌธ์ ํ ํ๋ฆฟ ์ ๋ฐ์ดํธ
์ ๋ฒ์ ๋ธ๋ก๊ทธ์ ์ฌ๋ฆฐ ์ฝ๋ฉ ๋ฌธ์ ํ ํ๋ฆฟ์ ์ฌ์ฉํ๋ค ์ธ ๊ฐ์ง ์์ ํ ์ ์ ์ ๋ฆฌํด๋ณธ๋ค.
1. ๋ฌธ์ ํ์ด ๋ฉ์๋์ ์ ๋ ฅ ํด๋์ค๋ก Scanner ๋์ InputStream ์ฌ์ฉ
Sorting ์๊ณ ๋ฆฌ์ฆ์ ํ ์คํธํ๋ ๊ณผ์ ์์ ํ ์ค์ด 1000000๊ฐ์ int๊ฐ์ผ๋ก ์ด๋ค์ง ํ ์คํธ ์ผ์ด์ค๋ฅผ ์ฝ์ด์ค๊ฒ ๋์๋ค. ์ญ์๋ ์ตํ ์๋ ค์ง ๋๋ก Scanner ํด๋์ค์ nextInt()๋ก๋ ์ญ๋ถ์กฑ์ด์๊ณ [1], ๋ช ์ญ์ด๋ฅผ ๋๊ฒ ๊ธฐ๋ค๋ ค๋ ์ ๋ ฅ ์ฒ๋ฆฌ๊ฐ ๋๋์ง ์์ BufferedReader + StringTokenizer๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค. ๋ฐ๋ผ์ ์ ๋ ฅ ๋ฐฉ์์ผ๋ก Scanner์ BufferedReader๋ฅผ ํ์์ ๋ฐ๋ผ ์ธ ์ ์๋๋ก ๋ฌธ์ ํ์ด ๋ฉ์๋๊ฐ Scanner ๋์ InputStream์ ์ ๋ ฅ๋ฐ๋๋ก ์์ ํ๋ค. ์ ๋น์ด abstraction ๊ด์ ์์๋ InputStream์ ๋ฐ๋ ๊ฒ์ด ๋ ์ ํฉํ๊ธฐ๋ ํ๊ณ .
2. ์ฌ๋ฌ ๊ฐ์ ํ ์คํธ ์ผ์ด์ค๋ฅผ ํ๋์ ํด๋์ค์์ ์คํํ๊ธฐ
์์ ๋ฒ์ ์ ํ ํ๋ฆฟ์ ๊ฐ ํ ์คํธ ํด๋์ค๋น ํ๋์ ํ ์คํธ ์ผ์ด์ค๋ฅผ ์คํํ๋๋ก ๊ตฌ์ฑ๋์ด ์์๋ค. ๊ทธ๋ฌ๋ค๋ณด๋ ์ ์ถ๋ ฅ ํ์ผ ์ฌ๋ฌ ์ ๊ฐ๊ฐ์ ๋ํด์ ํ ์คํธ ์ผ์ด์ค๋ฅผ ๊ตฌ์ฑํ๋ ค๋ฉด ํ์ผ์ ๋ณต๋ถํ๊ณ ํด๋์ค๋ช ๊ณผ ์ ์ถ๋ ฅ ํ์ผ๋ช ๋ง ๋ฐ๊พธ๋ ์์ ์ ๋ฐ๋ณต์ ์ผ๋ก ํด์ผ ํ๋ค. ์ด๊ฒ ์ง๋ฃจํ๊ธฐ๋ ํ๊ฑฐ๋์, ๊ฐ ํ ์คํธ ์ผ์ด์ค๋ค์ ๋น๊ตํ๋ฉด ์ค๋ณต๋๋ ์ฝ๋๊ฐ ๋๋ถ๋ถ์ด๋ผ ๋ฏธ๊ด์ ํด์น๋ค.
๊ณตํต๋๋ ๋ถ๋ถ์ ์ ๋ฆฌํ ๋ฐฉ๋ฒ ์ค๋ช ์ ์๋ ์์ ์ฝ๋๋ก ๊ฐ์ํ๋ค. ์ง๊ธ ์ด ๋ฐฉ๋ฒ์ ํ๊ณ๋, ๊ฐ @Test ๋ฉ์๋๋ค๋ง๋ค System.out์ ๊ฐ์ ์์ฑํ ByteArrayOutputStream ๊ฐ์ฒด๋ก setํ๊ธฐ ๋๋ฌธ์, ๋ฐ๋์ ์์ฐจ์ ์ผ๋ก ์คํ๋์ด์ผ ํ๋ค๋ ์ ์ด๋ค. ๋ง์ฝ ๊ฐ @Test ๋ฉ์๋๋ค์ parallelํ๊ฒ ์คํํ๋ค๋ฉด ํ ์คํธ๊ฐ ์ ๋๋ก ์คํ๋์ง ์์ ๊ฒ์ด๋ค.
3. ํ ์คํธ ์ถ๊ฐ์ ์์ ํด์ผ ํ๋ ์ฝ๋ ์์ญ ํ์ ์ํค๊ธฐ
ํ ์คํธ๋ฅผ ์ถ๊ฐํ๊ธฐ ์ํด ๋ณต๋ถ ํ ์์ ํด์ผ ํ๋ ๊ฐ๋ค์ด ์ฌ๊ธฐ์ ๊ธฐ ์์ด ํผ๋์ ์ฌ์ง๊ฐ ์์ผ๋ฏ๋ก ํ๋ฐ ๋ชจ์ ์ ๋ฆฌํ๋ค. ์ด ๊ณผ์ ์์ ํ ์คํธํ ๋ฌธ์ ํ์ด ๋ฉ์๋๋ฅผ ํจ์ ๊ฐ์ฒด๋ก assignํ๊ธฐ ์ํด Java 8์์ ์ถ๊ฐ๋ java.util.Function.Consumer ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋ค. Consumer ์ธํฐํ์ด์ค๋ ๋ฐํ ๊ฐ์ด ์์ด ์ ๋ ฅ ๊ฐ์ฒด๋ง์ ๋ฐ๋ ํจ์์ ํ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ค. [2, 3] (์๋ SolutionTest ํด๋์ค์ SOLUTION_TO_TEST ๊ฐ์ฒด ์ฐธ๊ณ )
์๋ ์ฝ๋๋ ์์ ๋ ํ ํ๋ฆฟ์ ๋ฌธ์ ํ์ด ํด๋์ค์ ํ ์คํธ ํด๋์ค๋ค. ์ ์ฒด ์ฝ๋๋ Github ์ ์ฅ์์์ ํ์ธํ ์ ์๋ค.
public class Solution { public static void solveProb(InputStream istream) { Scanner sc = new Scanner(istream); ... // Scanner๋ก๋ถํฐ ์ ๋ ฅ์ ๋ฐ์ stdout์ผ๋ก ๊ฒฐ๊ณผ ์ถ๋ ฅ } public static void main(String[] args) { solveProb(System.in); } }
public class SolutionTest { ///////////// Test-specific codes: you only need to modify these lines. ///////////////// // Requires Java 8 Consumer<InputStream> SOLUTION_TO_TEST = istream -> Solution.solveProb(istream); private final int numOfTestCases = 2; private final String[] INPUT_FILE_PATHS = { "src/ehwaz/problem_solving/template/input1.txt", "src/ehwaz/problem_solving/template/input2.txt" }; private final String[] OUTPUT_FILE_PATHS = { "src/ehwaz/problem_solving/template/output1.txt", "src/ehwaz/problem_solving/template/output2.txt" }; @Test private void runTestCase1() throws Exception { runTest(0, SOLUTION_TO_TEST); } @Test private void runTestCase2() throws Exception { runTest(1, SOLUTION_TO_TEST); } ///////////////////////////////////////////////////////////////////////////////////////// private FileInputStream istream; private ByteArrayOutputStream outContent; private Path outputFilePath; PrintStream original = System.out; public void runTest(int testIdx, Consumer solutionToTest) throws Exception { // Input file๋ก๋ถํฐ ํ ์คํธ input ์ค๋น istream = new FileInputStream(INPUT_FILE_PATHS[testIdx]); // ํ ์คํธ output์ ByteArrayOutputStream์ผ๋ก ๋ฐ๋๋ก ์ค๋น outContent = new ByteArrayOutputStream(); System.setOut(new PrintStream(outContent)); solutionToTest.accept(istream); // Consumer.accept(...) ํธ์ถ๋ก ๋ฌธ์ ํ์ด ๋ฉ์๋ ์คํ String result = outContent.toString().trim(); // Output answer ์ฝ๊ธฐ outputFilePath = Paths.get(OUTPUT_FILE_PATHS[testIdx]); String answer = new String(Files.readAllBytes(outputFilePath)).trim(); // Test ํต๊ณผ ์ฌ๋ถ ํ๋ณ Assert.assertEquals(result, answer, "Test case #" + (testIdx+1) + " is failed."); istream.close(); outContent.close(); System.setOut(original); } }
BufferedReader(+StringTokenizer)๊ฐ Scanner๋ณด๋ค ๋น ๋ฅธ ์ด์ ๋ก๋ ํด๋์ค ๋ด๋ถ buffer์ ํฌ๊ธฐ๊ฐ BufferedReader(8192 chars)๊ฐ Scanner(1024 chars)๋ณด๋ค ๋ ํฌ๋ค๋ ์ ์ด ์ฃผ๋ก ๊ฑฐ๋ก ๋๋ค. [๋งํฌ] Scanner๋ BufferedReader์ ๋นํด regex ๋งค์นญ์ผ๋ก ๋ฌธ์์ด์ ์ฝ์ด์ ๋ณํํ๋ ๊ณผ์ ์ด ์ถ๊ฐ๋ก ์ํ๋๊ธด ํ์ง๋ง, ๋๋ถ๋ถ์ ์ฑ๋ฅ ๋น๊ต์์๋ BufferedReader์ StringTokenizer๋ฅผ ํจ๊ป ์ฌ์ฉํ๋ฏ๋ก ๋ ๊ฒฝ์ฐ ๋ค ์ํ๋๋ ๊ณผ์ ์ ๊ฐ์ ์ ์ด๋ค. Scanner์ ๋ด๋ถ ๊ตฌํ์ ์ดํด๋ณด์ง ์๋ ์ด์ Scanner์์ regex์ value parsing์ด ์ํ๋๋ ๊ฒ์ด ์๋ ์ ํ์ ์์ธ์ด๋ผ๊ณ ๋จ์ธํ ์๋ ์๋ ๊ฒ ๊ฐ๋ค.ย โฉ๏ธ
Consumer ์ธ์๋ ์ ๋ ฅ ๊ฐ์ฒด ์์ด ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ Supplier ์ธํฐํ์ด์ค์, ๊ฐ์ฒด๋ฅผ ์ ๋ ฅ๋ฐ์ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ Function ์ธํฐํ์ด์ค๊ฐ ์๋ค.ย โฉ๏ธ
Java 8์์ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ ์ธํฐํ์ด์ค๊ฐ ์ถ๊ฐ๋ฌ๋ค๋ ๊ฑด ์๊ณ ๋ ์์์ง๋ง ์ด๋ ๊ฒ ์์ํ๊ฒ๋๋ง ์ ์ฉํด๋ณธ๊ฑด ์ฒ์์ด๋ผ ๊ธฐ์๋ค. Java 8์ ๋ํ ์ข์ ํํ ๋ฆฌ์ผ์ ์ฐพ์๋๋ฐ ์ ์ ๋ ํ๊ณ ์ ์ฉํด๋ณด๊ณ ์ถ๋ค.ย โฉ๏ธ








