ラベル scheme の投稿を表示しています。 すべての投稿を表示
ラベル scheme の投稿を表示しています。 すべての投稿を表示

2014/08/04

gaucheでワンライナー

簡単な数値計算をするときはbcコマンドよりgoshを使うことが多い。

% gosh -e '(print (+ 1 1))' -E exit

なので、こういうコマンドを用意している。

#!/bin/sh
gosh -e "(print $1)" -E exit

~/binにgでシンボリックリンクを張って使っている。

% g '(+ 1 1)'

状態を持ちたかったり、少し複雑な計算をする時は、rlwrap gosh。

gaucheでワンライナーについて同僚と話題になった時、下記の様にbeginで囲って書いていたそうなのでメモがてら。

% gosh -e '(begin (print (+ 1 1))(exit))'

2013/11/14

transpose コマンド(tsv/csvの行列転置)

行列転置したいことは結構あるのに、shellでやろうと思うとちょっと面倒くさい。普段はExcelで「形式を指定して貼り付け」しているけど悔しい。

ので、簡単なコマンドにした。以前作ったcsv2sqlをコピってちょっと書き換えただけ。

ソースはこちら。

2013/08/03

複数のTwitterアカウントに連投するアレ

Gaucheスクリプト。ネタ元はこちら。

Gauche-net-twitterがTwitterのapi v1.1に対応してないっぽくて間に合わんなーと思ったら

対応してるのがあった。

で、スクリプトの使い方は、consumer-keyなんかを書いたファイルを用意してコマンドを実行。それぞれのtweetは別スレッドで投稿されます。

% ./tweet-bals-batch-balk.scm ばるす > bals.log

結果はこんな感じでわかる。

% cat bals.log | grep done | awk '{print $1}'| sort | uniq -c

合計はこれで。

% cat bals.log | grep done | awk '{print $1}'| sort | uniq -c | awk '{ total+= $1}END{print total}'

コマンド名が長いのでシンボリックリンクを作成した。

% ln -s `realpath ./tweet-bals-batch-balk.scm` ~/bin/bals
% bals ばるす > bals.log

詳しくはでたらめ英語なhelpをご覧ください。

% bals -h
Usage: bals [option ...] message
  h|help     : Show this help
  n|number   : Number of continuous tweets (default:endress)
  k|key-file : The path of the file for which have listed the Consumer-key and Access-token
                 ex) twitter-id1 consumer-key1 consumer-secret1 access-token1 access-token-secret1
                     twitter-id2 consumer-key2 consumer-secret2 access-token2 access-token-secret2
                     ...
                     twitter-idn consumer-keyn consumer-secretn access-tokenn access-token-secretn
                 (default: ~/.tbbbrc)
  i|interval :Interval (default: 0.1)
  s|suffix   :Message suffix (default: !)
  d|debug    :Debug mode. Print message to console, Twitter not update

ソースはこちら。

2013/07/30

iotaの由来(素数夜曲)

素数夜曲: 女王陛下のLISPに書いてあった。

P.474 脚注1)

なおこの名称は, 「その内容である index の頭文字を採用するに当たり, より印象的にする為に対応するギリシア文字イオタιを用いたことに因る」とされている.

この素数夜曲: 女王陛下のLISPは前半(というか本編?)の数学がP.332まで、後半のP.333からP.834までschemeによる付録(付録!?)で、その他付録含めトータル871ページで3,600円というお得な本。

SICPを読む前に読む本」とか「SICPに挫折した人のための本」とかそういうススメられかたをされる。Scheme手習いScheme修行も似たようなススメられかたをするけど、難易度で言えば素数夜曲の方が難しく手習いと修行の方が易しい。

説明が丁寧でわかりやすく、とくに後半のScheme部分がすごくいい。継続の説明が平易でわかりやすい。

2013/07/10

CSVをSQL文に変換する

以前、必要だったのでザックリ書いたスクリプトだけど、便利だったんで結構使用頻度が高い。使うたびに修正したり機能追加されてる。あんまりちゃんとしたスクリプトでもないけど重宝してる。こういうのって普通はExcelとかで生成したりするもんなんだろうか?昔いた会社ではExcelで生成してたなあ。あれはあれで慣れれば便利なのかもしれん。慣れたくないけどな。

SQLつながりだけど、プログラマのためのSQL第4版が出てるんですね。ちょっと読んでみたい。第2版だったかなー、本屋で数時間立ち読m(ゲフンゲフン

2013/07/06

Gaucheで各種ソートアルゴリズム

ソートアルゴリズムって、ふざけたもの含めて結構あるんだなー。ふざけてる系がすごく面白い。ボゴソートとかボゾソートとかパーミューテーションソートとか(笑)あとは基数ソート、ビーズズートなんかのバケツっぽいのが好きだなあ。スパゲティソートもいいなあ(w
Wikipediaにあったソート。ソートじゃないのも入ってるかも。

Gauche

Gaucheで書いてみたのが、今んとこ以下のもの。
気が向いたらsortカテゴリで追加していこうかな。
ところでGaucheのsortはイントロソートの親戚なのかな?
Gaucheの組み込みの(Cで実装された)ソートはデフォルトではQuick Sortで始めて、 再帰の深さが ceiling(2*log(N)) を越えた時にHeap Sortにスイッチするように してる。

参考



「リストをn個ずつのサブリストに分割 (Python)」をGaucheで

Gaucheにはそのものズバリなslicesという手続きがある。
(slices '(a b c d e f g) 3)
  ⇒ ((a b c) (d e f) (g))
(slices '(a b c d e f g) 3 #t 'z)
  ⇒ ((a b c) (d e f) (g z z))
で、それは置いといて、Pythonのzip(*[iter(s)]*n)ってのは、n個のiteraterを作ってzipしてるってことだと思う(python知らね)。
Gaucheだとgeneratorを使って実現できるんじゃないかな。Gaucheにもzip手続きはあるけど、gzipはない。gzipなしで書くとこんな感じのことかな。
(use gauche.generator)
(generator->list (apply gmap list (make-list 3 (giota 15))))
;; => ((0 1 2) (3 4 5) (6 7 8) (9 10 11) (12 13 14))
gzipを定義するとしたらこんなんでいいのかな。
(use gauche.generator)

(define (gzip . list-of-list)
  (apply gmap list list-of-list))

(generator->list (apply gzip (make-list 3 (giota 15))))
;; => ((0 1 2) (3 4 5) (6 7 8) (9 10 11) (12 13 14))

Gaucheでstrand sort

その他のソート

ソース

(define (strand-sort ls)
  (define (merge ls1 ls2)
    (let rec ((ls1 ls1)(ls2 ls2)(acc '()))
      (cond ((null? ls1)
             (reverse (append (reverse ls2) acc)))
            ((null? ls2)
             (reverse (append (reverse ls1) acc)))
            ((< (car ls1)(car ls2))
             (rec (cdr ls1) ls2 (cons (car ls1) acc)))
            (else (rec ls1 (cdr ls2)(cons (car ls2) acc))))))
  (define (filter-sorted-elements ls)
    (if (null? ls)
        '()
        (let rec ((ls (cdr ls))(sorted (list (car ls)))(acc '()))
          (if (null? ls)
              (values (reverse sorted)
                      (reverse acc))
              (let1 sorted? (< (car sorted)(car ls))
                (rec (cdr ls)
                     (if sorted?
                         (cons (car ls)
                               sorted)
                         sorted)
                     (if sorted?
                         acc
                         (cons (car ls) acc))))))))
  ;; body
  (let rec ((ls ls)(acc '()))
    (if (null? ls)
        acc
        (receive (sorted rest)
            (filter-sorted-elements ls)
          (rec rest (merge sorted acc))))))


(use gauche.sequence)
(define (test sorter n)
  (for-each (^i (let1 ls (shuffle (iota (expt 10 i)))
                  (print "; length = " (expt 10 i))
                  (time (sorter ls))
                  (print)))
            (iota n 2)))

(test strand-sort 5)
; length = 100
;(time (sorter ls))
; real   0.000
; user   0.000
; sys    0.000

; length = 1000
;(time (sorter ls))
; real   0.005
; user   0.000
; sys    0.000

; length = 10000
;(time (sorter ls))
; real   0.215
; user   0.210
; sys    0.010

; length = 100000
;(time (sorter ls))
; real   6.727
; user   6.710
; sys    0.000

; length = 1000000
;(time (sorter ls))
; real 205.260
; user 204.550
; sys    0.100


Gaucheでbogo sort

これはsleep sortを見て以来の衝撃だな・・・。

その他のソート

ソース

(use gauche.sequence)

(define (bogo-sort ls)
  (if (apply < ls)
      ls
      (bogo-sort (shuffle ls))))


(define data-5 (shuffle (iota 5)))
(define data-10 (shuffle (iota 10)))
(define data-15 (shuffle (iota 15)))

(time (bogo-sort data-5))
;(time (bogo-sort data-5))
; real   0.001
; user   0.000
; sys    0.000

(time (bogo-sort data-10))
;(time (bogo-sort data-10))
; real  12.053
; user  12.010
; sys    0.000




Gaucheでmerge sort

その他のソート

ソース

(use srfi-1)
(define (merge-sort ls)
  (define (merge ls1 ls2)
    (let rec ((ls1 ls1)(ls2 ls2)(acc '()))
      (cond ((null? ls1)
             (reverse (append (reverse ls2) acc)))
            ((null? ls2)
             (reverse (append (reverse ls1) acc)))
            ((< (car ls1)(car ls2))
             (rec (cdr ls1) ls2 (cons (car ls1) acc)))
            (else (rec ls1 (cdr ls2)(cons (car ls2) acc))))))
  (if (or (null? ls)
          (null? (cdr ls)))
      ls
      (let1 split-index (quotient (length ls) 2)
        (receive (head tail)
            (split-at ls split-index)
          (merge (merge-sort head)
                 (merge-sort tail))))))



(use gauche.sequence)
(define (test sorter n)
  (for-each (^i (let1 ls (shuffle (iota (expt 10 i)))
                  (print "; length = " (expt 10 i))
                  (time (sorter ls))
                  (print)))
            (iota n 2)))

(test merge-sort 6)


; length = 100
;(time (sorter ls))
; real   0.000
; user   0.000
; sys    0.000

; length = 1000
;(time (sorter ls))
; real   0.002
; user   0.010
; sys    0.000

; length = 10000
;(time (sorter ls))
; real   0.025
; user   0.030
; sys    0.000

; length = 100000
;(time (sorter ls))
; real   0.288
; user   0.280
; sys    0.000

; length = 1000000
;(time (sorter ls))
; real   3.422
; user   3.370
; sys    0.030

; length = 10000000
;(time (sorter ls))
; real  40.993
; user  40.620
; sys    0.240


Gaucheでselection sort

その他のソート

ソース

(use srfi-43)
(define (selection-sort ls)
  (define (vector-min-index vect start-index)
    (do ((i start-index (+ i 1))
         (min-value +inf.0)
         (min-index 0))
        ((= i (vector-length vect))(values min-index min-value))
      (when (< (vector-ref vect i) min-value)
        (set! min-value (vector-ref vect i))
        (set! min-index i))))
  ;; body
  (do ((i 0 (+ i 1))
       (vect (list->vector ls)))
      ((= i (length ls))(vector->list vect))
    (vector-swap! vect i (vector-min-index vect i))))


(use gauche.sequence)
(define (test sorter n)
  (for-each (^i (let1 ls (shuffle (iota (expt 10 i)))
                  (print "; length = " (expt 10 i))
                  (time (sorter ls))
                  (print)))
            (iota n 2)))

(test selection-sort 4)
; length = 100
;(time (sorter ls))
; real   0.001
; user   0.000
; sys    0.000

; length = 1000
;(time (sorter ls))
; real   0.030
; user   0.030
; sys    0.000

; length = 10000
;(time (sorter ls))
; real   2.614
; user   2.610
; sys    0.000

; length = 100000
;(time (sorter ls))
; real 255.403
; user 254.710
; sys    0.020



Gaucheでbozo sort

これもボゴソートと同じ類か(笑)

その他のソート

ソース

(use srfi-43)
(use srfi-27)

(define (bozo-sort ls)
  (random-source-randomize! default-random-source)
  (let ((vect (list->vector ls))
        (len (length ls)))
    (until (apply < (vector->list vect))
      (vector-swap! vect
                    (random-integer len)
                    (random-integer len)))
    (vector->list vect)))


(use gauche.sequence)

(dotimes (10)
  (let1 data (shuffle (iota 10))
    (time (bozo-sort data))
    (print)))

;(time (bozo-sort data))
; real  30.852
; user  30.740
; sys    0.000

;(time (bozo-sort data))
; real   0.862
; user   0.860
; sys    0.000

;(time (bozo-sort data))
; real   5.286
; user   5.280
; sys    0.000

;(time (bozo-sort data))
; real   0.598
; user   0.600
; sys    0.000

;(time (bozo-sort data))
; real   2.561
; user   2.560
; sys    0.000

;(time (bozo-sort data))
; real   4.554
; user   4.540
; sys    0.000

;(time (bozo-sort data))
; real   4.434
; user   4.420
; sys    0.000

;(time (bozo-sort data))
; real  12.168
; user  12.130
; sys    0.000

;(time (bozo-sort data))
; real  11.710
; user  11.670
; sys    0.000

;(time (bozo-sort data))
; real  20.846
; user  20.790
; sys    0.000



Gaucheでstooge sort

その他のソート

ソース

(use srfi-43)

(define (stooge-sort ls)
  (let1 vect (list->vector ls)
    (let rec ((head 0)(tail (- (vector-length vect) 1)))
      (when (< (vector-ref vect tail)
               (vector-ref vect head))
        (vector-swap! vect head tail))
      (when (<= 3 (+ (- tail head) 1))
        (let1 index-of-1/3 (quotient (+ (- tail head) 1) 3)
          (rec head (- tail index-of-1/3))
          (rec (+ head index-of-1/3) tail)
          (rec head (- tail index-of-1/3))))
      vect)))

(use gauche.sequence)
(define (test sorter n)
  (for-each (^i (let1 ls (shuffle (iota (expt 10 i)))
                  (print "; length = " (expt 10 i))
                  (time (sorter ls))
                  (print)))
            (iota n 2)))

(test stooge-sort 2)

; length = 100
;(time (sorter ls))
; real   0.031
; user   0.030
; sys    0.000

; length = 1000
;(time (sorter ls))
; real   7.330
; user   7.310
; sys    0.000


Gaucheでbead sort(ビーズソート)

これすごく面白かった。rosetta codeのracketのソースを参考にしたんだけど、そのコードに出てくるcolumnって手続きが目からウロコだった。これはビーズを通したヒモを立てることそのものだ。かっこいい。自分で書く時には末尾再帰にして名前もbead-downにした。

ここの図解がわかりやすい。

その他のソート

ソース

(define (bead-sort ls)
  (define (bead-down ls)
    (let rec ((ls (remove null? ls))(acc '()))
      (if (null? ls)
          (reverse acc)
          (rec (remove null? (map cdr ls))
               (cons (map car ls) acc)))))
  ;; body
  (map length (bead-down (bead-down (map (cut make-list <> 1) ls)))))



(use gauche.sequence)
(define (test sorter n)
  (for-each (^i (let1 ls (shuffle (iota (expt 10 i)))
                  (print "; length = " (expt 10 i))
                  (time (sorter ls))
                  (print)))
            (iota n 2)))

(test bead-sort 3)

; length = 100
;(time (sorter ls))
; real   0.004
; user   0.000
; sys    0.000

; length = 1000
;(time (sorter ls))
; real   0.406
; user   0.410
; sys    0.000

; length = 10000
;(time (sorter ls))
; real  49.590
; user  47.500
; sys    1.380


Gaucheでpermutation sort

その他のソート

ソース

(use util.combinations)

(define (permutation-sort ls)
  (if (or (null? ls)
          (null? (cdr ls)))
      ls
      (let rec ((candidates (permutations* ls)))
        (if (apply <= (car candidates))
            (car candidates)
            (rec (cdr candidates))))))


(use gauche.sequence)
(dotimes (i 11)
  (let1 data (shuffle (iota i))
    (time (permutation-sort data))
    (print)))


;(time (permutation-sort data))
; real   0.000
; user   0.000
; sys    0.000

;(time (permutation-sort data))
; real   0.000
; user   0.000
; sys    0.000

;(time (permutation-sort data))
; real   0.000
; user   0.000
; sys    0.000

;(time (permutation-sort data))
; real   0.000
; user   0.000
; sys    0.000

;(time (permutation-sort data))
; real   0.000
; user   0.000
; sys    0.000

;(time (permutation-sort data))
; real   0.000
; user   0.000
; sys    0.000

;(time (permutation-sort data))
; real   0.002
; user   0.000
; sys    0.000

;(time (permutation-sort data))
; real   0.011
; user   0.010
; sys    0.000

;(time (permutation-sort data))
; real   0.084
; user   0.080
; sys    0.000

;(time (permutation-sort data))
; real   0.760
; user   0.750
; sys    0.010

;(time (permutation-sort data))
; real  10.210
; user  10.180
; sys    0.000


2013/07/05

Gaucheでquick sort

自分も書いてみた。

書いたといっても、検索して出てきたshiroさんが書いたクイックソートのコードを参考にした。match使ってないだけ。

その他のソート

ソース

(use srfi-1)

(define (quick-sort ls)
  (if (null? ls)
      '()
      (receive (ws ys)
          (partition (pa$ > (car ls))(cdr ls))
        (append (quick-sort ws)
                (list (car ls))
                (quick-sort ys)))))


(use gauche.sequence)
(define (test sorter n)
  (for-each (^i (let1 ls (shuffle (iota (expt 10 i)))
                  (print "; length = " (expt 10 i))
                  (time (sorter ls))
                  (print)))
            (iota n 2)))

(test quick-sort 6)
; length = 100
;(time (sorter ls))
; real   0.001
; user   0.000
; sys    0.000

; length = 1000
;(time (sorter ls))
; real   0.004
; user   0.000
; sys    0.010

; length = 10000
;(time (sorter ls))
; real   0.060
; user   0.060
; sys    0.000

; length = 100000
;(time (sorter ls))
; real   0.737
; user   0.730
; sys    0.000

; length = 1000000
;(time (sorter ls))
; real   9.191
; user   9.110
; sys    0.050

; length = 10000000
;(time (sorter ls))
; real 124.532
; user 123.700
; sys    0.450



2013/06/23

ライフゲーム

以前も何度か書いたことがある。

以前書いたやつはすべてのセルを何度もなめてた。プログラミング・セミナーでは生きてるセルだけに注目する方法が載ってたので、それっぽいのを書いてみた。

ソースはこちら。

左の終端は右の終端と、上の終端は下の終端とつながるようにした。こういうのをトーラスと言うんですってね。

ところで、こういう↓マジキチレベルのライフゲーム

ハッシュライフってやつなのかな?

アルゴリズムの筋がよく了解され、確かに素晴らしいとわかっていても、つまらない字句の誤りでなんとなく全体の信用が落ちるから怖い。プログラミング・セミナー P.175

2013/06/22

Re: Unicodeで遊ぶ

Unicodeには、Ⓐ、ⓐなどといったマル付きの英文字があるみたいなので、英文字列を入力するとマル付き文字に変換する簡単なスクリプトを作ってみました。
というのを見かけたので、試しにGaucheで。

2013/06/18

shellでmarquee

HTMLにmarqueeってタグありますよね。

HTMLにmarqueeってタグありますよね。

shellにそういうコマンドないのかなーと思って探したけど見当たらなかったのでgaucheで書いてみた。gaucheのversionは以下の通り。ただテキストが右から左へ流れるだけのしょうもないコマンドができた。

% gosh -V
Gauche scheme shell, version 0.9.4_pre3 [utf-8,pthreads], x86_64-unknown-linux-gnu

使い方は

% marquee hoge
とか
% cat message.txt | marquee
などすればOK。終了はCtrl-C。

-rオプションで左から右へ。alternateオプションは作るつもりだったけど疲れたので作らず放置。helpはいつも英語で書くけど英語全然わからん。

% marquee -h
usage: marquee [option] ... input
 options:
   h|help           print this help
   a|alternate      move from side to side
   s|scrollamount   milliseconds of scrolling speed (default: 100)
   r|reverse        move to right

デカ文字を流したければbannerコマンドとかfigletコマンドの結果を投げつけて下さい。

ソースは以下の通り。なんかごちゃごちゃしてしまったけど動いてるのでこれでいいや。

2013/03/23

Land of Lisp 10章のシミュレーション

画像は Land of Lisp 10 章で作るシミュレーションの世界にて100万日が経過した状態。

遺伝子とエネルギーを持った動く動物が、草と森がある世界で動きまわって食事をし、無性生殖で繁殖する世界のシミュレーション。動物は遺伝情報に従い特定の動きを見せ、動くことでエネルギーを消費する。草を食べることでエネルギーを補充、繁殖でエネルギーを大幅に消費、エネルギーが足りないと繁殖できない、エネルギーが切れると死ぬ、というもの。

ライフゲームも似たようなもんだよね。

プログラムの大部分は本に載っているCommon Lispのコードと翻訳者であるshiroさんが公開されているGaucheによるコードを基に、少し改造していくつかの条件をパラメータで渡せるコマンドにしてみたもの。

パラメータをいじって30万日くらい動かすと結果が違って楽しい。動作はコマンドを実行してEnterを押すごとに世界が1日進む。300000などの数値を打ち込んでEnterを押すとその分日数が経過する。


さて、読んでいてよくわからなかったのが、P.202の turn 手続きで移動方向を決める部分。説明を読んでもいまいち意味がわからなかった。angle 手続きを呼び出す辺り。angle の定義はこれ。

(define (angle genes x)
  (let1 xnu (- x (car genes))
    (if (< xnu 0)
        0
        (+ 1 (angle (cdr genes) xnu)))))

自分なりに書きなおしてみたのはこれ。

(define (angle genes x)
  (let rec ((genes genes)(x x)(acc 0))
    (let1 xnu (- x (car genes))
      (if (< xnu 0)
          acc
          (rec (cdr genes) xnu (+ acc 1))))))

angle 手続き事態は難しくないけど、これを使って何をやってるのかがわからなかった。

angle の仕事は、引数 x を基に、引数 genes(リスト)から一つ要素を選び、選ばれた要素のインデックスを返すこと。例えば、genes が (1 1 10 5 2 1 1 1) だった場合、合計が22なので x は0〜21のランダムな数値(angle を呼び出す側で決められる)で束縛される。angle の評価結果として出現する頻度が最も高いのが2、次が3、その次が4。

絵に書くとこんな感じか。絵の上の行の数値が x 、下が選択される要素。

今この絵を描いていて思いついたけど、以下のようなリストからランダムに選ぶのと同じってことだな。

(use srfi-27)
(let1 genes '(1 1 10 5 2 1 1 1)
  (apply append
         (map (^(g i)
                (iota g i 0))
              genes
              (iota (length genes)))))
;; => (0 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 4 4 5 6 7)

ということで、angle 手続きは下記のようなものでも良いということか。

(define (angle genes x)
  (~ (apply append
            (map (^(g i)
                   (iota g i 0))
                 genes
                 (iota (length genes))))
     x))

余談

これ、条件をちゃんと考えたら「ライフメーカーの掟」のプロローグ部分(ロボットがバグって進化し始める)のシミュレーション作れるんじゃないの。 (「ロボットがバグって進化し始める」っていう説明ではすごくちゃちなものに聞こえてしまうな。これをホーガン氏が書くとどえらい壮大なことになるんだよなあ。) このシミュレーションプログラムを有性生殖にして工場を作るだけでも近いものになりそうだな、という話。