PS/자주 하는 답변

입출력에 대해 몇 가지 자주 하는 답변

djm03178 2023. 11. 30. 10:07

1. 입력과 출력의 순서는 상관이 없습니다.

문제를 풀 때에는 오로지 출력한 전체 내용이 정답과 같기만 하면 됩니다. 여러 테스트 케이스 각각에 대해 답을 출력하는 문제라고 하더라도 반드시 한 케이스를 입력받은 후 답을 출력하고 다음 케이스를 입력받아야 하는 것은 아닙니다. 모든 케이스를 전부 입력받고 답을 나중에 몰아서 출력해도 상관 없고, 입력을 받던 도중에 답을 출력해도 되고, 입력을 받기 전에 답을 출력해도 되며 (답을 알 수 있다면), 입력을 아예 안 받고 답을 출력해도 됩니다.

 

2. 입력과 출력이 화면에 섞여나와도 문제 없습니다.

보통 프로그램을 테스트할 때에는 콘솔에서 실행하고, 이 콘솔 화면에서 입력과 출력이 함께 이루어지기 때문에 섞여나오는 것이 정답에 영향을 주지 않을까 걱정하는 분들도 있는데, 전혀 상관 없습니다. 콘솔 화면은 그저 입력과 출력을 말 그대로 화면상에 보여주는 역할일 뿐이고, 실제로는 입력을 받는 스트림과 출력을 하는 스트림은 전혀 별개이기 때문에 입력과 출력이 어떤 순서로 나타나든 아무런 문제가 없습니다. 오로지 프로그램에서 출력문을 통해 출력한 내용 전체가 정답이기만 하면 됩니다.

 

3. 문제에서 요구하는 것 외에는 어떠한 출력도 해서는 안 됩니다.

채점은 출력된 내용을 검사하는 것으로 이루어집니다. 그렇기 때문에 출력한 내용은 그 전체가 문제에서 요구한 답 그대로여야 합니다. 만일 정답과 무관한 출력이 한 글자라도 이루어진다면 그 코드는 정답을 받을 수 없습니다. 종종 입력을 받기 전에 "N을 입력하세요: "와 같은 출력을 하는 경우를 보는데, 아무리 이것이 테스트 시에는 편하더라도 반드시 제출할 때만큼은 불필요한 출력을 모두 지워야 합니다.

 

4. 문제에서 요구한 출력 형식을 정확히 지켜야 합니다.

일반적으로 채점은 출력된 내용을 글자 단위로 정답과 비교합니다. 즉, 문제에서 정수를 하나 출력하라고 했고, 정답이 '123'이라면 '123'이 출력되어야 하지, '1 2 3', '123.0', '정답: 123', '[123]'과 같이 한 글자라도 정답과 다른 글자가 들어가서는 정답을 받을 수 없습니다. 공백으로 구분이 되어야 한다고 했으면 공백으로 구분을 해주어야 하며, 띄어쓰기를 요구하지 않은 곳은 띄어쓰지 않아야 합니다. 또한 스페셜 저지에서 허용했다는 문구가 없는 이상은 대소문자도 정확히 구분해야 하므로 'Yes'를 출력하라고 했으면 'Yes'를 출력해야 하고, 'YES'나 'yes', yEs' 등은 전부 틀린 답입니다. 다른 흔한 예시로는 여러 개의 정수나 문자열 등을 공백으로 구분해서 출력해야 하는데, Python의 list를 그대로 print로 출력해서 대괄호와 콤마 등의 불필요한 문자들이 같이 출력되는 것이 있습니다.

 

5. 입력 조건을 어기는 입력은 주어지지 않습니다.

문제에 쓰여있는 입력 조건은 해당 조건을 지키는 입력만 테스트 데이터로 준다는 뜻입니다. 즉, 해당 조건을 제대로 지키는지 여부를 코드가 검사할 필요가 없습니다. 예를 들어 N이 10만 이하의 자연수라고 문제에 주어져 있다면 코드는 오로지 N이 10만 이하의 자연수일 때만 정답을 잘 출력할 수 있으면 되고, if (N <= 100000) 과 같은 검사를 일절 할 필요가 없습니다. 조건을 잘못 읽은 채로 검사하는 문장을 넣었다가 올바른 입력을 그대로 패싱해서 틀리는 경우가 상당히 많습니다.

 

6. 빠른 입력 / 출력을 사용합시다.

https://www.acmicpc.net/problem/15552 에 잘 설명되어 있으니 이걸로 대체합니다.

 

7. Flush를 중간에 하지 마세요.

Flush는 프로그램이 출력한 내용을 실제로 스트림에 전송하는 행위를 말하는데, 대표적으로 콘솔 화면에 출력하는 경우 지금까지 출력한 내용이 전부 화면에 나타나게끔 보장하는 것이 있습니다. 이러한 행위는 일반적으로 매우 매우 매우 매우 느리기 때문에 오로지 출력한 전체 내용만이 정답이면 되는 문제 풀이에서는 프로그램 중간 중간에 사용할 필요가 없습니다.

 

대표적인 flush 행위로는,

  • C++에서 endl을 사용하는 것. endl은 개행 + flush를 겸하는 역할이기 때문에, 그냥 '\n'을 쓰는 것이 훨씬 빠릅니다.
  • C++에서 cin.tie(0) 없이 입출력을 번갈아 수행하는 것: 기본적으로 cin은 cout에 묶여있기 (tie) 때문에 입력을 받을 때마다 자동으로 cout이 flush됩니다. 즉, 입력을 받기 전에 그때까지 출력한 건 확실하게 화면에 다 보이게 하겠다는 의도인 것입니다. 하지만 문제 풀이를 하는 데에 이런 기능은 필요하지 않으니 풀어주기 위해 쓰는 문장이 cin.tie(0) 입니다.
  • C++에서 cout.flush()를 호출하는 것
  • Java의 BufferedWriter에서 flush()를 호출하는 것: Java의 경우 flush를 한 번은 해야 하는데, 프로그램이 종료되기 전 맨 마지막에 한 번만 하면 됩니다. close()만 호출해도 flush가 같이 이루어집니다.

Flush를 하지 않으면 환경에 따라서는 중간 출력 결과가 보이지 않아 불편할 수도 있는데, 테스트를 위해 일시적으로만 flush를 시킬지, 아니면 로컬에서만 flush가 되게 할지 등은 자유입니다. 하지만 이는 채점 시에 정말 상상을 초월할 만큼 프로그램을 느리게 하는 원인이기 때문에 제출할 때만큼은 반드시 반드시 중간 flush를 제거하고 제출해야 합니다.

 

8. 널 문자는 단 한 개도 출력되어서는 안 됩니다.

https://djm03178.tistory.com/17

 

문자열의 끝까지만 봐야 합니다.

C/C++에서 문자열이란 초보자가 다루기가 상당히 까다로운 편에 속합니다. 정확한 사용법을 숙지하지 못하고 쓰다가 실수를 하는 일도 굉장히 잦습니다. 대표적인 사례가 바로 문자열의 끝과 관

djm03178.tistory.com

 

9. \b를 출력해서는 절대로 안 됩니다.

\b는 커서를 왼쪽으로 한 칸 옮기는 역할을 하도록 설계된 문자이지만, 이는 그저 화면상에서 그런 역할을 하도록 지정이 된 것 뿐입니다. \b는 그 자체로 하나의 문자이고, 채점 프로그램에게 있어 \b를 출력하는 것은 a, z, 1 등 어떤 다른 평범한 문자 하나를 출력하는 것과 다를 게 없습니다. 그 어떤 문제에서도 \b의 출력을 요구하지 않기 때문에, \b를 출력했다면 무조건 오답이 됩니다. 이미 출력했던 문자를 도로 지우는 방법은 존재하지 않으므로 불필요한 출력은 처음부터 이루어지지 않게 해야 합니다.

 

10. 개행 대신 공백을, 공백 대신 개행을 출력해도 정답을 받습니다.

보통 개행이나 공백을 틀린 경우에는 '출력 형식이 잘못되었습니다'를 받지만, 정확히 하나를 다른 쪽으로 대체해서 쓰는 것은 BOJ에서는 정답으로 인정해 줍니다. 이는 채점 정보 https://help.acmicpc.net/judge/info 에도 있는 내용으로, 버그이긴 하지만 편의상 너무 까다롭지 않도록 그냥 허용하는 것이라고 보면 됩니다. 다만 다른 온라인 저지에서는 이를 정답으로 허용하지 않을 수도 있으니 가능하면 문제에서 요구한 출력 형식을 정확히 지키도록 연습하는 것을 추천합니다.