2009. 3. 24. 18:41

일전한 글자수의 단어 세기

http://kldp.org/node/104031 를 보고 aero님과 얘기하다가 시작되었다.

문제의 내용(사실은 문제의 일부)는 다음과 같은 문자열에서 AA, AT, AG, AC....의 개수를 세는것

ATCGATCGATCGATAAAC
GATCTAGCTAGCATAACC

앞에서 부터 두글자씩 세는건 아주 단순하다.

$count{$_}++ while $str =~ /(..)/g


하지만 aero님의 문제제기,

앞에서 부터 2글자씩 세는 것이 아니라 임의의 두글자라면 어떻하죠?

먼저 aero님의 구현은
 while ( $str =~ /(..)/g ) {
    $count{$1}++;
    pos $str -= 1;
}
오 멋지다.  마지막으로 두글자의 다음 위치인 pos($str) 의 위치를 뒤로 한글자 돌려서 다시 검색한다.
2글자가 아니라 N글자라면 pos $str -= N-1 이라고 해주고 정규표현식을 조금 바꿔주면 끝.

나의 구현도 매우 비슷하다. 다만 perl 정규표현식의 \G앵커를 사용했다는 정도

pos($str) = 1;
while ( $str =~ /(.\G.)g ) {
    $count{$1}++;
}


처음 pos를 정해놓고 현재 pos위치를 의미하는 \G앵커를 이용하여 검색.. (자세한 내용은 perldoc perlre)
N글자의 단어를 찾으려면 pos위치를 N-1로 하고 /(.{$N-1}\G.)/g 로 바꾸면 끝..
N글자에서는 aero님의 코드가,, 몇글자 짧아지긴 하겠군요

글자수도 거의 같고, 효율도 거의 비슷하겠군.

원라이너 용으로 내 코드를 정리해 보면

perl -nle'pos=1;$c{$1}++ while /(.\G.)/g}{print"$_\t$c{$_}"for sort keys %c' filename


되겠다.

추가로 Luz♡lunA 님의 말씀

 <Luz♡lunA> [hanIRC] c식으로 하면 그냥 한글자씩 뽑으면서 prev를 저장해가면서 진행하면.....

맞습니다.
이게 정석인거죠.