1年ぶりぶり 2009年を振り返る

気が付けば世の中は2010年になっていて,このブログを1年以上放置させていた事実に驚く。
2009年は間違いなく人生の転機だったと思うので思い出しながら書いてみる。

  • 1〜2月

まだ新人で大した仕事もなく,のほほんとしていた2008年とは打って変わり,年明けからとんでもないことになった。
前任者が急に辞めてしまったため,真っ赤に燃え上がったプロジェクトに助っ人(生け贄)として投入されるも,周りの人達のサポートもあったため,なんとか切り抜けられる。

これが全ての始まりだったとは思いもしなかった。。

  • 3月

上記の働きにより常駐先に評価され,次のプロジェクトをそこのプロパー(社員)より優先に決めさせていただくことに。
そこで,同じ会社の同僚(自分と入社時期が同じで仲が良かった)がその常駐先からパフォーマンスが悪いという理由で派遣契約を解除されそうになっていたので,次のプロジェクトに二人で入れないかとちょっと無理目なお願いをしたところ,意外とすんなり受け入れられた。

上の同僚は研修期間が一緒で,研修の成績も悪くなかった(むしろ良い方)のは知っていて,パフォーマンスが悪いというのは派遣契約を解除するための方便だと思っていた。

だがそんなことはなかったぜ・・・・・・・・

  • 4〜7月

新しいプロジェクトに入り,7月の本番稼働を目指す。
お願いして連れてきた同僚が使えない。あれやこれやと(詳しく書くと2000字は軽く超えるので割愛)手を尽くしてみたものの急に仕事ができるようになるわけもなく。結局そいつの仕事量の80%を負担するハメに。

この頃からずっと風邪気味みたいな体調が続く。。。。。。。。。。。。。。。

  • 8月

システムは本稼働したものの,監視に上がってくるエラーの調査と報告に明け暮れる。本稼働を迎えてちょっとは落ち着くかと思ったがそんなことはなかったぜ。

そしてやってきた運命の日ー健康診断。

レントゲンに何かもやっとしたものが写ってる→再検査→即入院キタ━━━━(゚∀゚)━━━━!!!!
入院といってもただの入院じゃないです。隔離入院ですた。

この時のごたごたで常駐先からは結局労働力としてしか見られてなかったんだなーと実感。

  • 10月

10月10日に退院。隔離入院だったので病院の中でさえ自由に移動することができず地獄のような日々だった。

退院してから10月いっぱいは自宅療養させてもらうことに。
しかし,常駐先は退院後すぐにプロジェクトに復帰するものと(勝手に)思っていたらしく会社間で一悶着。
ふざけるな,こっちの身にもなってみろよと。

  • 11月

一応自社のオフィスに出勤することに。
新人の面倒や社内の教育計画などの簡単なお仕事をさせてもらう。

もうよその会社に常駐するのはいやだお(´・ω・`) と軽く社長に言ってみる。「そりゃそうだよねえ,,」と言った反応。

時間ができたので外部の勉強会に参加するようになった。

  • 12月

今しかないだろうと思いいつか取ろうと決めていた中小企業診断士の講座(TAC)を申し込む。

年明けから内勤になることが決定。(とりあえず1年間自分で新しいビジネスをやってみるという条件)

戦いはこれからだ!!!
2010年につづく

Lispの力?

たまにはネタにマジレス

を見て、これくらいの処理ならふつーの言語(C的syntaxと言う意味で)でも十分わかりやすい。

でもLispならどういう表現があるだろうかと考えてみました。

で、とりあえずrubyならこんな感じ?

$tamuken = 100
open("geinin.csv") do |f|
  f.each_line do |line|
    name, power, photo = line.split(",")
    if $tamuken < power
      death(name, power)
      puts "は東京で売れている芸人なので抹☆殺しました"
    else
      puts "は東京で売れてない芸人なので見逃しました"
    end
  end
end

豊富なsyntax sugerのおかげで結構すっきり。これ以上簡潔にするにはどうしたら...

そしてGauche的仮想言語に直訳

(define *tamuken* 100)
(let1 contents (read-from-file "geinin.csv")
  (dolist (line (string-split contents #\newline))
    (match-let1 (name power photo) (string-split line ",")
      (if (< *tamuken* power)
        (begin
          (death name photo)
          (print name "は東京で売れている芸人なので抹☆殺しました"))
        (print name "は東京で売れてない芸人なので見逃しました")))))

密度が濃いな〜という感じ。
とりあえず条件分岐を手続きに分離してみるか

(dolist (line (string-split (read-from-file "geinin.csv") #\newline))
  (match-let1 (name power photo) (string-split line ",")
    (death-if (< *tamuken* power) name photo)))

(define (death-if p name photo)
  (if p
    (begin
      (death name photo)
      (print name "は東京で売れている芸人なので抹☆殺しました"))
    (print name "は東京で売れてない芸人なので見逃しました")))

メインな処理がちょっとすっきり。Lispじゃないとif文一つをわざわざ別関数にする気が起きないのは自分だけかもしれないけどね。

あとは読み込んだcsvを分解するという、どうでもいいところが目立っているのが気にくわないので、適当にマクロをでっち上げてみる。

(with-csv "geinin.csv" ","
  (death-if (< *tamuken* ($ 1)) ($ 0) ($ 2)))

(define-macro (with-csv file sep . body)
  (let ((lines (gensym)) (line (gensym)))
    `(begin
       (let1 ,lines (string-split (read-from-file ,file) #\newline)
         (dolist (,line ,lines)
            (define ($ i) (list-ref (string-split ,line ,sep) i))
            ,@body)))))

フィールドの値をawk的に取得できるように。繰り返しも隠蔽。これならやりたいことが一目瞭然!
これがPaul Grahamが言ってたLispの力なのか。高階関数による手続きレベルでの抽象&マクロによる構文レベルでの抽象...

でもマクロは綺麗とは言い難いけどね。そんなものはどこかへ隠してしまえばいいのだ!
でもよくよく考えてみるとrubyでも

with_csv("geinin.csv") do |row|
  death_if($tamuken < row[1], row[0], row[2])
end

って書こうと思えば書けるじゃん!
Lisp初心者&信者の俺乙。

P11-P15 取り合えずコードだけ+

  • P11
(define (encode ls)
 (let iter ( (l ls) (len 0) (last '()) (ret '()))
   (cond
     ( (null? l)
      (cond 
        ( (= len 0)
         ret)
        ( (= len 1)
         (append ret (list len)))
        (else
         (append ret (list (list len last))))))
     ( (null? last)
      (iter (cdr l) 1 (car l) ret))
     ( (eq? (car l) last)
      (iter (cdr l) (+ len 1) (car l) ret))
     (else
       (if (> len 1)
         (iter (cdr l) 1 (car l) (append ret (list (list len last))))
         (iter (cdr l) 1 (car l) (append ret (list last))))))))

(print (encode '(a a a a b c c a a d e e e e)))
;( (4 A) (1 B) (2 C) (2 A) (1 D)(4 E))
  • P12
(define (decode ls)
  (define (s-times l)
    (let iter ( (i (car l)) (s (cadr l)) (ret '()))
      (if (= i 0)
        ret
        (iter (- i 1) s (append ret (list s))))))
  (let iter ( (l ls) (ret '()))
    (cond
      ( (null? l)
       ret)
      ( (pair? (car l))
       (iter (cdr l) (append ret (s-times (car l)))))
      (else
        (iter (cdr l) (append ret (list (car l))))))))

(print (decode '((4 a) b (2 c) (2 a) d (4 e))))
  • P14
(define (dupli ls)
  (let iter ( (l ls) (i 2) (acc '()) (ret '()))
    (cond
      ( (null? l)
       ret)
      ( (= i 0)
       (iter (cdr l) 2 '() (append ret acc)))
      (else
        (iter l (- i 1) (append acc (list (car l))) ret)))))

(print (dupli '(a b c c d)))
  • P15
(define (repli ls count)
  (let iter ( (l ls) (i count) (acc '()) (ret '()))
    (cond
      ( (null? l)
       ret)
      ( (= i 0)
       (iter (cdr l) count '() (append ret acc)))
      (else
        (iter l (- i 1) (append acc (list (car l))) ret)))))

(print (repli '(a b c) 3))

S-99 Ninety-Nine Scheme Problems

EeePC買ってからマック・カフェでちょこちょここれ
L-99: Ninety-Nine Lisp Problems
Schemeでやってまして、とりあえず第1章・リスト遊び(勝手に章付け)P28まで終わったのでまとめておきます。

  • P01 リストの最後の要素を単一要素のリストで返す関数
 (define (my-last lst)
   (let iter ( (l lst) )
     (if (null? (cdr l)) 
       (list (car l)) 
       (iter (cdr l)))))
  • P02 リストの最後2つの要素をリストで返す関数
 (define (my-but-last ls) 
   (cond
     ( (null? ls) ls) 
     ( (null? (cdr ls)) ls) 
     ( (null? (cddr ls)) ls) 
     (else
       (my-but-last (cdr ls)))))
  • P03 指定の位置の要素を返す関数
 (define (element-at lst index)
   (let iter ( (l lst) (count 1)) 
     (if (>= count index)
       (car l)
       (iter (cdr l) (+ count 1)))))
  • P04 リストの長さを返す関数
 (define (my-length lst) 
   (let iter ( (l lst) (len 0))
     (if (null? l) 
       len
       (iter (cdr l) (+ len 1)))))

ここまでは簡単。ただ再帰するだけ。

  • P05 逆順リスト
 (define (my-reverse lst)
   (let iter ( (l lst) (r '()))
     (if (null? l) 
       r
       (iter (cdr l) (cons (car l) r)))))

リストを潜っていき順に別に用意したリストの先頭に追加していく。

  • P06 リストが回文かどうか判定
 (load "my_reverse.scm") ;P05
 (define (palindrome? lst)
   (if (equal? lst (my-reverse lst))
     #t
     #f))

前のmy-reverseを使って元のリストと等しいか判定する。equal?くらい使ってもいいよね。

  • P07 ネストしたリストを平坦化
 (define (my-flatten lst) 
   (cond ( (null? lst)
          '())
          ( (pair? lst)
           (append (my-flatten (car lst)) (my-flatten (cdr lst))))
          (else (list lst))))

これが書けなくて3日間くらい悩んだ挙句カンニング。appendするとリストが1段階減る。

  • P08 連続した同じ要素を取り除く
 (define (compress lst)
   (let iter ( (l lst) (last '()) (r '()))
              (cond
                ( (null? l)
                 r)
                ( (eq? (car l) last)
                 (iter (cdr l) (car l) r))
                (else
                  (iter (cdr l) (car l) (append r (list (car l))))))))

再帰するときに前回の要素を持っておき、連続しているか判定する。

  • P09 連続した同じ要素をリストにまとめる
 (define (pack ls)
   (let iter ( (l ls) (acc '()) (ret '()))
     (cond
       ( (null? l)
        (if (null? acc)
          ret
          (append ret (list acc))))
       ( (null? acc)
        (iter (cdr l) (append acc (list (car l))) ret))
       ( (eq? (car l) (car acc))
        (iter (cdr l) (append acc (list (car l))) ret))
       (else     
         (iter (cdr l) (list (car l)) (append ret (list acc)))))))

返り値用のリストとは別に一時使用のリストを使う。

  • P10 ランレングス圧縮
 (define (encode ls)
   (let iter ( (l ls) (len 0) (last '()) (ret '()))
     (cond
       ( (null? l)
        (if (= len 0)
          ret
          (append ret (list (list len last)))))
       ( (null? last)
        (iter (cdr l) 1 (car l) ret))
       ( (eq? (car l) last)
        (iter (cdr l) (+ len 1) (car l) ret))
       (else     
         (iter (cdr l) 1 (car l) (append ret (list (list len last))))))))

P09からさらにカウンター用にlet変数追加

とりあえずそろそろ出勤なのでここまで。
>|hoge|<のpre記法の中でも((hage))←[実際は半角]の脚注が有効なのはLISPerに対する嫌がらせとしか思えない件。

あれ?

何で下の部分が黒いんだろ。透過処理してるとうまくいかないのかな…

今はこんな感じ。
[
avant-window-navigatorを新しいのにしたらせっかく登録したアイコンが全部無くなってしまった。。
岩本町マックモンハンプレーヤ多すぎてコンセント使えん。。

勉強時間が欲しかったので一ヶ月間4:30に起きてみた

今は普通に9時出社の職場で働いているんだけど、たとえ定時で帰ることができたとしてもなかなか勉強する気になれなかったので思い切って早起きすることにしました。(ちなみに今までは夜型だったので日付が変わってから寝るのが普通でした。)

4時半に目覚ましが鳴り、半分夢の中でパンを齧り、目覚ましにシャワーを浴びて、5:36の電車に乗り、6:30〜8:30までマックで過ごしています。

良かったこと

  • 通勤ラッシュに揉まれることもなく電車の中で快適に本が読める
  • 朝涼しい
  • 仕事で疲れる前にプライベートな時間が作れる
  • 遅刻しない
  • 始業からフルパワーで仕事ができる

微妙な点

  • やっぱり朝は眠い(土日夜更かししがちなので特に月曜は辛い)
  • 夜も眠い(というか10時くらいに寝ないと4:30に起きるのは辛い)
  • 1日4食になった(起きた直後とマックのチキンで朝2回)
  • なので食費がかさむ
  • 夜眠いので自炊が減った
  • 食費g(ry

ということで早起きは三文の得というより、金を時間に変えているような感じです。
あと夜10時に寝るので残業が厳しい場合や、テレビっ子には絶対無理です。

毎日2時間勉強できるとどうなるのか、これからも続けて試してみたいと思います。


あ、EeePC 900買っちゃいましたwwwwwwwww英語版のやつ。eeeXubuntu入れてマックでこれ書いてます。