2008. 6. 5. 17:45

정규표현식과 코드골프에 관한 IRC로그

어제 IRC에서 나온 뼈가되고 살이되는 펄 얘기 입니다.
주로 간단한 정규 표현식으로 뭘 할 수 있는지 에 관한 얘기죠.
재미있는 로그라 모두 긁어왔는데 좀 기네요. 132줄!!


하지만 읽기 귀찮으신 분들을 위해서 정리도 해드리는 센스!!
두개의 문제가 나왔는데

1.  연숙된 문자열에서 숫자의 앞뒤에 공백 넣기

"11aa11bbcc222d" 를 "11 aa 11 bbbb 222 d" 로 바꾸는 거죠.
간단한 문제이니 만큼 답도 간단합니다.
s/(\d+)/ $1 /g

또는
perl -pe 's/(\d+)/ $1 /g'


2. perldoc 문서 이름을 위키네임으로 바꾸기

twiki에 perldoc관련 플러그인을 만들다가 나온 문제입니다.
perldoc은 perlsub, perlreftut처럼 perl로 시작하고 모두 소문자로 되어있는데
이걸 PerlSub, PerlReftut 처럼 perl의 P와 perl 뒤으 문자 하나 총 2개의 대문자를 가진 문자열로 바꾸는 문제입니다.
다음 코드들에서 print가 나왔다가 안나왔다가 하는 이유는 저는 문자열 반환이 목적이었고, saillinux님과 aero님은 출력이 목적이었기 때문입니다. 알아서 잘 해석해주세요^^
 문자열이 $_에 저장되어 있다고 가정하면
처음에 나온 코드는  saillinux 님의
print "Perl".join '', map {ucfirst}split(/perl/, "$_");

오 훌륭하군요,
약간 바꿔보면
 print join '', map ucfirst, /(perl)(.*)/;

이렇게도 가능하지요.

제가 정규표현식을 써서 만든 코드는 
s/(perl)(.*)/ucfirst$1.ucfirst$2/e


이걸 코드 골프용으로 고치면,, 보기에는 지저분 하지만
/l/;ucfirst$`.'l'.ucfirst$

이렇게 만들 수 있습니다.

이걸 보여드렸더니 aero님께서 다른 아이디어를 제시하시더군요
print map "\u$_",/(perl)(.*)/


호~~ \u가 있었군요. 저는 \U는 알고 있었는데, \U는 한문자에만 적용되는 것이 아니라 \E와 쌍을 이루는 것이어서 못쓰고 있었거든요. 그래서.. 잽싸리 저도 코드를 바꿔봤습니다.
/l/;"\u$`l\u$'"

오호. 마지막 코드를 보신 aero님께서 한 말씀 날려주시더군요
ㅂㅌ

추가:2008/06/08
오늘 아침에 나온 아이디어입니다.
s/(perl|.*)/\u$1/g

우왕~~


코드에 대한 자세한 설명은 saillinux 님께서 해주시리라 믿습니다.
2008. 4. 17. 09:26

원라인 펄 놀이 - 첫줄 빼고 sort

#perl 에서 saillinux님과 JEEN님의 "쉘에서 파일의 첫 줄을 빼고 소팅하려면"이라는 대화내용을 듣다가 이를 위한 몇가지 아이디어가 떠롤랐다.

파일의 첫줄을 출력한다 던가 마지막 줄을 출력하는 것은 head나 tail로 쉽게 할 수 있지만 첫 줄을 빼고 출력하는 방법은?

1. 다음과 같은 saillinux 님이 가르쳐 주신 위대한 방법도 있다.
   
tail -n `expr \`wc -l file-to-sort | awk '{ print $1 }'\` - 1` file.txt
오.. 왠만한 내공이 아니고는 만들기도 힘든 구문!! `` 안에 ``를 쓰는 센스!!
옛날 연구실의 한 선배는 awk 두개를 써서 더블 루프을 구현하기도 했었다.

그러나 다행히도 더 간단한 방법이 있다.

2. tail
tail -n +2 file.txt
언제부턴지는 모르겠지만 tail 에 "앞에서 몇줄부터" 출력해주는 기능이 생겼다.
간단히 +를 숫자앞에 붙이면 끝이다. 문제는, 이 기능이 언제부터 생긴건지 모르기 때문에 호환성이 좀 걱정된다는 사실.

3. sed
sed -n '2,$p' file.txt 
오래 전부터 이런 일은 awk,  sed 가 강자였지..

그러나 진정한 강자는 따로 있는 법

4. perl
perl -ne'$.>1 and print' file.txt
perl -ne'2..-1 and print' file.txt
perl -ne'2..eof and print' file.txt
오.. 가장 "리더블" 하지 않은가!!(물론, $.을 알아야 하지만)

이제 남은 건 sort 하는 일뿐!! 이건 뭐... 첫줄은 출력하고 나머지는 sort하면 된다.
head -1 file.txt; perl -ne'$.>1 and print' file.txt | sort

그러나 여기서 끝내기엔 너무 쉬운 내용을 너무 길게 썼다.
뭔가 더해보자.
소팅하고 출력하는 것을 펄 안에서 끝내보자.
목표는 : 텍스트를 다 배열에 저장하여 첫줄 빼고 소팅한 다음 출력한다.

perl -ne'push @L, $_;END{print $L[0],sort @L[1..$#L];}' file.txt

잘 되긴 하는데,, 뭔가 아쉬운 이 느낌은 뭘까, 너무 당연한 코드라서 재미가 없다.
게다가 매줄마다 push를 하는건,, 너무 비싸다는 생각이!!
모든 줄을 한꺼번에 배열에 넣을 방법은 없을까?
음, 이럴땐 첨부터 꽁수를 생각해보자.
perl -ne'$f=$_;@l=<>;print $f,sort@l;last' file.txt
오옷!! 이거 그럴 듯 하다!! 더 꼬아보자!!
 perl -ne'@l=<>;last}{print $_,sort@l' file.txt
매우 맘에 드는 코드가 나왔지만, 펄을 새로 시작하는 사람에게는 절대 보여줘선 안될 코드 같다.


오늘의 새로운 아이디어!!

1.  파일을 읽어서 배열에 넣는 방법
perl -ne'@L=($_,<>)' file.txt


2. perl -ne에서  END{}를 쓰기 귀찮다면 }{를 쓰면 된다.
perl -ne'push @L,$_ }{ print sort $L'




2007. 12. 11. 03:01

코드골프 grid-computing

새로운 코드골프 문제가 나왔습니다.
http://codegolf.com/grid-computing
http://kldp.org/node/89102

문제의 내용은 다음고 같은 2자리 숫자로 이루어진 10x10 테이블을 받아서


01 34 46 31 55 21 16 88 87 87
32 40 82 40 43 96 08 82 41 86
30 16 24 18 04 54 65 96 38 48
32 00 99 90 24 75 89 41 04 01
11 80 31 83 08 93 37 96 27 64
09 81 28 41 48 23 68 55 86 72
64 61 14 55 33 39 40 18 57 59
49 34 50 81 85 12 22 54 80 76
18 45 50 26 81 95 25 14 46 75
22 52 37 50 37 40 16 71 52 17

가로 세로 합(총 20개) 중에 최대값을 출력하는 것.

예전에도 몇번 코드골프문제를 풀어본 적이 있지만 순위권에 들기가 너무 힘들어서 좌절 한 적이 있었는데
이 문제는 나온지 얼마 안되기 때문에 이때다 하고 달려들었습니다.
다행히 53글자로 순위권에 안착~~.
시간이 지나면 밀려나겠지만 일단 4위에서 캡춰!! 현재는 6위 -_-;;;;

코드를 공개하고 싶어서 입이 아니 손이 근질근질 거리지만 혹시라도 이 포스트를 읽으실 분의 즐거움을 위해서 당분간 공개하지 않기로 합니다.  비공개 포스트라도 만들어서 임금님 귀는 당나귀 귀라도 외쳐야 겠네요.