vigenere cipherをperlでshort coding

とりあえず、asciiコードの32番から126番まで。

# encrypt
$ perl -e'print+map{($a=ord getc)?($a>31&&$a<127)?chr(($a+$_-64)%95+32):chr($a):"",}unpack("C*","keyword")until eof()'
# decrypt
$ perl -e'print+map{($a=ord getc)?($a>31&&$a<127)?chr(($a-$_)%95+32):chr($a):"",}unpack("C*","keyword")until eof()'
# example (encrypt)
$ echo "hello world this is sample of vigenere cipher" | perl -e'print+map{($a=ord getc)?($a>31&&$a<127)?chr(($a+$_-64)%95+32):chr($a):"",}unpack("C*","keyword")until eof()'

TKfd_r\[Xf\ogMUYyacrXMSjdUrTRepaWXSQX_wS\UTKl
# example (encrypt->decrypt)
$ echo "hello world this is sample of vigenere cipher" | perl -e'print+map{($a=ord getc)?($a>31&&$a<127)?chr(($a+$_-64)%95+32):chr($a):"",}unpack("C*","keyword")until eof()' | perl -e'print+map{($a=ord getc)?($a>31&&$a<127)?chr(($a-$_)%95+32):chr($a):"",}unpack("C*","keyword")until eof()'

hello world this is sample of vigenere cipher

dolistsを書いてみた。

paul grahamのdolistsがschemeにも欲しい。

>(dolists ((i '(1 2 3)) (j '(4 5 6))) (print (list i j)))
(1 4)
(2 5)
(3 6)

こんな感じのやつ。

CLだとわだばlisperになるにあるように、

(defmacro dolists (pairs &body body)
  (let ((parms (mapcar (lambda (x) (declare (ignore x)) (gensym)) pairs))
        (f (gensym)))
    `(labels ((,f ,parms
                  (when (or ,@parms)
                        (let ,(mapcar (lambda (p g)
                                        (list (car p) `(car ,g)))
                                      pairs
                                      parms)
                          ,@body
                          (,f ,@(mapcar (lambda (p) `(cdr ,p)) parms))))))
             (,f ,@(mapcar #'second pairs)))))

でいける。
labelsをhttp://valvallow.blogspot.com/2010/05/common-lisp-labels-scheme.htmlから拝借。

(define-syntax labels
  (syntax-rules ()
    [(_ ((name (var ...)
               proc-body ...) ...)
        body ...)
     (letrec
         ((name (lambda (var ...)
                  proc-body ...)) ...)
          body ...)]))

(define-macro (dolists pairs . body)
  (let ((f (gensym))
        (parms (map (lambda (x) (gensym)) pairs)))
    `(labels ((,f ,parms
                  (when (or ,@(map (lambda (x) (list 'not (list 'eq? x '()))) parms))
                        (let ,(map (lambda (p g)
                                     (list (car p) `(car ,g)))
                                   pairs
                                   parms)
                          ,@body
                          (,f ,@(map (lambda (p) `(cdr ,p)) parms))))))
             (,f ,@(map cadr pairs)))))

schemeは'()が#tになるので(when (or ...))の条件判定部分をすこし置き換えた。
schemeが完全に分かってないから、もしかすると(gensym)なんかいらないのかも。。

arefとsvref

疑問;svrefは本当にはやいのか?
配列アクセス速度についてちょっと実験。

まずはlet over lambdaより引用。

(set-dispatch-macro-character #\# #\f
                              (lambda (stream sub-char numarg)
                                (declare (ignore stream sub-char))
                                (setq numarg (or numarg 3))
                                (unless (<= numarg 3)
                                  (error "Bad value for #f: ~A" numarg))
                                `(declare (optimize (speed ,numarg)
                                                    (safety ,(- 3 numarg))))))

(defmacro fast-progn (&rest body)
  `(locally #f ,@body))

(defmacro safe-progn (&rest body)
  `(locally #0f ,@body))

これはつまりdeclareを追加するというだけです。

* (macroexpand-1 '(fast-progn nil))

(LOCALLY (DECLARE (OPTIMIZE (SPEED 3) (SAFETY 0))) NIL)
T
* (macroexpand-1 '(safe-progn nil))

(LOCALLY (DECLARE (OPTIMIZE (SPEED 0) (SAFETY 3))) NIL)
T

以下4つの関数で比較してみた。

(defun loop-aref (times)
  (let ((arr (make-array times :initial-element 0)))
    (dotimes (i times)
      (setf (aref arr i) i))))

(defun loop-svref (times)
  (let ((arr (make-array times :initial-element 0)))
    (dotimes (i times)
      (setf (svref arr i) i))))

(defun floop-aref (times)
  (fast-progn
   (let ((arr (make-array times :initial-element 0)))
     (dotimes (i times)
       (setf (aref arr i) i)))))

(defun floop-svref (times)
  (fast-progn
   (let ((arr (make-array times :initial-element 0)))
     (dotimes (i times)
       (setf (svref arr i) i)))))

内容はただ配列に0,1,2,..と値を代入してるだけ。
arefとsvref、またコンパイラに最適化命令出すかいなか(optimize or not)で比較してます。

* (time (loop-aref n))

Evaluation took:
  0.029 seconds of real time
  0.028002 seconds of total run time (0.028002 user, 0.000000 system)
  96.55% CPU
  82,053,594 processor cycles
  40,000,008 bytes consed

* (time (loop-svref n))

Evaluation took:
  0.028 seconds of real time
  0.028002 seconds of total run time (0.028002 user, 0.000000 system)
  100.00% CPU
  80,788,770 processor cycles
  40,000,008 bytes consed

* (time (floop-aref n))

Evaluation took:
  0.015 seconds of real time
  0.016001 seconds of total run time (0.016001 user, 0.000000 system)
  106.67% CPU
  42,072,459 processor cycles
  40,000,008 bytes consed
  
* (time (floop-svref n))

Evaluation took:
  0.013 seconds of real time
  0.012001 seconds of total run time (0.012001 user, 0.000000 system)
  92.31% CPU
  35,575,659 processor cycles
  40,000,008 bytes consed

若干svrefの方が早くなってるけど、複数回計測するとそんなに大差はなかったかも。
ただやっぱりoptimizeすると実行時間は早い。
それもそのはず、disassembleしてみると、

* (disassemble #'loop-aref)

; disassembly for LOOP-AREF
; 0B243D70:       8D4424F8         LEA EAX, [ESP-8]           ; no-arg-parsing entry point
;      D74:       83EC0C           SUB ESP, 12
;      D77:       8945FC           MOV [EBP-4], EAX
;      D7A:       8BD3             MOV EDX, EBX
;      D7C:       8B3D303D240B     MOV EDI, [#xB243D30]       ; :ELEMENT-TYPE
;      D82:       BE27001001       MOV ESI, 17825831
;      D87:       8B5DFC           MOV EBX, [EBP-4]
;      D8A:       8B05343D240B     MOV EAX, [#xB243D34]       ; #<FDEFINITION object for MAKE-ARRAY>
;      D90:       B90C000000       MOV ECX, 12
;      D95:       892B             MOV [EBX], EBP
;      D97:       8BEB             MOV EBP, EBX
;      D99:       FF5005           CALL DWORD PTR [EAX+5]
;      D9C:       8B5DF8           MOV EBX, [EBP-8]
;      D9F:       81FB0B001001     CMP EBX, 17825803
;      DA5:       7407             JEQ L0
;      DA7:       8D43FD           LEA EAX, [EBX-3]
;      DAA:       A807             TEST AL, 7
;      DAC:       7452             JEQ L5
;      DAE: L0:   81FB0B001001     CMP EBX, 17825803
;      DB4:       744A             JEQ L5
;      DB6:       31C9             XOR ECX, ECX
;      DB8:       EB2A             JMP L3
;      DBA: L1:   8D42F9           LEA EAX, [EDX-7]
;      DBD:       A807             TEST AL, 7
;      DBF:       7533             JNE L4
;      DC1:       8A42F9           MOV AL, [EDX-7]
;      DC4:       3C8A             CMP AL, 138
;      DC6:       722C             JB L4
;      DC8:       3CDE             CMP AL, 222
;      DCA:       7606             JBE L2
;      DCC:       2CE6             SUB AL, 230
;      DCE:       3C10             CMP AL, 16
;      DD0:       7722             JNBE L4
;      DD2: L2:   8B42FD           MOV EAX, [EDX-3]
;      DD5:       39C8             CMP EAX, ECX
;      DD7:       7638             JBE L6
;      DD9:       8BC1             MOV EAX, ECX
;      DDB:       894C0201         MOV [EDX+EAX+1], ECX
;      DDF:       8BC1             MOV EAX, ECX
;      DE1:       83C104           ADD ECX, 4
;      DE4: L3:   8BC3             MOV EAX, EBX
;      DE6:       39C1             CMP ECX, EAX
;      DE8:       7CD0             JL L1
;      DEA:       BA0B001001       MOV EDX, 17825803
;      DEF:       8BE5             MOV ESP, EBP
;      DF1:       F8               CLC
;      DF2:       5D               POP EBP
;      DF3:       C3               RET
;      DF4: L4:   8B05383D240B     MOV EAX, [#xB243D38]       ; 'VECTOR
;      DFA:       CC0A             BREAK 10                   ; error trap
;      DFC:       03               BYTE #X03
;      DFD:       1F               BYTE #X1F                  ; OBJECT-NOT-TYPE-ERROR
;      DFE:       90               BYTE #X90                  ; EDX
;      DFF:       10               BYTE #X10                  ; EAX
;      E00: L5:   8B053C3D240B     MOV EAX, [#xB243D3C]       ; 'INTEGER
;      E06:       CC0A             BREAK 10                   ; error trap
;      E08:       03               BYTE #X03
;      E09:       1F               BYTE #X1F                  ; OBJECT-NOT-TYPE-ERROR
;      E0A:       D0               BYTE #XD0                  ; EBX
;      E0B:       10               BYTE #X10                  ; EAX
;      E0C:       CC0A             BREAK 10                   ; error trap
;      E0E:       02               BYTE #X02
;      E0F:       18               BYTE #X18                  ; INVALID-ARG-COUNT-ERROR
;      E10:       4F               BYTE #X4F                  ; ECX
;      E11: L6:   CC0A             BREAK 10                   ; error trap
;      E13:       04               BYTE #X04
;      E14:       22               BYTE #X22                  ; INVALID-ARRAY-INDEX-ERROR
;      E15:       90               BYTE #X90                  ; EDX
;      E16:       0F               BYTE #X0F                  ; EAX
;      E17:       4F               BYTE #X4F                  ; ECX
NIL
* (disassemble #'loop-svref)

; disassembly for LOOP-SVREF
; 0B243C08:       8D4424F8         LEA EAX, [ESP-8]           ; no-arg-parsing entry point
;       0C:       83EC0C           SUB ESP, 12
;       0F:       8945FC           MOV [EBP-4], EAX
;       12:       8BD3             MOV EDX, EBX
;       14:       8B3DC83B240B     MOV EDI, [#xB243BC8]       ; :ELEMENT-TYPE
;       1A:       BE27001001       MOV ESI, 17825831
;       1F:       8B5DFC           MOV EBX, [EBP-4]
;       22:       8B05CC3B240B     MOV EAX, [#xB243BCC]       ; #<FDEFINITION object for MAKE-ARRAY>
;       28:       B90C000000       MOV ECX, 12
;       2D:       892B             MOV [EBX], EBP
;       2F:       8BEB             MOV EBP, EBX
;       31:       FF5005           CALL DWORD PTR [EAX+5]
;       34:       8B5DF8           MOV EBX, [EBP-8]
;       37:       8BF2             MOV ESI, EDX
;       39:       81FB0B001001     CMP EBX, 17825803
;       3F:       7407             JEQ L0
;       41:       8D43FD           LEA EAX, [EBX-3]
;       44:       A807             TEST AL, 7
;       46:       743D             JEQ L3
;       48: L0:   81FB0B001001     CMP EBX, 17825803
;       4E:       7435             JEQ L3
;       50:       31C9             XOR ECX, ECX
;       52:       EB21             JMP L2
;       54: L1:   8D46F9           LEA EAX, [ESI-7]
;       57:       A807             TEST AL, 7
;       59:       753B             JNE L4
;       5B:       807EF9B2         CMP BYTE PTR [ESI-7], 178
;       5F:       7535             JNE L4
;       61:       8BD6             MOV EDX, ESI
;       63:       8B42FD           MOV EAX, [EDX-3]
;       66:       39C8             CMP EAX, ECX
;       68:       7633             JBE L5
;       6A:       8BC1             MOV EAX, ECX
;       6C:       894C0201         MOV [EDX+EAX+1], ECX
;       70:       8BC1             MOV EAX, ECX
;       72:       83C104           ADD ECX, 4
;       75: L2:   8BC3             MOV EAX, EBX
;       77:       39C1             CMP ECX, EAX
;       79:       7CD9             JL L1
;       7B:       BA0B001001       MOV EDX, 17825803
;       80:       8BE5             MOV ESP, EBP
;       82:       F8               CLC
;       83:       5D               POP EBP
;       84:       C3               RET
;       85: L3:   8B05D03B240B     MOV EAX, [#xB243BD0]       ; 'INTEGER
;       8B:       CC0A             BREAK 10                   ; error trap
;       8D:       03               BYTE #X03
;       8E:       1F               BYTE #X1F                  ; OBJECT-NOT-TYPE-ERROR
;       8F:       D0               BYTE #XD0                  ; EBX
;       90:       10               BYTE #X10                  ; EAX
;       91:       CC0A             BREAK 10                   ; error trap
;       93:       02               BYTE #X02
;       94:       18               BYTE #X18                  ; INVALID-ARG-COUNT-ERROR
;       95:       4F               BYTE #X4F                  ; ECX
;       96: L4:   CC0A             BREAK 10                   ; error trap
;       98:       04               BYTE #X04
;       99:       49               BYTE #X49                  ; OBJECT-NOT-SIMPLE-VECTOR-ERROR
;       9A:       FE9001           BYTE #XFE, #X90, #X01      ; ESI
;       9D: L5:   CC0A             BREAK 10                   ; error trap
;       9F:       04               BYTE #X04
;       A0:       22               BYTE #X22                  ; INVALID-ARRAY-INDEX-ERROR
;       A1:       90               BYTE #X90                  ; EDX
;       A2:       0F               BYTE #X0F                  ; EAX
;       A3:       4F               BYTE #X4F                  ; ECX
NIL

* (disassemble #'floop-aref)

; disassembly for FLOOP-AREF
; 0AF2A692:       8B55FC           MOV EDX, [EBP-4]           ; no-arg-parsing entry point
;       95:       8D5C24F8         LEA EBX, [ESP-8]
;       99:       83EC0C           SUB ESP, 12
;       9C:       8B3D60A6F20A     MOV EDI, [#xAF2A660]       ; :ELEMENT-TYPE
;       A2:       BE27001001       MOV ESI, 17825831
;       A7:       8B0564A6F20A     MOV EAX, [#xAF2A664]       ; #<FDEFINITION object for MAKE-ARRAY>
;       AD:       B90C000000       MOV ECX, 12
;       B2:       892B             MOV [EBX], EBP
;       B4:       8BEB             MOV EBP, EBX
;       B6:       FF5005           CALL DWORD PTR [EAX+5]
;       B9:       8B4DFC           MOV ECX, [EBP-4]
;       BC:       31C0             XOR EAX, EAX
;       BE:       EB09             JMP L1
;       C0: L0:   89440201         MOV [EDX+EAX+1], EAX
;       C4:       8BD8             MOV EBX, EAX
;       C6:       83C004           ADD EAX, 4
;       C9: L1:   39C8             CMP EAX, ECX
;       CB:       7CF3             JL L0
;       CD:       BA0B001001       MOV EDX, 17825803
;       D2:       8BE5             MOV ESP, EBP
;       D4:       F8               CLC
;       D5:       5D               POP EBP
;       D6:       C3               RET
;       D7:       CC0A             BREAK 10                   ; error trap
;       D9:       02               BYTE #X02
;       DA:       18               BYTE #X18                  ; INVALID-ARG-COUNT-ERROR
;       DB:       4F               BYTE #X4F                  ; ECX
NIL
* (disassemble #'floop-svref)

; disassembly for FLOOP-SVREF
; 0AF5494A:       8B55FC           MOV EDX, [EBP-4]           ; no-arg-parsing entry point
;       4D:       8D5C24F8         LEA EBX, [ESP-8]
;       51:       83EC0C           SUB ESP, 12
;       54:       8B3D1849F50A     MOV EDI, [#xAF54918]       ; :ELEMENT-TYPE
;       5A:       BE27001001       MOV ESI, 17825831
;       5F:       8B051C49F50A     MOV EAX, [#xAF5491C]       ; #<FDEFINITION object for MAKE-ARRAY>
;       65:       B90C000000       MOV ECX, 12
;       6A:       892B             MOV [EBX], EBP
;       6C:       8BEB             MOV EBP, EBX
;       6E:       FF5005           CALL DWORD PTR [EAX+5]
;       71:       8B4DFC           MOV ECX, [EBP-4]
;       74:       31C0             XOR EAX, EAX
;       76:       EB09             JMP L1
;       78: L0:   89440201         MOV [EDX+EAX+1], EAX
;       7C:       8BD8             MOV EBX, EAX
;       7E:       83C004           ADD EAX, 4
;       81: L1:   39C8             CMP EAX, ECX
;       83:       7CF3             JL L0
;       85:       BA0B001001       MOV EDX, 17825803
;       8A:       8BE5             MOV ESP, EBP
;       8C:       F8               CLC
;       8D:       5D               POP EBP
;       8E:       C3               RET
;       8F:       CC0A             BREAK 10                   ; error trap
;       91:       02               BYTE #X02
;       92:       18               BYTE #X18                  ; INVALID-ARG-COUNT-ERROR
;       93:       4F               BYTE #X4F                  ; ECX
NIL

こんな感じでoptimizeした結果は当然のように命令数が少ない。
とくに型チェックがないのがいいみたい。
またoptimizeするとsvrefとarefのコードに差がなくなっている。


let over lambdaでも触れているけど、プログラムを遅くする原因は3つ。
悪いアルゴリズム、悪いデータ構造、一般的なコード。
この一般的なコード、つまり汎用型は他のスクリプト言語では修正不可能な場合が多い。
だけどLispなら宣言の仕方で早いコードがかけますよというお話でした。


結論;多少早くなる、それよりoptimizeしろ。

elispでgoogle translate

google translate apiのversion2、REST形式を採用した。
(https://code.google.com/intl/ja/apis/language/translate/v2/using_rest.html)

(defun wget (url)
  (shell-command-to-string (concat "/usr/bin/wget -q \"" url "\" -O -")))

(defun translate-parse (text)
  "convert json text to translated text"
  (let ((regexp "translatedText\":\\s-*\"\\(.+\\)\""))
     (string-match regexp text)
     (match-string 1 text)))

(defun gtranslate (query &optional source target)
  "google translate"
  (let* ((source (or source "ja"))
         (target (or target "en"))
         (querykey "Input Your API Key")
         (json (wget (concat "https://www.googleapis.com/language/translate/v2?key=" querykey
	             "&q=" query
	             "&source=" source
	             "&target=" target
	             "&callback=handleResponse"))))
    (translate-parse json)))

(defun translate-message (from to text)
  (message "%s(%s):%s(%s)" text from (gtranslate text from to) to))

(defun trType (q default)
  (if (or (string= q "ja")
          (string= q "en")
          (string= q "de")
          (string= q "fr")
          (string= q "it")
          (string= q "no")
          (string= q "fi")
          (string= q "es"))
      q
      default))

(defun translate (from to text)
  "en,ja,fr,it,de,hi,ar,no"
  (interactive "stranslate from(default en):\nstranslate to(default ja):\nstext:")
  (let ((from (trType from "en"))
        (to (trType to "ja")))
    (translate-message from to text)))

自分のAPIを取得して、querykeyを置き換えたものを.emacsにかきかき。
M+x translateでつかえます。

elispでword count

就活のエントリーシートでwordcountが必要なときってよくある。
でもemacsのワードカウントコマンドってあるのかよく分からんかったので自分で作ってみた。

(defun wc (text)
  "word count"
  (length (apply 'concat (split-string text "[\s\n ]+"))))

(defun bwc nil
  "buffer word count"
  (interactive)
  (message "current buffer has %d words" (wc (buffer-string))))


(defun cwc nil
  "current clip board word count"
  (interactive)
  (message "clip board has %d words" (wc (current-kill 0))))


これを.emacs.emacs.elに書いてちょ。
適当な文章を開いて
M+x bwc
でスペースと改行を除いた文書全体のword数が出ます。


あとクリップボードにあるワード数は
M+x cwc
ででまつ。
GUI emacsの場合、右クリック&ドラックで選択領域を出してやってもいいし、
C+space -> M+w
などでコピーしてクリップボードに張り付けてもokです。

ubuntu10.10でopencv-androidのサンプルコンパイル

まずは・・・

opencvandroidで使うためには

http://opencv.willowgarage.com/wiki/Android

をチェック。
このあとの説明はほぼすべてここの説明の焼き直しです。
あとsdkはもう既にインストール済みであるという前提です。
パスもしっかり通してあるていでよろ。

$ cat ~/.profile |tail-2
PATH="$HOME/src/android-sdk-linux_x86/tools:$PATH"
PATH="$HOME/src/android-sdk-linux_x86/platform-tools:$PATH"
$ source ~/.profile

手っ取り早くopencvのサンプルアプリをインストール。

手っ取り早くサンプルをインストールして見たいなら

http://code.google.com/p/android-opencv/downloads/detail?name=CVCamera.0.7.apk

android端末のブラウザでダウンロードしてインストールするか、もしくはandroidをつないでコマンドライン上で

$ adb install CVCamera.0.7.apk

を実行

あと、このadbからのインストールの場合には、usbドライバの設定が必要。
ubuntu上でusbドライバ設定するには
HTC Desire HDなどのandroidをつないだ状態で、

$ lsusb
Bus 002 Device 004: ID 056e:0035 Elecom Co., Ltd 
Bus 002 Device 003: ID 413c:2003 Dell Computer Corp. Keyboard
Bus 002 Device 002: ID 8087:0020  
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0bb4:0ca2 High Tech Computer Corp. 
Bus 001 Device 002: ID 8087:0020  
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
$ sudo emacs /etc/udev/rules.d/51-android.rules
$ cat /etc/udev/rules.d/51-android.rules
SUBSYSTEM=="usb", SYSFS{idVendor}=="0bb4", MODE="0666"

0bb4がベンダーであるHTCを意味しており、0ca2はHTC Desire HDといった製品を意味するはず。
ベンダー名"HTC"を許可しますよという設定だと勝手に解釈してる。

ちなみに、ここを参考にしました。
http://y-anz-m.blogspot.com/2010/03/androidubuntu-xperia.html

この後に

$ adb kill-server ; sudo /ほにゃらら/android-sdk-linux_x86/tools/adb start-server

を実行。これでデバイスをadbで認識するので、adb installなどできます。
いちいち打つのが面倒なので、~/.bash_aliasesにaliasすることをおすすめします。次のような感じで。

$ emacs ~/.bash_aliases
$ source ~/.bash_aliases
$ cat ~/.bash_aliases
alias adbconnect='adb kill-server;sudo /ほにゃらら/android-sdk-linux_x86/platform-tools/adb start-server
$ adbconnect # do it

opencvの取得とコンパイル

いよいよ本題の自分でコンパイルについて。
subversionで最新版のopencvをとってきます。

$ svn co https://code.ros.org/svn/opencv/trunk/opencv/
$ cd opencv
$ mkdir release
$ cd release
$ cmake ../
$ make; sudo make install

cmakeをする際に必要なモジュールがなかったら、apt-getでとってきてくらさい。例えば、GTKだったら

$ sudo apt-get install libgtk2.0-dev

とか。

opencvandroidコンパイル

まずndkの改造版をhttp://www.crystax.net/android/ndk-r4.phpからとってきてください。

$ cd ~
$ wget "http://www.crystax.net/data/android-ndk-r4-linux-x86-crystax-4.tar.bz2"
$ tar xvf android-ndk-r4-linux-x86-crystax-4.tar.bz2 

ここで重要なのはndkをホームディレクトリに解凍することです。
後々のパスの設定で$HOME/android-ndk-r4-crystaxが適用されます。
ちょっとキモいですが、文句はopencvの著者にどうぞ。

さて、buildです。
あ、その前にswigはインストールしておいてくらさい。
staticライブラリのビルド。

$ cd opencv/android
$ mkdir build
$ make

次にandroid-jniのビルド。
これが後のプロジェクトへの橋渡し役になります。

$ cd opencv/android/android-jni
$ make 
ERROR local environement not setup! try:
gedit local.env.mk
Makefile:12: *** Please setup the local.env.mk - the default was just created'.  中止.
$ make
$ sh ./project_create.sh
$ ant compile

一回目のmakeは気にせずに、2回目のmakeを実行。
sh project_create.sh
で次のようにうまくいかない場合は、

Error: The project either has no target set or the target is invalid.
Please provide a --target to the 'android update' command.
$ android update project --name android-opencv --path . --target 2

などとターゲット指定。
ant compileで

BUILD FAILED
<android-sdk-root>\tools\ant\lib_rules.xml:121: Refrence android.libraries.src not found

になった場合はbuild.xmlを修正。

$ emacs build.xml
$ diff build.xml build.xml~ -u
--- build.xml	2011-02-08 02:28:04.329244958 +0900
+++ build.xml~	2011-02-08 02:19:18.396426362 +0900
@@ -80,6 +80,5 @@
              - customize to your needs.
     -->
     <setup />
-    <path id="android.libraries.src"><path refid="project.libraries.src" /></path>
-    <path id="android.libraries.jars"><path refid="project.libraries.jars" /></path>
+
 </project>

といった感じで、setupタグの終わりにpathを2行挿入。
またコンパイルは、gcj-jdkとopen-jdkなどが入っていて、sun-java6-jdkを入ってないケースでもエラーになる。
その場合、

$ sudo apt-get --purge remove gcj-jdk
$ #その他いろいろ削除
$ sudo apt-get autoremove
$ sudo add-apt-repository "deb http://archive.canonical.com/ lucid parter"
$ sudo apt-get update
$ sudo apt-get install sun-java6-jdk

などでsun-java6-jdkを入れると通る。

Calibrationサンプルのインストール

$ cd opencv/android/apps/Calibration
$ sh project_create.sh # if you fail, set target such as: android update project --name CVCamera --path . --target 2
$ ant debug
$ ant install

sh project_create.shでだめだったらまたターゲットを指定して実行。
ant installの際には実機デバイスをつないでおく必要がある。
これでCalibrationがインストールされるはず。

CVCameraサンプルのインストール

Calibrationとほぼ同様。

$ cv opencv/android/apps/CVCamera
$ sh build.sh
$ make
$ sh project_create.sh # if you fail, set tartget such as: android update project --name CVCamera --path . --target 2
$ ant debug
$ ant install

opencvアプリの自作

一番したいことはこれですが、正直結構めんどいです。
得にswigの設定とかだるすぎでし。
テンプレートはopencv/android/apps/camera_templateにあります。
気が向いたらそのうち書くかも。

simple quick sort

何年ぶりかに、quick sortを書いてみた。
たぶんこれ以上美しくはかけないと思う。
あくまで独断と偏見だけど。

void quickSort(int *a, int n){
  if( n <= 1 ) return;
  int i=1,j=n-1;
  int pivot = a[0];
  int swp;
  
  while( i<j ){
    if( a[i] <= pivot ){
      i++;
    }else{
      swp = a[i];
      a[i] = a[j];
      a[j] = swp;
      j--;
    }
  }
  
  if( a[i] > pivot ){
    i--;
  }
  
  a[0] = a[i];
  a[i] = pivot;

  quickSort(a,i);
  quickSort(&a[i+1],n-i-1);
}

どうして最後の比較と置換が必要になるかというと、
それはwhile実行では最後のiの示す要素の比較が行われていないから。
また{a_{first},pivot,{a_{last}}という感じでピボットを境に前半と後半でソートしたいから。

こんな感じで実行してね。

int main(int argc, char **argv){
  if( argc <= 1 ) return 1;
  int a[argc-1];
  int i,j;

  for(i=0; i<argc-1; i++){
    a[i] = atoi(argv[i+1]);
  }

  quickSort( a, argc-1 );

  for(i=0; i<argc-1; i++){
    printf("%d\n",a[i]);
  }
  return 0;
}