Comment detail

文字列の均等分割 (Nested Flatten)

正規表現を使いました。

countは0以上の無限リストを作成する命令で、0以上の各整数iについて「『i文字またはi+1文字』のブロックがn個ある」という正規表現を作ってマッチを試みます。マッチすればグループ分けをreturn。greedyなので前半のグループが長い方、後半のグループが短い方になります。

1
2
3
4
5
6
7
8
def divid(n, s):
    import re
    from itertools import count
    for i in count():
        pat = "^%s$" % "(.?.{%d})" % i * n
        m = re.match(pat, s)
        if m:
            return m.groups()

算術演算もstrlenに相当する関数も使ってないよ!(よっぽどうれしかったらしい)

括弧が抜けてました…

1
2
- pat = "^%s$" % "(.?.{%d})" % i * n
+ pat = "^%s$" % ("(.?.{%d})" % i * n)
5 行目は、
pat = "^%s$" % ("(.?.{%d})" % i * n)
のように括弧が必要だったりしませんか?

修正済でしたね…。すみません。

なるほどなるほど。では nongreedy なものを。
1
2
3
4
function doukaku88(n, s){
  for(var i = 0, m; !(m = s.match(RegExp('^'+ Array(n + 1).join('(.{'+ i +','+ ++i +'}?)') +'$'))););
  return m.slice(1);
}
D に移植してみました。文字列の長さと分割数次第ではひどく時間がかかります。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import std.stdio;
import std.regexp;
import std.string;

string[] divid(uint n, string s){
    string[] ret;
    for(uint i;; i++){
        auto pat = "^" ~ format("(.{%d,%d})", i, i + 1).repeat(n) ~ "$";
        if(auto m = search(s, pat)){
            for(uint j = 1; j <= n; j++){
                ret ~= m.match(j);  // ret ~= m[j];
            }
            break;
        }
    }
    return ret;
}

void main(){
    auto sample = "ゆめよりもはかなき世のなかをなげきわびつゝあかしくらすほどに四月十よひにもなりぬれば木のしたくらがりもてゆく";
    writefln(divid(4, sample).join("\n"));
    writefln("----");
    writefln(divid(5, sample).join("\n"));
    writefln("----");
    writefln(divid(6, sample).join("\n"));
}

Index

Feed

Other

Link

Pathtraq

loading...