CodeIQ Blog

自分の実力を知りたいITエンジニア向けの、実務スキル評価サービス「CodeIQ(コードアイキュー)」の公式ブログです。

「Rubyでコードゴルフ:ぐるぐる渦巻き」最終ランキング発表~上位5位のコード公開+Ozyさんの解説付き #codegolf #ruby

CodeIQ中の人、millionsmileです。

Rubyでぐるぐるコードゴルフ、最終ランキングの発表です!
今回は上位5位のコード公開と、出題者Ozyさんからの「How to ぐるぐる」の解説付きです。

===============================
Ozyです。

How to ぐるぐる

これぞスクリプト言語という、ぐるぐるメソッドがあります。

3×3の場合の具体例

まず、1からスタートして、サイズ1の配列を作ります。

[1]

次に、これと同じサイズの行列を作り、中には2を入れます。

[ [2], [1] ]

のような状態を作るということです。これに対してtransposeを使うと、

[ [2, 1] ]

のようになります。なんだよflattenと一緒じゃないかーと言わないでくださいね。もう少し進めば意味は分かります。配列の長さが2になりましたので、今度は長さが2の配列を用意して、3と4を入れます。

[ [3, 4], [2, 1] ]

行列風に書くと、

3 4
2 1

ちょっとぐるっとしました。ここで、Array.transposeを発動します。

[ [3, 2], [4, 1] ]

さらに2つの配列を逆順にすると、

[ [ 4, 1], [3, 2] ]
4 1
3 2

それっぽくなりました。


それぞれの配列は、まだ長さが2のままですので、さらに長さ2の配列を作り、5と6を加えます。

[ [5, 6], [4, 1], [3, 2] ]

これをtransposeして、順序を逆にすれば、

[ [6, 1, 2], [5, 4, 3] ]
6 1 2
5 4 3

のようになります。もう出来上がりが見えてきましたね。ここで配列のサイズが3になりましたので、今度はサイズ3の配列を作り、7と8と9を入れます。

[ [7, 8, 9], [6, 1, 2], [5, 4, 3] ]

これで、目的の形になりました!

7 8 9
6 1 2
5 4 3

transposeとreverseを使いながら、文字通りぐるぐるしていくわけです。

上位ショートコーダーの超短いコード

1位 Muさん(107B)
n=gets.to_i**2;v,*a=0;a=[a.map{"%#{n.to_s.size}d"%v+=1}]+a.transpose.reverse while v<n;puts a.map{|l|l*' '}
2位 tompngさん(108B)
n=gets.to_i/2
a=-n..n
a.map{|y|puts a.map{|x|"%#{4-21/(n+6)}d".%2*[2*y*y-y,2*x*x-x-z=(x-y).abs].max-~z}*' '}
3位 tomwotさん(111B)
y=[];z=0;(2*n=gets.to_i).times{y=[y.map{z+=1}]+y.transpose.reverse};puts y.map{|w|["%#{z.to_s.size}d"]*n*' '%w}
4位 UGさん(113B)
n,*m=eval *$<
eval"m=[[*$....$.+=m.size]]+m.transpose.reverse;"*n*2
puts m.map{|r|["%#{"#{n*n}".size}d"]*n*" "%r}
5位 antimon2さん(116B)
puts (a=0...n=gets.to_i).map{|y|a.map{|x|d=y-x;"%#{"#{n*n}".size}d"%[x,y].sort.map{|w|1-(m=w*2-n)*~m+d=-d}.max}*' '}

全体順位表

1位: Mu (107)B
2位: tompng (108)B
3位: tomwot (111)B
4位: UG (113)B
5位: antimon2 (116)B
6位: UTO, iehn (117)B
7位: hoi (118)B
8位: Azicore (119)B
9位: mad_p (121)B
10位: hogeover30 (122)B
ーーーーー 上級の壁(125B) ーーーーー
11位: th (127)B
12位: rotary-o, ayuzak (129)B
13位: autotaker (131)B
14位: siman (132)B
15位: ushsh (133)B
16位: robert, ttakuru88 (137)B
17位: whiteleaf (138)B
18位: uru (139)B
19位: しかく (143)B
20位: saidie, hm001 (147)B
ーーーーー 中級の壁(150B) ーーーーー
21位: climpet
22位: hogehoge-codeiq
23位: ciel
24位: nishioi
25位: niwatoriheart
26位: hirokazu1020
27位: じゃい
28位: pavlocat
29位: RLD
30位: ysk_univ
31位: Mahito
32位: tmtms
33位: setaria
34位: れこ
35位: manozo
36位: okura3
37位: masatanish
38位: facil89
39位: わだこ
40位: moneymog
41位: ricca
42位: ぺこ
43位: tokyoster
44位: tossy
45位: TONY0922

もっと短くできるか?

今回1位は107バイトでしたが、もっと短くすることは可能です。上位のコードをよくよく見返すだけで、少なくとも104バイトまでは縮められるはずです。もちろん、もっと縮める方法もあるかもしれませんので、色々と研究してみてくださいね。

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

ゴルファーのみなさん、Rubyでぐるぐるできましたか?
ぐるぐるバッジの付与は後日行う予定です。(今日じゃないよ)

問題文は以下に掲載します。

【問題】
標準入力から、3以上の奇数Nが与えられます。
N×Nサイズのぐるぐる渦巻きをきれいに出力してください。

【例】
N=3のとき
7 8 9
6 1 2
5 4 3

N=5のとき
21 22 23 24 25
20  7  8  9 10
19  6  1  2 11
18  5  4  3 12
17 16 15 14 13

【注意】
・きれいな渦巻きにするために、桁数の差を埋めるスペースを必ず入れてください。(N=5の場合を参照)
・Nの最大値は99としておきます。
・実行テストで使用するRubyのバージョンは、ruby-1.9.3です。
・テストデータのセットは
 https://dl.dropboxusercontent.com/u/110505645/CodeIQ/201305/testdata.zip
 からダウンロードできますので、確認に利用してください。

【解答方法】
完成したコードをテキストファイル(.txt)に変換し、下記のファイルアップロードより提出してください。また、複数回ご提出いただいた場合は、正しく出力されるコードの中で、コードサイズが最小のものを記録とします。


【過去の暫定ランキング】
2013年6月5日14時時点の暫定ランキング
http://codeiq.hatenablog.com/entry/2013/06/05/154930
2013年6月1日11時時点の暫定ランキング
http://codeiq.hatenablog.com/entry/2013/06/01/144344

ぐるぐる楽しかったですね。
問題受付は終了しましたが、さらに104Bまで縮むという宿題が残っているのでチャレンジしてみては?
https://codeiq.jp/ace/ozy4dm/q335
f:id:codeiq:20130610164351p:plain

CodeIQ中の人の一言:ほこたて。みてない。