태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.


http://golf.shinh.org/p.rb?Morse+decode


이번 문제에서는 input으로 모스부호가 들어오면 이걸 해석하여 문장을 출력해야 합니다.

이 문제의 경우, 짧은 신호는 '.', 긴 신호는 '-', 띄어쓰기는 ' ', 글자마다의 구분은 '/' 으로 되어있습니다.

예를 들어, input 으로
가 들어오면
를 출력하면 됩니다.


문제의 요지는 크게 두가지로 나뉩니다.

1) input에서 /를 기준으로 글자들과 띄어쓰기를 분리해내기.

2) a에서 z까지, 그리고 쉼표와 마침표에 해당하는 모스 부호를 맵핑하기.


1번의 경우, 정규표현식을 사용하면 간단합니다.

모스부호는 .과 -로만 이루어져있고, 띄어쓰기는 스페이스 하나 이므로

로 표현할 수 있습니다. /는 위 정규식에 매치되지 않기 때문에 자연스럽게 걸러집니다.

문제는 모스코드를 맵핑하는 방법인데요, 일단 제일 먼저 머릿속에 떠오른 방법은 해시테이블을 사용하는겁니다.



이렇게 해서 나온 최종 코드는 다음과 같습니다.




아주 잘 동작하기는 하지만 무려 480바이트로 너무 깁니다, 저걸 줄인다고 그렇게 큰 성과가 나올것 같지도 않습니다.









두번째로 생각한 방법은 gsub를 사용해서 모스부호를 글자로 고치고, /를 지워버린 후 출력하는 방법인데요

대략 이런 식의 코드가 나왔습니다.



388바이트. 아까보다는 훨씬 줄었지만, 이걸 eval과 array.join 을 적절히 사용하여 줄여본다 해도 200바이트 미만으로 내려가기는 힘들 것 같습니다.











세번째로 생각한 방법은 .를 0으로, -를 1로 고친 후 맨 앞자리에 1을 붙여서 나온 이진수를 index로 사용하여

a~z, 쉼표, 마침표, 띄어쓰기가 들어간 문자열상수로부터 해당 글자의 아스키 코드를 골라낸 다음 putc 함수로 출력하는 방법이었습니다.

다음과 같이, 각 글자들은 그 글자를 나타내는 모스부호를 적절히 변환하여 하나의 숫자로 표현할 수 있습니다.


그런데, 자세히 보시면 이 숫자들 중에 겹치는 수는 단 하나도 없으며, 단 두개의 숫자를 제외한 모든 수가 30보다 작다는 것을 알 수 있습니다. 보기 쉽게 정렬하면 다음과 같이 됩니다.



이러한 원리를 이용하여 86바이트까지 줄일 수 있었고, 현재 공동 1위에 올라있습니다

그래도 아직 종료시각 까지 25일이나 남아서 누군가가 이 기록을 깰 가능성이 크기 때문에 장담은 못하겠습니다. -_-; 

세번째 방법으로 작성한 코드는 경기 종료 후 공개하겠습니다. ㅎㅎ


=================

아악 벌써 순위 뒤편으로 밀려나버렸네요 -_-; 86바이트로는 택도 없어요 -_-;;

무서운 사람들.. ㄷㄷ

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by leonid

심심해서 369게임을 작성해봤습니다.

369게임에서 제일 중요한 요소는 아무래도

"주어진 숫자에 대해 몇 회 박수를 쳐야 하는지 계산하기" 인 것 같습니다. ㅎㅎ

숫자 안에 포함된 3, 6 또는 9의 개수만큼 박수를 치거나, 만약 3,6,9가 없을 경우 해당 숫자를 리턴하면 됩니다.

예를 들어, 307은 박수 한번, 9936은 박수 네번, 400은 "400"이라고 말하면 됩니다.

이걸 구현할 알고리즘을 연구하다가 다음과 같은 코드를 생각해봤습니다.



여기서 n이 주어진 숫자입니다. 숫자를 문자열로 바꾼 후, tr  명령을 사용해서 '3', '6', 그리고 '9'를 제외한 다른 문자를 지운 후, 남은 문자열의 길이를 구하는 겁니다. 이 길이가 바로 필요한 박수 횟수입니다.

그 다음, "clap "이라는 문자열을 방금 구해낸 박수 횟수만큼 복사합니다. 1이면 "clap ", 2이면 "clap clap ", 3이면 "clap clap clap ", 0이면 "" 이 되겠죠.

그 다음 max 함수를 사용하여 마지막으로 n을 문자열로 바꾼 스트링(num_s)과 비교하여 더 우선순위가 높은 문자열을 리턴하도록 합니다.
만약 박수 횟수가 0이면 왼쪽의 스트링은 ""이 되고, 빈 문자열은 무엇이든 들어있는 문자열보다 무조건 우선순위가 낮습니다. 따라서 우측의 숫자가 리턴됩니다.
만약 박수 횟수가 1 이상이면, 왼쪽의 스트링은 "clap clap ..."이 되는데, 문자열 끼리의 비교 과정에서 왼쪽 스트링의 첫번째 문자는 무조건 'c'가 되고, 오른쪽 스트링의 첫번째 문자는 무조건 숫자입니다. 'c'가 '1'~'9'보다 더 아스키코드 값이 크기 때문에 max 함수를 통하여 왼쪽의 스트링이 리턴됩니다.

루비 언어를 쓰고 있기 때문에 이런 복잡해보이는 알고리즘을 간단한 코드로 구현할 수 있었습니다.
만약 C나 C++을 쓰고 있었더라면 코드가 굉장히 길어지겠죠. ㅎㅎ

이외에도 사용자의 입력에 대한 예외처리, 채팅방에서 369게임을 하는 것처럼 보이기 위한 꾸미기, 컴퓨터와 같이 하기, 어설픈 OOP(-_-;) 등 여러 자질구레한 사항들을 추가하다보니 코드가 좀 길어졌습니다. 간단한 게임도 생각보다 만만치 않네요. -.-;


소스코드는 아래와 같이 생겼습니다. 좀 눈아프게 생기긴 했지만 그래도 저 나름대로 예쁜 코드, 버그 없는 코드를 만들어보려고 노력해봤습니다. -.-;




아래는 소스코드 파일이고, 혹시 루비 인터프리터가 설치되어있지 않은 분들을 위해서 exe버전(rubyscript2exe 사용)도 같이 첨부합니다. ㅎㅎ



크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by leonid


38 bytes.

I took the idea from eban (http://jarp.does.notwork.org/diary/) 's 39B code :


which saves 3 bytes by changing $_.size into ~/$/.

However, since regexp ignores newline characters, we can remove -l option, thus saving one more byte.


http://jp.rubyist.net/magazine/?0023-RubiMaGolf


크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by leonid

42 bytes.

-------------

shinh님이 주최한 코드골프 이벤트에 트랙백 보내기 위한 글입니다.

주소 : http://jp.rubyist.net/magazine/?0023-RubiMaGolf

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by leonid

루비를 애용하시는 많은 분들의 고민 중 하나가 바로 배포 관련 문제일 겁니다.

대부분 컴퓨터에는 루비 인터프리터가 설치되어있지 않기 때문에 자신의 루비 코드를 배포하려면 인터프리터 까지 다운 받도록 해야 합니다.

하지만 몇 kb 되지 않는 루비 코드를 실행시키려고 20메가 가량 되는 인터프리터를 추가로 기꺼이 다운받으려는 분들이 그리 많지는 않을 겁니다. 특히, qtruby 처럼 외부 라이브러리가 필요한 경우는 문제가 더욱 심각해집니다. 용량의 문제보다도, 이들을 설치하기에는 너무 바쁘고 귀찮습니다.

다행히도 이러한 문제를 해결해주는 두 프로그램이 있습니다. tar2rubyscript와 rubyscript2exe 라는 프로그램인데요, tar2rubyscript는 여러개의 루비 코드를 하나로 묶어주고, rubyscript2exe는 루비 코드를 완전히 독립된 응용프로그램 (윈도우용 exe, 리눅스용 또는 맥용 바이너리) 으로 만들어줍니다.

두 프로그램 모두 하나의 루비 코드로 되어있고, 별 다른 설치 필요없이 바로 작동합니다. 물론 루비 인터프리터는 있어야 겠죠

사용법은 간단합니다.
커맨드라인 창에서 ruby rubyscript2exe.rb application.rb 를 입력하시면 해당 폴더에 application.exe 라는 파일이 생기고, 이를 곧바로 배포할 수 있습니다. 이렇게 생성된 프로그램은 시작하기 전에 동작에 필요한 파일들을 수집합니다. 이 때문에 프로그램 실행 시 약 5초 정도의 딜레이가 있습니다.

커맨드라인 창에서 ruby tar2rubyscript.rb program/ 를 입력하시면 해당 폴더에 program.rb 가 생성됩니다. 이 파일 하나가 program/ 폴더 안의 여러 루비 코드 들을 모두 포함하고 있습니다. 메인으로 실행 시켜야 할 코드의 이름을 init.rb 로 해주셔야 잘 작동합니다.

간혹 init.rb 를 폴더 안에 넣었음에도 program 폴더로부터 생성한 program.rb를 실행 할 시 init.rb가 없다면서 오류가 나는 경우가 있습니다. 왜인지는 잘 모르겠지만, 이럴 경우에는 폴더를 지우고 ruby program.rb --tar2rubyscript-justextract 를 실행하여 압축을 풀어서 program 폴더를 얻습니다. 이 폴더에 다시 ruby tar2rubyscript.rb program/ 명령을 실행시키면 이 때 만들어지는 program.rb는 잘 작동하게 됩니다.

rubyscript2exe와 tar2rubyscript는 윈도우, 리눅스, 맥에서 모두 작동합니다.

rubyscript2exe의 경우 맥에서 이용하려면 eee_darwin 이라는 파일을 자신이 직접 컴파일 해야 하는데, 제작자 홈페이지에서 지시하는 대로 따라서 하면 됩니다. 그런데 최신 버전 맥에서는 제대로 작동하지 않더군요.


이 프로그램 들은 각각 다음 주소에서 다운 받으실 수 있습니다. 루비 코드 뿐 아니라 gem 형태로도 배포하고 있습니다. 여러가지 옵션들에 대한 설명들도 있으니 들어가서 읽어보시면 도움이 됩니다.

http://www.erikveen.dds.nl/rubyscript2exe/#6.0.0
http://erikveenstra.nl/tar2rubyscript/index.html#6.0.0


예시로 qtruby의 example에 있는 tetrix라는 게임을 하나의 exe 파일로 만드는 과정을 녹화해봤습니다.

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by leonid


평소에 테스트 주도 개발 (TDD, Test-Driven Development)을 익혀보려고 했지만 계속 미뤄왔다가, 이번 기회에 비로소 TDD로 뭔가를 작성해보게 되었습니다.

TDD는 코드를 작성하기 이전에 앞으로 작성될 코드에 대한 테스트를 먼저 작성하는 개발 방법론으로, 개발 사이클 주기가 짧아서 쉽고 빠르게 개발을 할 수 있으며 많은 테스트를 수행하므로 버그도 비교적 적게 발생한다고 합니다.

TDD에서는 다음의 단계들을 한 사이클로 하고, 이 사이클을 유한번 반복하는 방식으로 개발을 합니다.

1. 새 테스트 작성하기 (이 테스트가 시험할 코드를 작성하지 않았으므로 거의 대부분 실패합니다.)
2. 새 테스트를 통과할 수 있도록 수단과 방법을 가리지 않고 코딩하기
3. 코드가 새 테스트를 통과하는지 확인하기
4. 코드 리펙토링하기

무슨 말인지 잘 모르겠지만 일단 여기 쓰여있는 걸 바탕으로 프로그램을 작성해봤습니다.

처음부터 크고 어려운걸 하면 기가 죽을것 같으므로 일단 간단한 프로그램부터 시작해야될것 같아서
숫자 세자리 마다 콤마 찍는 프로그램을 작성하는 모습을 동영상으로 찍어봤습니다.

예를 들어 1234567이 있으면 "1,234,567"이 되겠죠 ㅎㅎ

Textmate에서 Ruby 언어로 작성했습니다.






첫번째 동영상을 올리고 나서 좀 생각해보니 음수에 대해서 테스트를 안했었다는 걸 깨달았습니다.


그래서 음수에 대한 테스트를 추가하는 동영상을 다시 녹화했습니다.







두번째 동영상을 올리고 다시 생각해보니까 이번에는 소수점을 포함한 숫자에 대한 테스트를 안했더군요 -_-;;


그래서 추가로 다시 녹화했습니다.






제가 미처 생각하지 못한 부분이 또 있을지도 모르지만, 그래도 일단 콤마찍기 프로그램은 이쯤으로 끝냅니다. -_-ㅋ


최종적으로 나온 코드의 모습은 다음과 같습니다.


comma.rb


test_comma.rb





온라인으로 대충 훑어본 내용만 보고 막무가내로 해봤는데.. 이렇게 하는게 TDD 인지 잘 모르겠네요 -_-;;

관련 서적 중에 많은 분들이 추천하시는 책이 있어서 한번 사서 공부해보렵니다. ㅎㅎ

테스트 주도 개발 (CD-ROM 포함) 상세보기
켄트 벡 지음 | 인사이트 펴냄
최근 주목받고 있는 프로그래밍 방법인 테스트 주도 개발, 즉 TDD를 설명한 최초의 책이자, 가장 권위적인 책. 테스트 주도 개발을 퍼뜨린 장본인이며 객체 지향 프로그래밍의 선구자 중 한 사람인 켄트 벡이 직접 썼다. '테스트 주도 개발(Test-Driven Development)'은 테스트가 개발을 주도하는 방법이다. 테스트가 개발을 주도한다는 것은 테스트가 코딩의 방향을 이끌어 간다는 말이다. 테스트를 실패하는 코드가 없으면 코딩


크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by leonid

최근 이틀 동안 QtRuby를 설치하기 위해 꽤 애를 먹었습니다. 그래서 혹시 저와 같은 일을 겪으실 것 같은 분들을 위해 이렇게 글을 씁니다.

Qt는 Trolltech사(Nokia에 인수됐죠)에서 만든 GUI 라이브러리입니다. 말하자면 MFC 같은거죠. 여러모로 기타 GUI 라이브러리들에 비하여 장점이 많아서 꽤 유명합니다. KDE 리눅스, 구글 어스 등 많은 유명한 애플리케이션 들에 사용되고 있죠.

원래 Qt 라이브러리는 C++ 언어를 쓰게 되어있지만, 여러가지 다른 언어들의 바인딩도 나와있습니다. 저는 C++보다는 Ruby언어를 좋아하므로 QtRuby를 선택하게 되었습니다.

QtRuby의 최신 버전인 QtRuby 1.4.9를 설치하기 위해서는 다음과 같은 파일들이 필요합니다.
  1. qt4-qtruby-1.4.9.tgz : 이건 당연히 필요
  2. qt-mac-opensource-src-4.3.3.tar.gz : Qt 라이브러리가 있어야 합니다. 그런데 최근에 나온 4.3.4나 4.4.0beta1 로는 QtRuby 1.4.9가 빌드되지 않더군요. Qt를 컴파일 할 때 -no-framework 플래그도 넣어보고 여러가지 조합을 시도해봤지만 실패했습니다. QtRuby 포럼에서 보니 버그 비슷한거라더군요. -_-; Qt 4.3.3 버전으로는 플래그를 따로 지정을 하지 않아도 빌드가 잘 됐습니다. 사실 이걸 알아내느라 고생을 한겁니다. Qt가 빌드 한번 하는데 시간이 오래걸리니까 한번 시행착오 할때마다 시간낭비가 심하죠..
  3. cmake-2.4.8-Darwin-universal.dmg : cross-platform make 라고 하는 프로그램인데 윈도우, 맥, 리눅스에서 모두 동작하는 소프트웨어인 것 같습니다. QtRuby 1.4.9를 컴파일 하려면 이게 있어야 한다네요.
이 파일들을 ~/Desktop 에 받았다고 가정하고 계속 진행합니다.

먼저, cmake를 설치합니다. dmg파일을 열고 패키지를 열면 알아서 다 해줍니다.

다음으로 Qt 4.3.3을 설치해야 하는데, C++ 컴파일러가 있어야합니다. 뭐 다들 있으시겠지만, 전 설치 당시에 그게 없어서 -_-; 맥에서 제공해주는 Xcode 유틸리티를 설치했습니다.
터미널을 켜고 다음 명령들을 순서대로 실행합니다.



빌드 되는데 오랜 시간이 걸릴 것이므로 잠시 다른일을 하고 계시다가 Qt 설치가 끝나면 다음 명령을 해줍니다.



그리고 위 두줄을 ~/.profile 파일에 넣어줍니다.

echo $PATH 를 해서 나오는 주소 중에 /usr/local/Trolltech/Qt-4.3.3/bin 이 있는지 체크해봅시다. 없으면 좀 있다가 QtRuby를 설치 할 때 Qt가 있는 폴더를 찾을 수 없어서 설치 할 수가 없습니다.

이제 QtRuby를 설치합니다.

이제 irb를 열고 QtRuby가 잘 설치되었는지 확인합니다.


true가 리턴되면 잘 설치된겁니다.

QtRuby의 프로젝트 홈페이지 -> http://rubyforge.org/projects/korundum/

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by leonid

http://codegolf.com/choose


최근에 코드골프 홈페이지에 새로운 문제가 등장했습니다.

이번 문제는 다른 문제들에 비해 비교적 간단해서 풀기 좋았습니다.

input으로 n과 k값이 들어오는데 이를 이용해서 을 구하는 문제입니다.


Test case는 대략 이런식으로 생겼습니다.


input을 받는 방식은



이외에는 딱히 좋은 방법이 없어보이므로

어떤 방식으로 계산하느냐가 승부의 관건인 것 같습니다.

저는 거의 5일간 밤새면서 이 문제에 매달려서 고민하던 도중 헬스장에서 운동하다가 갑자기 떠오른 방식을 사용해서 36바이트로 Ruby부문 공동 1위를 먹었습니다.

수학 좋아하는 분들이라면 이 방식을 금방 캐치해내실듯 하네요 :)

사용자 삽입 이미지


------------

Python으로도 39바이트로 공동1위 -_-v

사용자 삽입 이미지



크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by leonid

http://golf.shinh.org/p.rb?leap+year

최근에 shinh씨의 골프서버에 재밌는 문제가 등록됐습니다.

데드라인이 지나서 모든 소스들이 공개됐기 때문에 이번에 디테일하게 한번 살펴보겠습니다.

사용자 삽입 이미지

사용자 삽입 이미지


보시는 바와 같이 input에서 각 라인마다 주어지는 연도가 윤년인지를 파악하여 알려주는 간단한 문제입니다.

위의 입력/출력 예시만 보고 몇가지 승부의 관건을 생각해낼 수 있습니다.

1. 윤년 계산하는 알고리즘
2. 입출력 방식


주어진 연도가 윤년인지를 판단하는 알고리즘은 구글을 대충 검색하시면 나옵니다.

1. 4로 나누어 떨어지면 윤년
2. 100으로 나누어 떨어지면 윤년이 아님
3. 400으로 나누어 떨어지면 윤년

그런데 이번 문제의 경우 윤년이 아닌지를 판단해서 해당 경우 스트링 "not"을 붙여줘야 하므로 조건을 뒤집어야 합니다.

1. 4로 나누어 떨어지지 않으면 윤년이 아님
2. 100으로 나누어 떨어지면 윤년이 아님
3. 400으로 나누어 떨어지지 않으면 윤년이 아님

조건을 좀더 간단하게 하면

1. 4로 나누어 떨어지지 않거나
2. 100으로 나누어 떨어지면서 400으로는 나누어 떨어지지 않으면 윤년이 아님

코드로 작성하면
이 됩니다. 여기서 y가 연도.

여기서 좀 더 줄여보면
으로 할 수 있습니다.

100과 400에서도 각각 1바이트씩 줄일 수 있네요.
여기서 ?d는 'd'의 ASCII 코드 (100이죠)를 뜻하고, $$는 프로세스 넘버를 뜻합니다. 프로세스 넘버는 코드를 실행시킬 때마다 달라지므로 $$가 400이 되려면 운이 필요하겠죠.

input을 받아들이는 방식은 여러가지가 있지만

이번 문제에서는 커맨드라인 옵션을 쓰는 것이 바람직해보입니다.

stdin으로 들어오는 문자열을 한 줄씩 읽어들이는 옵션에는 n과 p가 있는데

p의 경우 코드가 실행된 후 $_ (읽어온 해당 라인) 를 print로 출력하기 때문에 더 유용합니다.

왜냐 하면 sample output을 보았을 때 input으로 들어온 연도의 뒷부분에 스트링이 붙어서 출력되게 하면 되므로
와 같은 식의 코드가 가능해지기 때문입니다.

만약 n 옵션을 사용했더라면
같은 식의 코드가 되겠죠. 3 bytes 손해입니다.

아 그리고 $_ 의 마지막 character는 "\n" 일 것이기 떄문에 l 옵션을 같이 붙여줘야 할 것입니다.

이제까지 생각해본 것들을 바탕으로 코드가 완성되었습니다.

76 bytes 입니다.

1 byte 더 줄일 수 있네요. if와 y 사이에 공백이 하나 들어있던걸 절약한 겁니다.


이 방식으로는 75B 가 한계인것 같네요.

그런데 제가 이 코드를 생각해냈을 당시 1위가 64B 였습니다. 다른 방법을 찾아봅시다.

Ruby의 Standard Library에는 Date라는 클래스가 있습니다.

이 클래스에는 Date.leap? 이라는 함수가 있죠. 인자로 정수를 받아서 이게 윤년인지를 계산하여 true나 false를 리턴해줍니다. 이 함수를 사용하려면 require'date' 를 해야하지만 커맨드라인 옵션 #!ruby -rdate 로도 할 수 있습니다. 마침 다른 커맨드라인 옵션도 사용하고 있으니 후자의 방식으로 작성해야 더 유리하겠지요.

그리하여 다음과 같은 코드가 가능해집니다.

길이가 훨씬 줄었습니다. 하지만 여전히 68B 네요. 아직도 4바이트나 더 줄여야 합니다.

그런데 이 방식으로는 68B가 한계인것 같습니다. 다른 방법을 찾아봅시다.

처음의 알고리즘을 자세히 살펴보면 뭔가 4 라는 숫자가 많이 나오는걸 볼 수 있습니다.

연도가 100으로 나누어 떨어지는지, 떨어지지 않는지에 따라 400으로 나눠보느냐, 4로 나눠보느냐의 차이가 있는 겁니다.

따라서 100으로 나누어 떨어지는 경우 미리 100으로 나눠버리고 나면 이 경우도 마찬가지로 4로 나눈 나머지를 따라 윤년인지 아닌지를 판단할 수 있습니다.

미스테리가 슬슬 풀리기 시작합니다.

input으로 각 라인마다 주어지는 연도 $_는 처음부터 정수가 아니라 String 이라는 걸 잘 생각해보세요.

코드골프의 꽃이라 할 수 있는 정규 표현식(Regular Expression / regexp)을 쓰는겁니다.

100으로 나누어 떨어지는지를 검사하려면 $_의 끝부분에 '00' 이 있는지를 알아내면 됩니다.

정규표현식으로 쓰면 /00$/ 가 되겠네요. 여기서 $는 스트링의 끝부분이라는 뜻입니다.

그 다음 string.sub 함수를 사용해서 그 부분을 없애버립시다. 정규표현식이나 문자열을 받아서 그 부분을 스트링 내에서 찾아낸 다음 바꿔주는 함수입니다.

정도가 되겠네요.

그런데 Kernel.sub 라는 함수가 있습니다. 이 함수는 $_.sub 를 실행시킵니다.


따라서 로 줄일 수 있습니다.

그런데 여기서 정규표현식 /00$/ 를 /00/로 줄이면 안될까요?

뒤의 $를 제외시키면 "2002"나 "2008" 같이 연도의 가운데에 "00"가 있는 경우도 찾아내서 없애버립니다.

그렇게 되어 1008, 3008, 3002 등등 몇몇 연도의 윤년 여부를 제대로 계산하지 못해버리고 맙니다.

그런데 이 문제의 경우 연도의 가운데에 "00"가 들어가는 경우는 "2008"과 "2000" 밖에 없으며,

다행스럽게도 얘네들은 /00$/에서 $를 제외시킨 상태로 코드를 실행시켜도 윤년 여부가 제대로 계산됩니다.

따라서
로 더 줄일 수 있게 됩니다.

이를 바탕으로 코드를 작성하면
로 65B가 됩니다. 이제 한 바이트 남았군요.

하지만 이 방법으로는 65B가 한계인것 같습니다.

이번에는 $`를 사용해봅시다. $`는 가장 최근의 정규표현식에 매치된 부분의 앞부분이 저장되는 변수입니다.

다시 말해, $_="2000" 을 $_=~/00$/로 매치하고 나면 $`=="20"이 되는거죠.

그렇다면, 만약 매치가 안될 경우에는?

아쉽게도 $`==nil이 되어버리는군요. 정규표현식을 약간 수정해야 할 것 같습니다.

/00$|$/ 로 바꾸면 잘 동작할것입니다.
'스트링의 끝부분의 "00"을 매치하거나, 만약 "00"가 없으면 그냥 스트링의 끝부분을 매치한다' 는 의미입니다.

이렇게 하면 $_="1234" 를 $_=~/00$|$/로 매치하고 나면 $`=="1234"가 됩니다.

이를 바탕으로 코드를 작성해보면

로 67B가 됩니다.

그런데 Regexp 클래스에는 ~ 라는 함수가 있는데, 이 함수는 $_ 와 해당 표현식을 매치합니다.

다시말해, $_=~/00$|$/ 라고 했던 부분을 ~/00$|$/ 으로 줄일 수 있다는 겁니다. 3 bytes 절약인 셈입니다.

다시 코드를 작성해보면

로, 드디어 64B가 되었습니다. 마침내 공동 1위네요.

그런데 랭킹에 보니 1위가 이제는 62B 로 더 줄어버렸습니다. 2바이트를 더 줄여야됩니다. -_-;

하지만 전 이 64B 코드에서 마감시간 이전까지 더이상 줄일 수가 없었고, 결국 4위 (공동 3위)로 마무리하고 말았습니다.

사용자 삽입 이미지



마감시간이 지난 지금, 모든 코드가 공개되어있으므로 하나씩 살펴봅시다.

먼저, 저와 같이 64B 코드를 내놓은 kt3k 님의 코드를 봅시다.
이분은 chomp 함수를 써서 "00"을 없앴군요. 이런 방법도 있었다는걸 몰랐네요.


다음은 63B 코드로 2위를 차지한 ksk님의 코드입니다.
이분 코드에는 l 옵션이 없네요.

$_에서 /00$|$/ 와 매치되는 부분을 찾아서 그 부분의 끝에 뒤의 문자열을 붙이는 방식을 사용했습니다. 정규표현식은 문자열 내의 \n을 무시하기 때문에 l 옵션을 제외시킬 수 있었던 거였군요.

제 코드와 비교해보면 2 바이트의 []를 사용하는 대신 l 옵션과 ~ 함수와 \n의 3바이트를 절약하면서 결과적으로 1바이트를 단축 시킬 수 있게 되었습니다.



마지막으로, 62B 코드로 1위를 차지한 flagitious님의 코드입니다.
엥? 뭔가 완전히 다른 코드입니다.

이 분은 $_ 내의 "00"을 없애기 위해 split을 사용했네요.

커맨드라인 옵션들 중 a는 $F에 $_.split을 저장하는 옵션이고, F00은 a 옵션을 사용할 때에 $F에 $_.split 대신 $_.split('00')을 저장하라는 옵션입니다.

예를 들어, $_="1600" 의 경우 $F=["16"]이 되고,

$_="2008"의 경우 $F=["2","8"]이 됩니다.

그리고 이를 숫자로 바꾸기 위해서 "#$F"로 스트링으로 만든 후에 (["2","8"]이 "28"로 변환 됩니다.) eval 함수를 사용했습니다. eval은 argument로 들어온 스트링을 코드로 인식하여 실행시키는 함수입니다.

대단합니다. 스트링의 한 부분을 "없앤다" 의 개념을 사용하는데에 split 함수를 생각해내다니요.

이번 코드골프 문제로 많은 걸 배웠습니다. :)
크리에이티브 커먼즈 라이선스
Creative Commons License

'Programming > Ruby' 카테고리의 다른 글

QtRuby 1.4.9 를 Mac OSX 10.5.1에 깔기  (2) 2008/03/10
[CodeGolf] Choose  (2) 2008/01/25
[Anarchy Golf] leap year  (6) 2008/01/11
[Golf] Luck-based 18B -2000 to -10000  (0) 2007/12/20
[Golf] 22 bytes -2000 to -10000  (0) 2007/12/20
[Anarchy Golf] 최근 현황  (2) 2007/11/16
Posted by leonid
2007/12/20 - [Programming/Ruby] - [Golf] 22 bytes -2000 to -10000
Works only if the process number is 801 and pid is 1989.
-----------------------------------------------------------------
## Unfortunately, this code doesn't work, since id is a method and assigning a value to a method is impossible. I thought this code is valid because when I was testing my code with
, this one worked properly. Seems that id=1989 creates a variable named id and it overrides the same-named method afterwards, which makes id+=10 valid. On the other hand, if I run id+=10 from the beginning, the interpreter thinks there must be a variable named id but cannot find one except the Kernel.id method, and of course raises an error. ##

크리에이티브 커먼즈 라이선스
Creative Commons License

'Programming > Ruby' 카테고리의 다른 글

[CodeGolf] Choose  (2) 2008/01/25
[Anarchy Golf] leap year  (6) 2008/01/11
[Golf] Luck-based 18B -2000 to -10000  (0) 2007/12/20
[Golf] 22 bytes -2000 to -10000  (0) 2007/12/20
[Anarchy Golf] 최근 현황  (2) 2007/11/16
[Anarchy Golf] Google  (0) 2007/11/08
Posted by leonid