숏코딩을 해보자 (Code Golf)
백준 온라인 저지를 풀어본 사람들이라면 대개 이러한 메뉴를 본 적이 있을 것이다.
필자의 경우는 사실 숏코딩보다는 성능에 치중하는지라 숏코딩에 대한 글은 올린 적은 없어 이번기회에 한 번 숏코딩의 기본적인 방법을 정리하고자 한다.
먼저 숏코딩이 무엇인지를 알아야하지 않겠는가. 숏코딩이란 말 그래도 짧은코딩인데 소스를 얼마나 짧게 짜느냐를 보는 것이다. 예로들면 이런 것이다
int value = 10;
이렇게 보편적으로 변수를 선언할 때, 여기서 좀 더 짧게 짜고자 하면 변수명을 더욱 간단하 하면 된다.
int v = 10;
여기서 더 공백까지 줄인다면 더 짧게 할 수 있다.
int v=10;
기본적으로 숏코딩은 코드 길이, 즉 바이트를 기준으로 한다. 백준 채점 서버는 UTF-8을 기준으로 하는 것 같으니, 되도록이면 한글은 쓰지 않는게 좋다. 한글의 경우 3바이트를 쓰기 때문에 바이트가 더 길어지므로 1바이트 문자들인 영어와 숫자들로만 최대한 구성하는 것이 좋다.
이렇게 코드의 길이를 최대한 줄이는 것이 바로 숏코딩이다. 무슨 의미가 있겠냐고 묻는다면 비효율적인 코드를 줄이는 연습에 도움이 되지 않을까 생각한다. 그리고 나름의 여기서 재미를 찾는 분들도 있을 것이니 한 번 심심하다면 도전해보면서 소소한 챌린지를 해보면 좀 더 코딩하는데 재미를 붙일 수 있을 것이다.
그럼 아래의 예제를 통해 숏코딩을 해보자.
- C언어로 숏코딩 해보기
가장 대중적인 C언어를 사용하여 숏코딩을 해보겠다. C언어로 위 문제를 푼다면 일반적으로 아래와 같이 풀 것이다.
#include <stdio.h>
int main () {
int a;
int b;
scanf("%d %d", &a, &b);
printf("%d", a + b);
return 0;
}
(112바이트)
가장 일반적인 풀이 방법이다. 극히 평범하고 보기에도 재미가 없다.(?)
일단 가장 먼저 변수들을 하나로 묶어보자. int a하고 b를 한 번에 생성하는 것이다.
#include <stdio.h>
int main () {
int a, b;
scanf("%d %d", &a, &b);
printf("%d", a + b);
return 0;
}
(107바이트)
변수를 하나 합치면서 5바이트가 줄었다. 여기서 더 압축을 해보자. C언어를 배운사람들이라면 대부분 알겠지만 main함수의 리턴 타입의 경우 생략할 경우 컴파일러에서는 int형으로 간주하기 때문에 생략할 수 있다. 또한 C99기준으로 main함수는 } 에 도착하면 0을 반환하기 때문에 return 0; 또한 생략해도 된다. 즉, 아래와 같이 코드를 더욱 짧게 만들 수 있다.
#include <stdio.h>
main () {
int a, b;
scanf("%d %d", &a, &b);
printf("%d", a + b);
}
(92바이트)
여기서 숏코딩을 몇 번 해본 분들은 알겠지만, #include <stdio.h> 를 생략할 수 있다. 아마 gcc에서 지원하는 기능인 것 같지만, GCC가 C언어 표준 라이브러리를 암시적으로 연결하기 때문에 가능한 것 같다. 이에대한 것은 아래 글을 보면 도움이 될 것 같다.
main () {
int a, b;
scanf("%d %d", &a, &b);
printf("%d", a + b);
}
(72바이트)
여기서 더 줄일 수 있는 방법은 뭘까?
위 문제에서 보면 인자를 두 개 받기 때문에 main함수 매개변수로 넣어줄 수 있다. 즉, 다음과 같이 짤 수 있을 것이다.
main (a, b) {
scanf("%d %d", &a, &b);
printf("%d", a + b);
}
(62바이트)
그리고 여기서 줄이기 위해 공백을 최소화해보면 다음과 같다.
main(a,b){
scanf("%d%d",&a,&b);
printf("%d",a+b);
}
(59바이트)
그리고 마지막으로 개행까지 모두 없애보면
main(a,b){scanf("%d%d",&a,&b);printf("%d",a+b);}
총 42바이트가 된다.
이렇게 처음 112바이트였던 것을 42바이트 까지 줄일 수 있다. 이런 방식이 바로 숏코딩이다.
- Java로 숏코딩 해보기
두 번째로 대중적인 언어중 하나인 Java로 숏코딩을 해보겠다.
자바의 경우 문법 자체가 긴 언어에 속하는 언어다.
아마 가장 대중적인 방법은 아래와 같을 것이다.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int a = in.nextInt();
int b = in.nextInt();
System.out.print(a + b);
}
}
(208바이트)
가장 일반적인 풀이 방법이다. 자바를 처음 접했던 분들이라면 대개 이러한 방법을 사용했을 것이다.
일단 앞서 Scanner 의 객체 명을 한 글자로 줄여주고 class의 제어접근자 public을 삭제해보면 다음과 같을 것이다.
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner i = new Scanner(System.in);
int a = i.nextInt();
int b = i.nextInt();
System.out.print(a + b);
}
}
(198바이트)
또한 여러분이 무심코 넘어가는 것 중 하나가 main(String[] args) 에서 args 또한 매개변수 명으로 args 대신 다른 것으로 대체해줄 수 있다. 이 또한 줄여보고, 패키지를 import 해줄 때, Scanner 대신 * 로 util패키지 전체를 import 해주면 좀 더 짧게 쓸 수 있겠다.
import java.util.*;
class Main {
public static void main(String[] s) {
Scanner i = new Scanner(System.in);
int a = i.nextInt();
int b = i.nextInt();
System.out.print(a + b);
}
}
(189바이트)
여기서 좀 더 줄일 수 있다면, Scanner 를 쓰지 않고 바이트스트림을 사용하여 입력받는 방법이다. 즉, 다음과 같이 줄일 수 있다.
class Main {
public static void main(String[] s) throws Exception {
byte[] a = new byte[3];
System.in.read(a);
System.out.print(a[0] + a[2] - '0' - '0');
}
}
(165바이트)
또한 '0'은 아스키값으로 48이니 그의 두 배인 96을 빼주는 것으로 변경하고, class 대신 interface를 사용하여 메인 메소드의 public도 빼줄 수 있도록 한다. class가 아닌 interface 에서 main메소드를 선언하는 것은 java8부터 가능한 기능이라고 한다. 이렇게 코딩할 기회는 그리 많지는 않아 잘 모르는 분들도 있지만, 의외로 아주 가끔씩 보일 때가 있곤 한다.
interface Main {
static void main(String[] s) throws Exception {
byte[] a = new byte[3];
System.in.read(a);
System.out.print(a[0] + a[2] - 96);
}
}
(155바이트)
여기서 가능한 공백과 개행을 모두 지워보면 다음과 같이 된다.
interface Main{static void main(String[]s)throws Exception{byte[]a=new byte[3];System.in.read(a);System.out.print(a[0]+a[2]-96);}}
(130바이트)
이렇게 숏코딩을 하는 재미로도 백준 문제들을 접할 수도 있다.
또 위와 같은 언어가 아닌 처음 목적 자체가 숏코딩을 위한 언어도 있다. 바로 GolfScript(골프스크립트) 라는 언어인데, 이 언어 자체가 코드 골프(특정 알고리즘의 코드 길이를 짧게 하기 위한 목적인 대회)를 위한 목적으로 만들어진 변태같은 언어다.
http://www.golfscript.com/golfscript/builtin.html
쉽게 정리된 걸 보고싶다면 아래 것을 보면 될 것이다
https://esolangs.org/wiki/GolfScript
여기서 보면 알겠지만 스택구조이기 때문에 이에 기반하여 코드를 짜보자면 다음과 같다.
~ 연산자는 dump 할 수 있고, 두 수의 덧셈의 경우 + 이다.
즉, ~+ 만 해주면 끝난다....
~+
이건 그냥 난해한 프로그래밍 언어라.. 스택을 잘 활용할 줄 알면 좋은 숏코더(?)가 될 지도 모르겠다.
일반적으로 고급 언어 중에서는 파이썬이 숏코딩에 유리한 언어인 것 같다. 찾아보니 루비 언어도 숏코딩에 유리하다고는 하지만 이 언어는 본 적이 없으므로 pass..
파이썬의 경우 eval() 이라는 매우매우 좋은 함수가 있어서 join만 활용할 줄 알면 다음과 같이 짜면 된다.
print(eval('+'.join(input())))
이렇게 몇 개의 언어로 숏코딩 하는 방법을 봤다.
가끔은 이런 재미로 코딩해보는 것도 나쁘지 않을듯...? 막상 해보다 보면 언어에 대한 이해가 높아질 수 있어서 한 번쯤은 도전해보아도 좋을 것 같다.
그리고 이번에 포스팅 하면서 느낀거지만 백준에 숏코딩 하는 분들 보면 정말 괴물같은 분들이 많다..
아무쪼록 가끔은 색다른 코딩을 해보는 것도 또다른 즐거움이지 않을까 싶어 작성해봤다. 여러분들도 즐거운 코딩하시길 바란다.
'이모저모' 카테고리의 다른 글
Bogo sort (보고 정렬) 알고리즘 (6) | 2020.09.29 |
---|