校正待ちですることがないので(後半はうそ)、Code Golf の "Switchboard" という問題に手をつけてみた。コードを短くすることはともかく、この問題は解法を考えるのが面白かった。いまのところ23位だけど、これが個人的なスキルの限界だと思う。
Scheme は受け付けてない。そうとはしらず最初は暢気に Scheme で書いたことはいうまでもない。しょうがないので Ruby で書き直したんだけど、"gets" だけで標準入力から1行読み取れるなんて。実用的にもほどがある。
(define a '(1 2 3))
(let ((current-a (list-copy a)))
(set-car! a 0)
(set-cdr! a current-a))
gosh>a
(0 1 2 3)
(define a '(1 2 3))set-car! と set-cdr! の場合には、もともと a が指し示す領域にあったデータが書き換わっている。それに対して set! でやっていることは、もともと a が指し示す領域にあったデータは換わってなくて、a という名前で束縛されていたものを別の場所に cons して作った (0 1 2 3) に 付け換えたにすぎない。
(set! a (cons 0 a))
gosh>a
(0 1 2 3)
(define (fib n)
(let fib-iter ((a 1) (b 0) (count n))
(if (= count 0)
b
(fib-iter (+ a b) a (- count 1)))))
(define (fib n)
((lambda (a b count)
(if (= count 0)
b
(fib-iter-1 (+ a b) a (- count 1))))
1 0 n))
(lambda (fib-iter)
(lambda (a b count)
(if (= count 0)
b
(fib-iter (+ a b) a (- count 1)))))
(define (fib n)
(((lambda (fib-iter)
(lambda (a b count)
(if (= count 0)
b
(fib-iter (+ a b) a (- count 1)))))
fib-iter-omega)
1 0 n))
(lambda (fib-iter) (fib-iter fib-iter))
(lambda (delusion)
((lambda (fib-iter) (fib-iter fib-iter))
(lambda (f) (delusion (lambda (x y z) ((f f) x y z))))))
(define (fib n)
(((lambda (delusion)
((lambda (fib-iter) (fib-iter fib-iter))
(lambda (f) (delusion (lambda (x y z) ((f f) x y z))))))
(lambda (fib-iter)
(lambda (a b count)
(if (= count 0)
b
(fib-iter (+ a b) a (- count 1))))))
1 0 n))
gosh> (map fib (iota 20))
(0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181)


#! /usr/local/bin/gosh
(use gauche.vport)
(use srfi-13)
(define argv-str
(let R ((files *argv*) (str ""))
(if (null? files)
""
(call-with-input-file (car files)
(lambda (port)
(let ((joined-string
(string-join (list str (port->string port)) "" 'strict-infix)))
(if (not (null? (cdr files)))
(R (cdr files) joined-string)
joined-string)))))))
(define (getc str)
(cond ((> (string-length str) 0)
(let ((c (string-ref str 0)))
(set! argv-str (string-drop str 1))
c))
((= (string-length str) 0)
"")
(else
(error "Out of Range -- getc"))))
(define (argf thunk)
(if (string-null? argv-str)
(with-input-from-port (current-input-port)
thunk)
(with-input-from-port
(make <virtual-input-port>
:getc (lambda () (getc argv-str)))
thunk)))
;;; test
(argf (lambda ()
(port-for-each
(lambda (line) (print (regexp-replace #/hello/ line "damn")))
read-line)))
$ cat test.txt
hello world
this is argf test
$ ./argf.scm test.txt test.txt
damn world
this is argf test
damn world
this is argf test
$ cat test.txt test.txt | ./argf.scm
damn world
this is argf test
damn world
this is argf test
gosh>
(define A
((make-matrix 6 6)
0.68 0.65 0.8 0.11 0.01 0.14 0.65 0.88 0.89 0.02 0.19 0.01 0.8 0.89 0.91 0.02 0.04 0.1 0.11
0.02 0.02 0.81 0.82 0.77 0.01 0.19 0.04 0.82 0.81 0.64 0.14 0.01 0.1 0.77 0.64 0.66))
gosh> A
((0.68 0.65 0.8 0.11 0.01 0.14) (0.65 0.88 0.89 0.02 0.19 0.01) (0.8 0.89 0.91 0.02 0.04 0.1)
(0.11 0.02 0.02 0.81 0.82 0.77) (0.01 0.19 0.04 0.82 0.81 0.64) (0.14 0.01 0.1 0.77 0.64 0.66))
gosh> (eigenvalues-jacobi A)
(-0.010575430595377565 -0.09400171282374802 2.109504119397093 -0.08138275206455295 0.279213041557744 2.5472427345288424)
(define (matrix-transform m)ちょっと満足。ただし単位行列や回転行列を定義するのに要素を頭からなめるはめになってるんだけどね。満足しちゃだめ!
(apply zip m))
(define (matrix-product m1 m2)
(if (not (= (line-length m1) (row-length m2)))
(error "Matrix-Product Not Defined" (list m1 m2))
(apply (make-matrix (line-length m1) (row-length m2))
(map (cut fold + 0 <>)
(map (cut apply map * <>)
(cartesian-product (list m1 (matrix-transform m2))))))))
(define (matrix-sum m1 . ms)
(map (cut apply map + <>)
(apply zip m1 ms)))

f が集合 A から集合 B への単射つまり、単射という写す集合と写される集合の要素に関する問題を、移すほうに値域を持つ別な任意の写像(ただし定義域は固定)どおしの関係として定義すればいいってこと(ちなみに講義では、たぶんあえて、定義域とか値域うんぬんの議論をぼかしてた。当たり前っちゃ当たり前のことなんだけど、これが固定されていないと f との合成写像を取ったところで何の意味もない。そのため圏論では、定義域と値域をあわせて写像ではなく「射」という言葉を使ってる。たぶん。僕のこれまでの圏論の認識といえば「射で考えるやり方」という程度だったので、今日の講義でようやくさっぱりした)。
=def
任意の集合C と任意の h,k:C→A について f・h = f・k ⇒ h = k
(define (quicksort/values ls)
(define (low-x-high)
(values
(filter (cut > (car ls) <>) (cdr ls))
(list (car ls))
(filter (cut <= (car ls) <>) (cdr ls))))
(if (null? ls)
'()
(receive (low x high)
(low-x-high)
(append (quicksort/values low)
x
(quicksort/values high)))))
(define (quicksort/values ls)
(if (null? ls)
'()
(call-with-values
(lambda ()
(values
(filter (lambda (x) (> (car ls) x)) (cdr ls))
(list (car ls))
(filter (lambda (x) (<= (car ls) x)) (cdr ls))))
(lambda (low x high)
(append (quicksort/values low)
x
(quicksort/values high))))))
(use srfi-1)Code Kata というより Scheme Kata?
(define ls '(4 9 2 5 8 7 3 1 6 4))
(define (quicksort1 ls)
(if (null? ls)
'()
(append (filter (lambda (x) (> (car ls) x)) (quicksort1 (cdr ls)))
(list (car ls))
(filter (lambda (x) (<= (car ls) x)) (quicksort1 (cdr ls))))))
(quicksort1 ls)
(define (quicksort2 ls)
(call/cc
(lambda (k)
(if (null? ls)
k
(append (filter (lambda (x) (> (car ls) x)) (quicksort2 (cdr ls)))
(list (car ls))
(filter (lambda (x) (<= (car ls) x)) (quicksort2 (cdr ls))))))))
(quicksort2 ls)
(define (quicksort/cps1 ls k)
(if (null? ls)
(k '())
(quicksort/cps1
(cdr ls)
(lambda (cdrls)
(append (filter (lambda (x) (> (car ls) x)) (k cdrls))
(list (car ls))
(filter (lambda (x) (<= (car ls) x)) (k cdrls)))))))
(quicksort/cps1 ls (lambda (k) k))
(define (quicksort/cps2 ls k)
(if (null? ls)
(k '())
(quicksort/cps2
(filter (lambda (x) (> (car ls) x)) (cdr ls))
(lambda (ls-lower)
(quicksort/cps2 (filter (lambda (x) (<= (car ls) x)) (cdr ls))
(lambda (ls-upper)
(k (append ls-lower
(list (car ls))
ls-upper))))))))
(quicksort/cps2 ls (lambda (k) k))