간단하게 펄과 함께 하는 숏코딩 Short Coding
숏코딩
숏코딩은 코드 길이를 극한까지 줄이는 코딩을 의미한다. 골프에서 낮은 타수로 홀인하는 것처럼 숏코딩은 최소한의 바이트수로 해당 문제를 풀어내는 것을 말한다.
예를 들면 int value = 0; 를 공백과 이름을 줄여서 int v=0; 으로 하는 것도 일종의 숏코딩 기법이다.
가독성 따윈 개나줘라의 코딩이 무슨 의미가 있냐고 물어볼 수 있겠으나, 해당 언어의 테크닉을 극한까지 알고 있어야 최대한으로 바이트 절약이 가능하다.
숏코딩을 시도하면 언어의 상세 스펙문서를 얼마나 꿰차는지가 중요한지 알게된다.
문제
https://www.acmicpc.net/problem/14425
5 11
baekjoononlinejudge
startlink
codeplus
sundaycoding
codingsh
--------------------------------
baekjoon
codeplus
codeminus
startlink
starlink
sundaycoding
codingsh
codinghs
sondaycoding
startrink
icerink
위와 같이 s 집합의 문자열이 나머지 문자열에서 얼마나 나타나는지 체크하는 프로그램을 작성하라고 한다. 위 그림에서 ———- 로 나눠진 부분.
세어보면 4개 임을 알 수 있다. 문제 풀이는 간단해보인다. 해시형 자료구조에 해당 문자열을 넣고, 다음 검사문자열에서 해당 문자열이 있다면 카운팅을 하고 최종적으로 프린트 하면 될것 같다.
떠오르는 대로 코딩해보자.
($n, $m) = split(/ /, <STDIN>);
%s = {};
while(--$n >= 0) {
$_ = <STDIN>;
chomp;
$s->{$_} = 1;
}
$sol = 0;
while($m--) {
$_ = <STDIN>;
chomp;
if ($s->{$_} == 1) {
$sol++;
}
}
print $sol;
두개의 루프로 문제풀이를 했다. 먼저 %s 에 해당 문자열에 대한 값을 1로 셋하고 다음 루프에서 검사하면서 1 이면 카운팅 하는 방식.
점점 줄여보도록 하자. 먼저
또한 함수 호출의 괄호또한 생략가능하므로 split/ /,<>; 으로 고쳐 쓸 수 있다.
$_ = <STDIN>;
chomp;
$s->{$_} = 1;
또한 다음과 같이 고칠 수 있다.
$s->${<>}=1;
위 과정을 적용 시키면
($n, $m) = split/ /, <>;
while($n--) {
$s->{<>} = 1;
}
$v = 0;
while($m--) {
if ($s->{<>} == 1) {
$v++;
}
}
print $v;
perl 에서 한줄 짜리 명령어일 때 if, while, for 등의 명령어는 뒤에 위치하면서 괄호를 생략할 수 있다.
예를 들면
if(condition) { s; }
는
s if(condition);
으로 고쳐쓸 수 있다.
적용시켜보자.
($n, $m) = split/ /, <>;
$s->{<>} = 1 while$n--;
$v = 0;
while($m--) {
if ($s->{<>} == 1) {
$v++;
}
}
print $v;
밑의 while 은 하나의 명령이 아니다. 하지만 삼항연산자로 하나의 명령으로 바꾸고 한줄 짜리 while 로 바꾸면
$s->{<>}==1?$v++:0 while$m--;
print$v;
조금 더 줄여보자.perl 에서는 ==1 으로 검사를 하지 않더라도 undefined 나 0 이 아니면 참으로 반환한다.
$s->{<>}?$v++:0 while$m--;
print$v;
print 함수는 인자가 생략되면 특별한 변수 $_ 를 출력하게 되어있다. 고쳐보자.
$_=0;$s->{<>}?$_++:0 while$m--;print;
위 테크닉을 다 적용하고 나면~
($n,$m)=split/ /,<>;$s->{<>}=1 while$n--;$_=0;$s->{<>}?$_++:0 while$m--;print;
78 bytes!
현재 숏코딩 1위 파이썬 코드 84 bytes
I=input;n,m=map(int,I().split());*s,=map(I,['']*n);print(sum(I()in s for _ in[0]*m))
보다 6 bytes 줄인 78 bytes 로 1등이다~^_^
더 줄일 방법이 있을까요? 제 펄 실력의 한계네요.