1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

オフラインリアルタイムどう書くF01 の問題をRuby正規表現で解く

1
Last updated at Posted at 2017-01-19

問題 : http://nabetani.sakura.ne.jp/hena/ordf01_twicel/
実装リンク集 : http://qiita.com/Nabetani/items/8e02ede04315b4eadd6d

Rubyで正規表現を使って電車の中で実装。
隣の人に肘がぶつかってやりにくかった。

hoge.rb
def match_count(t, reg)
  cnt = 0
  while t =~ reg
    cnt += 1
    i = t.index($1)
    t = t[i + 1, t.size - i - 1]
  end
  cnt
end

def num_count(t)
  regh = /(\D{2}.{7}\D\d{2}\D.{7}\D{2})/
  regv = /(\D.{8}\D\d\D.{7}\D\d\D.{8}\D)/
  [regh, regv].map { |reg| match_count(t, reg) }.inject { |a, e| a + e }
end

def wb_count(src)
  t = ['a' * 10, src.split('/').map { |a| 'a%08ba' % a.hex }, 'a' * 10].flatten.join
  %w(1 0).map { |a| num_count(t.gsub(a, 'a')) }.join(',')
end

DATA.each do |d|
  n, src, exp, _link = d.split
  act = wb_count(src)
  puts %(#{n} : #{src}  #{act} != #{exp}) if act != exp
end

__END__
0 	dc/bc/a7/59/03/d5/d4/ea 	2,3 	リンク
1 	ff/ff/ff/ff/ff/ff/ff/ff 	0,0 	リンク
2 	00/00/00/00/00/00/00/00 	0,0 	リンク
3 	cc/33/cc/33/cc/33/cc/33 	16,16 	リンク
4 	aa/aa/55/55/aa/aa/55/55 	16,16 	リンク
5 	ac/a3/5c/53/ca/3a/c5/35 	8,8 	リンク
6 	db/00/db/00/db/00/aa/aa 	0,13 	リンク
7 	24/24/db/24/24/db/24/24 	0,12 	リンク
8 	d7/d7/e9/f1/f7/de/60/56 	3,2 	リンク
9 	17/7d/64/9b/a5/39/53/a6 	2,2 	リンク
10 	bb/8f/18/fb/89/c2/c7/35 	1,2 	リンク
11 	6d/63/20/08/54/cd/32/4f 	2,2 	リンク
12 	a9/ca/cd/46/99/e6/f0/30 	2,2 	リンク
13 	5b/70/fd/45/e2/a1/ab/9a 	1,2 	リンク
14 	24/e4/a8/12/e1/a6/3f/f3 	2,1 	リンク
15 	79/32/2e/07/d5/10/e7/9d 	2,2 	リンク
16 	60/bc/ab/ec/1f/eb/63/2c 	4,2 	リンク
17 	a5/dd/92/4e/67/c6/dc/34 	6,1 	リンク
18 	aa/96/6d/67/d2/a8/ac/90 	3,2 	リンク
19 	95/72/7d/5c/47/dc/ef/99 	4,0 	リンク
20 	17/d6/6a/27/1f/25/26/b8 	2,1 	リンク
21 	f0/f3/76/c5/31/ca/6b/ae 	1,2 	リンク
22 	01/59/26/fa/8c/70/12/cd 	1,4 	リンク
23 	1a/c3/1f/0b/83/b6/81/0d 	0,5 	リンク
24 	4c/49/05/cf/54/bb/1f/da 	1,2 	リンク
25 	eb/7c/d5/09/2a/c2/14/6b 	0,7 	リンク
26 	b4/d3/4c/c4/ed/19/e8/63 	1,3 	リンク
27 	bd/bc/6d/60/9b/00/9a/32 	2,4 	リンク
28 	94/97/3f/e3/c7/06/15/c0 	2,2 	リンク
29 	5f/1d/67/16/b8/f7/0a/2a 	2,2 	リンク
30 	df/e6/f9/4f/59/e9/1f/ee 	3,0 	リンク
31 	5a/53/9a/9a/73/b4/37/07 	3,2 	リンク
32 	bd/87/7c/e7/c0/37/82/da 	2,3 	リンク
33 	3d/c0/13/ac/57/3d/15/78 	2,2 	リンク
34 	63/64/54/3a/40/28/4e/4e 	0,3 	リンク
35 	f6/81/c9/15/00/4c/a0/a8 	1,4 	リンク
36 	19/41/df/f8/e3/74/6b/9b 	4,2 	リンク
37 	d5/0b/dd/35/3b/d2/0b/6b 	1,5 	リンク
38 	08/b7/91/f3/6e/3c/74/a0 	0,0 	リンク
39 	b8/a8/b4/a6/93/2c/94/3f 	0,0 	リンク
40 	88/22/21/ee/dc/19/43/01 	0,0 	リンク
41 	e1/ee/35/bc/fc/00/8e/fe 	0,0 	リンク
42 	3c/42/63/5f/27/47/07/90 	0,0 	リンク

端っこの判定が面倒なので上下左右に1マスずつクワイエットゾーンを設けました。('a' のこと)

あとは2マスが横並び、縦並びの2種類あるので、それぞれのパターンにマッチする正規表現(regh, regv)を作って、マッチ数を白黒それぞれで数えています。

正規表現のパターンを作るのが面倒でした。
実際のところテスト通ったからOKなんだろうけど、パターンの要素数を目視では数えられませんでしたね。
例えば、¥D{7}の7のことです。

それと当初はマッチ数の計測にscan.sizeを使おうとしましたが、この方法だと文字列が重複する箇所は計測できないので、仕方なくマッチ数を求める関数を作ることにしました。

うまいやり方があれば教えてください。

投稿後にアドバイスいただきましたので、num_countの実装を以下のように修正しました。
正規表現の肯定先読みを使うことで、私のやりたかったscan.sizeでの実装が実現できました。

def num_count(t)
  reg1 = /\D{2}(?=.{7}\D\d{2}\D.{7}\D{2})/
  reg2 = /\D(?=.{8}\D\d\D.{7}\D\d\D.{8}\D)/
  [reg1, reg2].map { |reg| t.scan(reg).size }.inject { |a, e| a + e }
end
1
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?