태터데스크 관리자

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

태터데스크 메시지

저장하였습니다.


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


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

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

최근에 갑자기 많은 수의 문제들이 등록됐습니다.

대부분이 꼼수를 쓰기 좋고, 너무 간단한 문제들이라서 좀 그렇긴 하지만 당분간 심심하지 않겠네요 ㅎㅎ



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

'Programming' 카테고리의 다른 글

[Anarchy Golf] 새로운 문제들 대거 출시!  (0) 2008/01/24
Syntax highlighter 테스트  (1) 2007/11/16
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
If I change 200 into ?\xc8, it's actually 22 bytes.
Can't get this even shorter though.


If using $$ is allowed (like in http://golf.shinh.org),
I can write an even shorter luck-based 21 bytes solution : Works only if the process number is 1000 when this code is executed.


Even crazier 18 bytes solution is possible if extreme luck is allowed :
see http://leonidblog.tistory.com/44
### This one just doesn't work LOL. sorry ###

The problem is to write a code that prints exactly the same numbers the code below does.


You can see details of the problem (Japanese) at:
http://jp.rubyist.net/magazine/?0022-RubiMaGolf


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

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

[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
[CodeGolf] Vigenere Cipher  (0) 2007/11/04
Posted by leonid


최근에 http://golf.shinh.org 에 문제 세개를 투고했습니다.

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

Nothing - http://golf.shinh.org/p.rb?Nothing

사용자 삽입 이미지


사람을 두번 낚는 문제입니다. -_-ㅋ

첫번째는 Output 에 있는 *NOTHING* 이 "없음" 을 뜻하는 게 아니라 스트링 "*NOTHING*" 그대로 라는 것.

그리하여 애초에 "아싸 좋구나" 하면서

등을 써서 1B 를 올리려다 실패한 golfer들은


의 15B 를 등록할 수밖에 없게 되며, 곧바로 두번째 함정에 낚이게 됩니다.

입력 란에 있는 *NOTHING* 역시 스트링 "*NOTHING*" 이었다는것.

이 사실을 알고서야


의 8B 솔루션을 생각해내는 겁니다.

(저의 8B 솔루션은 였습니다만..)

결과적으로, echo 문제와 동일합니다.

사용자 삽입 이미지
2~6위는 , 7위는 를 사용한듯.

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

Print numbers _Revised_ - http://golf.shinh.org/p.rb?Print+numbers++_Revised_

사용자 삽입 이미지

수열의 패턴을 알아내는 것이 관건입니다.

수열은 한국의 유명한 퍼즐책 "재미있는 영재들의 수학퍼즐" 에서 가져왔습니다.

패턴은 알고나면 쉽지만, 모르는 상황에서 알아내기는 굉장히 어렵습니다.



원래 투고했던 문제는 수열 맨 뒤의 10000을 제외한
10 11 12 13 14 15 16 17 20 22 24 31 100 121
을 출력하는 내용이었으나..

수열의 패턴을 적용해서 출력하는것 보다(30B)
 
와 같이 단순무식하게 숫자들을 그대로 출력해버리는게(29B) 더 낫다는 사실을 알고나서 급히 뒤의 10000을 추가하였습니다.

이젠 적어도 루비에서는 저런 방법은 안통합니다.. :P

그나저나 뒤에 추가한 10000이 golfer들을 더욱 혼란에 빠지게 했는지, 아니면 오히려 패턴을 알아내는 결정적인 힌트를 줬는지는 잘 모르겠..

아무튼, 수열의 패턴을 파악하면 27B의 코드가 가능합니다.

사용자 삽입 이미지

2~4위는 본인과 같은 코드를 생각하고 있는듯.

5~9위 역시 패턴을 파악한것 같습니다. 이제 줄이는 일만 남았네요


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

Factorial - http://golf.shinh.org/p.rb?Factorial

사용자 삽입 이미지



input으로 들어오는 리스트에서 각 숫자들의 Factorial을 구하여 출력하는 문제입니다.

Ruby에는 Factorial 함수가 없기 때문에 직접 구현해야 하는데,

일반적인 방법으로 했다가는 바이트 수가 엄청나게 늘어버립니다.

34B 까지 줄인 현재 힌트를 드리자면,

"Option, Range, 그리고 Eval을 잘 사용하라" 입니다.

본인은 어느 특정 Option의 존재를 잊은 채로 35B 코드를 등록해놓고 가만히 있다가

kinaba님의 34B 솔루션에 1위를 놓치고 말았습니다. -_- (부랴부랴 34B 코드를 등록했지만 늦게 등록했기에 등수는 변하지 않음.. OTL)

내가 투고한 문제에서 추월당하다니 OTL

이래서 golfing에서 방심은 금물입니다.

사용자 삽입 이미지

1~4위는 다들 같은 방식의 코드를 생각하고 있는 듯.


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

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

[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
[CodeGolf] Vigenere Cipher  (0) 2007/11/04
Posted by leonid


http://golf.shinh.org/p.rb?google


google 문자열을 길게 출력하는 아주 간단한 문제입니다.

input으로 :
2가 들어오면
-> google
10이 들어오면   
-> goooooooooogle
42가 들어오면   
-> goooooooooooooooooooooooooooooooooooooooooogle
을 출력하면 됩니다.

문제가 간단하기 때문에
Ruby의 26B 해법을 어렵지 않게 생각해낼 수 있습니다.


여기서 과연 더 이상 줄이는게 가능할까요?

더 줄일 수 있습니다! 불가능이란 없다!
24B로 현재 Ruby 1위

힌트는 "일반적인 접근으로는 안됨" 입니다.

사용자 삽입 이미지


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

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

[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
[CodeGolf] Vigenere Cipher  (0) 2007/11/04
Posted by leonid