@a=<>; # 표준입력을 배열에 저장하고map { # 입력의 각 행에 대하여split/ /; # 공백으로 구분하여 3개의 숫자로 된 배열을 만들어 @_에 담고$s[$_[1]][$_[0]]=chr$_[2] # 스트링의 2차원 배열에 해당 위치에 해당 문자를 담는다}@a;map { # 이제 출력 map{print$_?$_:' '}@$_; # 문자가 없는 좌표는 스페이스 출력 print"\n"}@s
굳이 @a라는 임시 배열을 쓸 필요가 없고, split은 인자를 주지 않으면 알아서 스페이스를 구분자로 사용하므로[2]
"어느 좌표에 저장된 문자가 있으면 그 문자를, 없으면 스페이스를"이라는 문제를 해결하기 위해서 계속 "||"연산자를 사용했는데, printf를 써서 "%1s"로 인자를 주어서 출력하게 하는 버전들[6][7][8]. 그러나, 결과적으로 이건 홀인원을 향한 길에 도움이 되지 못했음. 오히려 벙커에 빠진 셈이랄까.
한 글자 스트링들의 2차원 배열 대신에 각 라인을 나타내는 스트링들의 1차원 배열로 만든 jg님의 버전 등장[9]. 이하의 진행에서는 계속 jg님이 힌트를 듣고서야 주인장도 진행할 수 있었다. ㅠ,.ㅡ
입력되는 좌표의 순서가 중구난방이기 때문에, 어떤 행을 구성한 후 다시 그 행 어느 열의 좌표가 들어오면 기존 행에 합쳐주어야 하는데, 스트링에 대하여 bitwise OR 연산을 사용.
jg님의 글[10]
이거 전에 Beginning Perl 읽으면서 Perl/디버깅에도 적어뒀던 것들인데... 명령행 인자를 사용해서 켤 수 있는 스위치들을 일일이 외우기도 싫고 해서 그냥 적어두기만 하고 잊고 있었는데 여기에 비밀이 있었다.
아래와 같이 실행하면
$ perl -n -e '코드'
Perl은 아래와 같이 가정하여 수행한다.
while (<>) {
코드
}
명령행 인자가 아니라 shebang 라인에 적어 줄수도 있다.
#!perl -n
코드
근데 우리가 작성하는 프로그램은, 일단 표준 입력을 전부 다 읽어서 스트링을 구성하는 단계와, 완성된 스트링을 출력하는 단계로 나누어지기 때문에, 저렇게 코드 전체가 루프 안으로 들어가버리면 곤란하다...라고 생각을 했는데...
다음과 같은 사기스러운 코드가 가능하더라.
#!perl -n
코드1
}
{
코드2
이러면 이게 아래처럼 해석된다! -_-;;;
while (<>) { # Perl이 루프의 시작을 붙여주고,
코드1
} # 여기서 첫번째 단계의 루프가 끝나고 -_-;
{ # 새로운 블럭이 시작되면서
코드2
} # Perl이 닫는 중괄호를 붙여준다 -_-;;;;
-n 대신에 -p를 쓰면 Perl이 알아서 print까지 한다
#!perl -p
코드
# 이것은 아래와 같이 해석
LINE:
while (<>) {
코드 # your program goes here
} continue {
printordie"-p destination: $!\n";
}
그리고 -l 옵션을 주면 print를 할 때마다 뒤에 $\ (the output record separator)의 값을 붙이는데 이게 기본값이 "\n"이다.
따라서 아래와 같은 게 가능해지고, 여기까지가 주인장이 알고 있는 것만으로 할 수 있는 최선의 코드였다.
이제 1바이트가 남았는데... jg님의 말을 빌자면, 위 코드에서, 두 글자로 표현된 것을 한 글자로 줄일 수 있다 이것도 사기라면 사기인데, 어쨌거나 해보니까 되더라.
#!perl -lp
비밀 :-P
힌트는, "메모장으로는 안 되고 vi나 emacs로는 됨"
주인장도 그 비밀이 뭐였는지 생각이 안 났다가.. 다시 생각이 났다.
"\0" 이라고 표기된 두 바이트를, 널 캐릭터(0x00)로 바꿔쓰면 된다... -_-; ViEditor에서 널 캐릭터 입력은 Ctrl+V,Ctrl+@
이것과 별도로, vi에서 저장하니 시키지도 않았는데 꼭 끝에 "\n"을 붙여버려서 1바이트 늘어나 버린다. (윈도우 gvim에서는 "\r\n"을 붙여서 2바이트) "set noeol binary" 옵션을 주어서 저장하면 끝에 "\n"을 붙이지 않긴 하는데, 리눅스에서 그 상태로 실행하면 에러가 나더라.
$ perl ascii.pl < input
Unrecognized character \x11 at ascii.pl line 2.