Diary?

2008-08-26
Tue

(19:52)

何か流石にできの悪い研修生対策として、月水金は研修に専念してくれという指令が出た。ってちょっとまて、そうなると週二日しか今のプロジェクトに専念できんぞ。確かに今の状態じゃ微妙通り越してヤバいのはわかるし、ここでさらにバンバカ切っちゃったら士気への影響とか採用にかかったコストの回収とか、いろいろあるってのもわかるんだが。

で、その問題になってるレベルの奴がどういうコードを書いているかというとだな……まずは一般的に初学者がやりがちなミスから見せるか。

SomeClass sc = new SomeClass();
List<SomeClass> list = new ArrayList<SomeClass>();
while (/* 適当な条件文 */) {
  sc.setFoo(...);
  sc.setBar(...);
  list.add(sc);
}

同じインスタンスを使いまわして残念という奴で、こういうのは何がわかってないのか見た瞬間に当たりが付くので教え易い部類に入る(いや、参照型の概念を教えるのは結構面倒くさいんだけどよ)。もっとも、このコードも自力でスクラッチから書けたわけではないのがアレなんだが。まあそれは不問にしておこう。

それにしても次のコードはねえだろうと思った。

private int someMethod(SomeClass a, AnotherClass b) {
  a = new SomeClass();
  b = new AnotherClass();
  ...
}

お前この一ヶ月半近くの間何やってきたんだよ。本気でこればっかりは意味がわからなかったのでよくよく話を聞いてみたら、他のメソッドが全部次のように冒頭でローカル変数を作っていて、それを深く考えずに真似したらしい。

private List<SomeClass> makeSomeClassList() {
  SomeClass sc = new SomeClass();
  List<SomeClass> list = new ArrayList<SomeClass>();
  ...
}
 
private List<AnotherClass> makeAnotherClassList() {
  AnotherClass sc = new AnotherClass();
  List<AnotherClass> list = new ArrayList<AnotherClass>();
  ...
}

……まあ、最初のうちは思わず閉口するようなヘマをするのは仕方がないので、これも不問にしたいといえばしたいんだが、そいつの問題点ってまさに「下手の考え休むに似たる」って感じで、要するに講師の俺がちょくちょく見に行ってやらないと一時間でも二時間でもコードとにらめっこしたまま固まって、上みたいなコードを書くのならまだしも何もできてない事があるんだよな。多分だけど、一日放っておいたらマジで一日固まってると思う(今のところ途中で俺が痺れを切らして話しかけてしまってる)。

そしてこれでも、話を聞きにいくと多少は進展するだけ前に採用拒否した奴よりもマシってのが、なんていうか終わってるところだよなー。まあ下を見たらキリがないのでそれはもう忘れておこう。

しかしこういう何度言ってもアドバイスを受けに来ないで固まりっぱなしの奴ってどうすりゃいいんだろうな。とりあえず俺は採用拒否以外にはノーアイディア。

(21:09)

sumim’s smalltalking-tos 経由で http://www.flownet.com/ron/papers/lisp-java/instructions.html なんてものを知ったので、とりあえず解いてみた。一応言っとくけど、言語は Python な。きちんと計ってないけど、かかった時間は以下のとおりだったと思う。

  • 会社の昼休みに問題文を読んで「30 分でいけるな」と判断して解き始める
  • 見積りの倍の 1 時間で書き終え……たと思ってたんだが
  • 帰ってきてから凄まじい勘違いに気がついて、急遽書き直し

なので問題文を読む時間含めて 2 時間と 30 分ってところか。正直 Python 使ってこれというのは時間かかりすぎな気がしなくもないけど、まあそれが俺の実力なんだろうな。辞書の作り方とかそんなことより、 flatten を書き損じて頭を抱えてたのは内緒だ。

def str2tuple(s):
    r = []
    for c in s:
        r.append(c.lower())
        r.append(c.upper())
    return  tuple(r)
 
def word2num(word, mapping):
    r = []
    for c in (i for i in word if i.isalpha()):
        for k in mapping:
            if c in k:
                r.append(str(mapping[k]))
    return ''.join(r)
 
def words2dict(wlist, mapping):
    r = []
    for w in wlist:
        r.append((word2num(w, mapping), w))
    return tuple(r)
 
def encode(phone, dictionary):
    def _encode():
        found = False
        if not phone: yield '', 0
        else:
            for s in (phone[:i] for i in range(len(phone), 0, -1)):
                for k, v in ((a, b) for a, b in dictionary if s == a):
                    found = True
                    yield v, len(s)
            if not found:
                yield phone[0], 1
    
    for e, l in _encode():
        if l > 0 and l < len(phone):
            for x in [[e] + [e2] for e2 in encode(phone[l:], dictionary)]:
                yield x
        else:
            yield [e]
 
def flatten(arg, none=''):
    def _(ls):
        if not ls: yield none
        for l in ls:
            if isinstance(l, list):
                for i in flatten(l):
                    yield i
            else:
                yield l
    r = list(_(arg))
    return r
 
def escape(s):
    return s.replace('-', '').replace('/', '')
 
def validate(args):
    orig, enc = args
    esc = escape(orig)
    if len(esc) < len(enc):
        return False
    is_num = False
    for c in enc:
        if c.isdigit():
            if is_num:
                return False
            is_num = True
        else:
            is_num = False
    return True
 
slist = 'E', 'JNQ', 'RWX','DSY', 'FT', 'AM', 'CIV', 'BKU', 'LOP', 'GHZ'
wlist = """an
blau
Bo"
Boot
bo"s
da
Fee
fern
Fest
fort
je
jemand
mir
Mix
Mixer
Name
neu
o"d
Ort
so
Tor
Torf
Wasser""".split()
phones = """112
5624-82
4824
0721/608-4067
10/783--5
1078-913-5
381482
04824""".split()
mapping = dict(map(lambda xi: (str2tuple(xi[1]), xi[0]), enumerate(slist)))
dictionary = words2dict(wlist, mapping)
for e in filter(validate,
            reduce(lambda a, b: a + b,
                map(lambda x:
                    [(x, flatten(v)) for v in encode(escape(x), dictionary)],
                    phones))):
    print e[0] + ': ' + ' '.join(e[1])

割とコードの切り詰め競争的な意味合いもある気がしたので、若干詰めて書いた。文字列をハードコードしてる部分とかを抜いた論理行だけなら 70 弱といったところで、正直まだまだ詰められるけどまあ俺はそっち方面にはさほど興味は無いのでこれでいいや。ちなみに本題のファイルは使ってない。そっち使うとなるともうちょっとデータ構造もアルゴリズムも変える必要があると思うけど、面倒になった(元は会社での気分転換だしな)。

特にこのコードに付いては書くことがないのだけど、あえて書くなら再帰とジェネレータと内部関数だな。この手の処理になると、ほぼ手癖でこういうコードになっちまう。

Creative Commons
この怪文書はクリエイティブ・コモンズ・ライセンスの元でライセンスされています。引用した文章など Kuwata Chikara に著作権のないものについては、それらの著作権保持者に帰属します。