코드골프를 하기 위해 알아야 할 것들

redneval의 이미지

`Vigenere Cipher' 루비 부문 1위에 오른 leonid님에 비할 바는 아니지만

(http://kldp.org/node/87919 참고)

저는 이번에 `Reverse' 펄 부문 4위에 올랐습니다.

그걸 기념할 겸해서 글을 써보기로 했습니다.



제목 : 코드골프를 하기 위해 알아야 할 것들


1. 코드골프는 보기보다 쉽다.

아마 코드골프에 익숙하지 않은 분들은 고수들이 올린 코드를 보게되면,

예를들어 다음과 같은 코드를 본다면,

sub b{[@b=(abs||99,bottle."s"x!!++$_,of,beer),on,the,wall]}print"@{+b}, @b.
",$_?"Take one down and pass it around":"Go to the store and buy some more",", @{+b}.

"for-99..-1

(출처 : http://kldp.org/node/83181 의 raymundo님)

지레 겁부터 먹을지 모릅니다.

하지만 위의 코드는 단지 "읽기 어려울" 뿐이고, 약간만 고쳐서 읽기 쉬운 코드로 바꿔보면,

sub a {
    return [ (@b = (abs$i||99, bottle."s"x(!!++$i), of, beer)), on, the, wall ]
}
for $i (-99..-1) {
    print
        "@{a()}, @b.\n",
        $i ? "Take one down and pass it around"
             :"Go to the store and buy some more",
        ", @{a()}.\n\n"
}

훨씬 이해하기가 쉬워졌습니다.

그러므로 처음코드는 보기에는 어렵지만,

연산자 우선순위와 몇 가지 법칙 (함수의 반환값, for문의 $_ 변수 등) 등을 알고 있다면

어려울 것이 없습니다.

코드골프라고 해서 특별히 어려운 내용이 나오는 것은 아닙니다.

오히려, 코드의 길이를 줄이기 위해서는, 되도록 구성을 간단하게 만드는 경우가 많습니다.


2. 문법과 연산자

코드골프를 하려면 펄을 알아야 하고,

펄을 공부하려면 우선 perldoc 을 봐야합니다. (http://perldoc.perl.org)

문법은 perlsyn에 있으므로, http://perldoc.perl.org/perlsyn.html 을 보면 됩니다.

번역문(http://wiki.kldp.org/wiki.php/perldoc/perlsyn)도 참고하세요.

perlsyn과 perlop을 완벽히 이해하면 문법과 연산자는 거의 끝입니다.

그런데, 코드골프를 하기 위해서는 `이상한' 코드들에 관심을 더 가져야 합니다.

예를들어, perlop 문서를 읽고나서 다음과 같은 코드를 작성할 수 있어야 합니다.

($n=1)++;

$n+=($n+=1)+=2;

그러므로 상상력을 발휘하고 직접 테스트 해보면서, 쉽게 눈에 띄지 않는 문법요소를 익혀야 합니다.


3. 함수

http://perldoc.perl.org/index-functions.html 를 보는 것으로 충분합니다.

함수의 형태, 동작, 반환값을 꿰고 있어야 합니다.

물론 다 외울 필요는 없고, 중요함수만 외우고, 나머지는 필요한 때 찾아보면 됩니다.

사실, 쓸만한 함수들은 그리 많지 않습니다. 쓸만한 함수를 알파벳 순으로 적어보면 다음과 같습니다. (정규식 관련함수 제외)

abs, chr, grep, int, join, map, ord, pop, print, push, reverse, shift, splice, split, substr


4. 실행옵션

http://kldp.org/node/82236#comment-392112 을 읽고나서야 알게 된 것이지만

펄의 실행옵션을 사용하면 코드를 더 줄일 수 있습니다.

입출력문제가 많은 코드골프 특성상, 가장 많이 쓰이는 옵션은 -p 와 -n 입니다.

-n 옵션을 사용하면 다음과 같이 해석됩니다.

while (<>) {
    ...;	# ...은 실제 작성한 코드 부분
}

`;' 가 붙기 때문에 다음과 같이 이상한 코드가 가능합니다.

#!perl -n
$;="Hello, world\n";
print$

-p 옵션을 사용하면 다음과 같이 해석됩니다.

while (<>) {
    ...	# ...은 실제 작성한 코드 부분
}
continue {
    print or die "-p destination: $!\n";
}

그런데 이와 관련된 트릭이 있습니다.

설명하기 쉽게 연습문제를 하나 풀어볼까요.

연습문제) wc -l 명령어와 같이, 표준입력으로 들어오는 입력의 라인 수를 출력하는 프로그램을 작성하시오.

#!perl -pl
}{$_=$.

위와 같이 프로그램하면,

while (<>) {
}
{
    $_=$.
}
continue {
    print or die "-p destination: $!\n";
}

위와 같이 바뀌므로, while 문 내에서 하는 것은 아무 것도 없고,

while 문이 종료되고 나서 $_=$. 의 대입이 발생하고 마지막으로 $_ 를 출력하게 됩니다.

나머지 옵션에 대한 설명은, http://perldoc.perl.org/perlrun.html 를 읽으면 됩니다.

다 볼 필요는 없고, p, n, l, a, F, 0 정도만 알아두면 될 듯 합니다.

a, 0 옵션을 왜 사용하는지 의문이 난다면, 다음 연습문제가 도움이 될 겁니다.

연습문제) wc -w 명령어와 같이, 표준입력으로 들어오는 입력의 단어 수를 출력하는 프로그램을 작성하시오.

#!perl -0apl
}{$_=@F


5. 특수변수

특수변수 $_, @_ 는 아마 잘 알고 있을 겁니다.

그 밖에도 정규식 관련 특수변수와 입출력 관련 특수변수들도 역시 중요합니다.

내용은 그리 어렵지 않습니다.

http://perldoc.perl.org/perlvar.html


6. 정규식

펄의 `꽃'이라 할 수 있는 정규식은, 코드골프에서도 생각이상으로 써먹을 곳이 많습니다.

연습문제) "1 3 5 2 12 3 4 6 1 2" 과 같이 표준입력으로 들어오는 값들의 합을 출력하는 프로그램을 작성하시오.

우선 평범하게 풀어봅시다.

@N=split" ",<>;
map{$s+=$_}@N;
print"$s
"

코드크기는 39B가 됩니다.

펄의 실행옵션 a, p, l 을 이용하면,

#!perl -apl
map$s+=$_,@F;$_=$s

30B가 되었습니다.

그런데 정규식과 $\를 사용하면,

#!perl -pl
s/\d+/$\+=$&/eg}{

28B가 됩니다.

정규식은 배열에 비해 여러 단점을 가지고 있음에도,

$&, $`, $' 과 같은 특수 변수와 각종 부가옵션을 이용할 수 있는 장점이 있습니다.


7. 고수의 노하우를 배워라

펄 골프에 관한 최고의 문서는 아마 The "Perlgolf History" Book 일 것입니다.

http://terje2.frox25.no-ip.org/~golf-info/Book.html

이 책을 읽고 전부 이해가 간다면, 당신은 이미 고수.

File attachments: 
첨부파일 크기
Image icon codegolf.png7.92 KB
Forums: 
keedi의 이미지

호오! 일목요연하게 꼼꼼히 정리해주셔서 레퍼런스로서 좋은 글입니다.

여기 나오는 팁은 사실 굳이 코드골프를 하지 않으신다고 하시더라도
쉘 커맨드에서 one-liner 커맨드로 사용하기도 무척 유용합니다~ :-)

펄로 코드 골프를 시작하려는 분들이나 쉘에서 사용하시려는 분들께 유용한 자료네요. ^^)b

---------------------------
Smashing Watermelons~!!
Whatever Nevermind~!!

Keedi Kim

----
use perl;

Keedi Kim

leonid의 이미지

코드골프의 재미는 널리널리 퍼트려야 합니다 :)

위의 연습문제 중 합을 구하는 문제를
정규표현식만큼 유용하게 쓰이는 eval이라는 함수를 이용해서
Ruby로(Perl은 제가 잘 몰라서-_-a) 풀어봤습니다.

p eval gets.split*'+'

로 21B입니다.

아, 그리고 Reverse 4위 오르신거 축하드립니다. :)

redneval의 이미지

keedi 님/

네, 펄 골프를 잘하게 되면 자연히 펄 실력도 올라가지요 :)

이 글은 `펄로 코드 골프를 시작하려는 분' 을 대상으로

코드 골프가 어떤 것인지 알리고자 작성한 글입니다. (거기다가 잘 알려진 몇 가지 팁까지)

저는 펄을 배우기 위한 동기부여로 코드골프를 합니다.

코드 몇 자 줄이려고 perldoc 뒤져가며 문서를 읽다보면

정작 코드 줄이는데 성공하는 경우보다는 펄에 대한 몰랐던 지식, 머리속에서 코딩하는 능력, 새로운 아이디어만 얻고 끝나는 경우가 더 많았습니다.

아무튼 펄을 배울 분들에게도 코드골프를 추천하고 싶습니다.

leonid 님/

역시 1위 하신 분의 실력이 굉장하군요.

저도 eval 써서 좀 줄여봤습니다.

#!perl -pl
y/ /+/;$_=eval

25B입니다. 역시, 루비 p 함수의 막강함에는 따라갈 수가 없군요.

--------------------Signature--------------------
Light a candle before cursing the darkness.

redneval의 이미지

왠지 leonid 님에게 `합 구하기 문제' 코드배틀에 진 것 같아서 찝찝한(?) 마음이 드네요. :)

얼마 후에 나올 펄 5.10 버전용으로 만들면,

$_=<>;y/ /+/;say eval

로 21B입니다. 이것으로 비긴겁니다. 펄 만세~~ :)

--------------------Signature--------------------
Light a candle before cursing the darkness.

leonid의 이미지


사용한 언어가 서로 다르기 때문에 (펄과 루비)

전 그다지 '배틀' 이라고는 생각하지 않았습니다 :)

그러나 상대 역시 똑같이 루비를 사용하고 있다면 얘기가 달라지죠.. ㅎㅎ

권순선의 이미지

참고로 지난 10일 KLDPConf때 keedi님의 발표에서 perl tidy 모듈을 사용하면 읽기 어려워 보이는 펄 코드도 줄바꿈/인덴트 등을 맞춰서 보여준다고 합니다.

+1점 날리고 갑니다... :-)

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.