2009-10-17
SICP Lite #5 ×素人臭いSICP読書会 in Java-ja に参加した話
秋口に入って、そろそろ仕事にも慣れてきたというか、職場で使う言語以外でアルゴリズムの勉強すっか*1と思い、Haskellとscheme再開してたんだけど*2、Java-jaのMLにSICP読書会の告知があったので参加しました。
SICP Lite #5 × 第1回チキチキ もっと素人臭いSICP読書会 in Java-ja : ATND
SICPもたぶんこれを機会にまじめに読み始めた気がするので、とても良い契機になった。
進度→第1章10P1.1.7「例:Newton法による平方根」まで
会場では、参加者のSICPどこまで読んでる具合とか、「勉強会や読書会はじめてなんですけど」など色々あるのでいくつかグループに分れて進行。
自分はその中で読書会初経験者なので「はじめから」グループでの参加。
同グループには自分と同じく読書会初経験の人やSICP初心者です、という人も。
進行は各グループで自己裁量にまかされていたので、結局全員で手探りでやっていた。
そんな感じだったので、今回は一番最初の問題からLispの文法基礎だったり、式評価について解説している問題1.5あたりまで進め、回答に対して、自分なりの解説を本文から引用する、という形式をとりました。
問題解いた後は各自で13Pまで読み進めてタイムアップ。
ちなみに、同じグループに参加してたetoさんがマジで江渡浩一郎さんだった。
以下、自分の問題への回答
問題1.1
これ、goshで実行すると問題にならないので、どういう順序で式を評価しつづけ、印字結果に至るのか、というのを口述、という形に。
lispの文法書式って特殊とおもわれがちだけど、これ以外と読みやすい事を再発見
自習してた時はこんな風にコメント書いて回答としてた。
hemeStruc
問題1.2
分子分母で改行
;; 問題1.2 (/ (+ 5 4 (- 2 (- 3 (+ 6 (/ 4 5))))) (* 3 (- 6 2) (- 2 7)))
問題1.3
「最小値を省いた二つの数の2乗の和」と考えるのがポイントか
;; 問題1.3 ;; 三つの数を引数としてとり、大きい二つの数の2乗の和を返す手続き (define (f a b c) (define (g i j) (+ (* i i) (* j j))) (cond ((and (< a b) (<= a c)) (g b c)) ((and (< b a) (<= b c)) (g a c)) ((and (< c a) (<= c b)) (g a b)) (+ (* a a) (* a a))))
問題1.4
回答内容はコメント部分。
ただ、自分はまだこれを実際に活用できない。
大抵実行時エラー出しちゃんだよなぁ。
;; 問題1.4 (define (a-plus-abs-b a b) ((if (> b 0) + -) a b)) ;; if (> b 0) ;; (+ a b) ;; else ;; (- a b) (a-plus-abs-b 5 6) (a-plus-abs-b 5 -6)
問題1.5
;; 問題1.5 (define (p) (p)) ;; ずっと再帰的に呼びつづけてしまう (define (test x y) (if (= x 0) 0 y)) (use slib) (require 'trace) (trace p) (test 0 (p))
トレースするとこうなる
gosh> p
gosh> test
gosh> #<undef>
gosh> #t
gosh> #<closure (debug:trace-procedure debug:trace-procedure)>
gosh> CALL p
CALL p
CALL p
CALL p
CALL p
つまりif式(節?)での条件分岐の際に、lispは作用的順序を採用している為に、「条件が成立してようとしていなくても、"alternative"を評価する」という事。
これ、「Haskellで同じ関数定義して実行してみるとやっぱり0が返ってくるんでしょうね」って会場で思いついたのでHaskellでテストできるコードを書いて実行してみた。
--p :: Integer -> Integer p = p --test :: Integer -> Integer -> Integer test x y | x == 0 = 0 | otherwise = y
別に型付け宣言しなくてもいいよ
実行結果
Main> test 0 $ p 1 0
よし。遅延評価ですね。
次回
当グループは次回までに24Pまで各自予習ないし復習をしてくる、という事に(もちろん自分のペースでどんどん先に進んでよし)。
日時
2009/11/18(水)19:00開始、21:00終了
場所
グリー株式会社 (東京都港区六本木4-1-4 黒崎ビル3F)
あれっ、予定変ってる!! 解散時はもっと遠い会場で午後半休覚悟してたのに。
2008-05-28「シャープペンシルはダメです」となぜか小学校では使えなかった世代
「人は明度を等比で感知する」ということをProcessingで検証してみた
Processing, Design, color | |
![]()
明度差は等比で認識する。
これはユニバーサルカラーデザイン(色彩計画におけるユニバーサルデザイン)について調べていた時に知ったことなんだけど、人の色覚において、明度(色の明るさ)の感受は等差階級ではなく等比階級で認知するとか。
つまり、どういうことかというと、単純にillustratorやphotoshopで等間隔の数値で色を作ってもそれは数字的には等間隔の階調ではあっても、「"人の目にとって"等間隔ではない」ということらしい。
もし、等間隔の明度計画を考える必要があるとき、たとえばHSB値のBrightnessを(100, 90, 80, 70, …)ではなく、(100、90、 81、 72.9, …)とする、ということらしい。
じゃあ、それProcessingで検証してみようじゃないの
sketch
奇数行を等比階調、偶数行を等差階調にグラデーションするようにして、下に行くほどその階調差を強めるようなSketchを書いた。
で、コレ↓
1行目{100, 90, 81, 72.9, …} (* 90%)
2行目{100, 90, 80, 70, …} (- 10%),
3行目{100, 80, 64, 51.2,…} (* 80%),
4行目{100, 80, 60, 40, …} (- 20%),
ちょっと比較しにくいけど、これをぱっと見してると等比階調の方が使い勝手よさそうだ、っていうのだけわかる。
ピッチ差を調整して再試行。こんどは等差階調の方をもっとゆるやかにしてみる。
あれれ、偶数行のピッチ差を2%にしてコレ。
2行目{100, 90, 80, 70, …} (- 10%)
4行目{100, 88, 76, 65, …} (- 12%)
等差のグラデーションは左側は比較的なめらかだけど、右の黒みがかるところでいきなりガクンと差がついて見えるはず。
対して等比のグラデーションの方はグレーの階調がどのピッチでも比較的滑らかに見える。ただ白とライトグレーの差がキツく出ている。
どうやら定説どおり明度のグラデーションは等比で考えた方が良いみたいだ。
等差階調
交互だとみづらいかもしれないので今度はそれぞれの階調でみてみる。
初期値ピッチ2、でピッチ差を1づつ強めてこんな階調。やっぱり右端で穴があいたような急落が起きるね。
そこだけじゃなくて、ところどころ注視するとけっこうな「階調の段差」が見えてしまう。
となりあう色の相互作用で紙の折れ目のような影や光を感じる効果が起きる(現象の名前失念した)んだけど、それを考慮しても許容しづらいレベル。けっこうパキッ、パキッ、と不規則に折れたように見える。
等比階調
初期値ピッチ97.5%から行ごとに2.5%づつ階調比をつよめてこんな感じ。一番下の行で75%階調。
うん、等差階調にくらべて本当に滑らかですね。特に左上の角の明度が比較してキレイに分布しています。
こりゃトーンカーブの概念じゃねぇか
ただ、100と75や25と18.75だと随分実感覚と差が出てしまうから、やはり全て一定の比ではなくて「明るみの部分は比率差を小さく、中腹では一定、暗くなるにしたがって比率をまた小さく」と調整するのが賢明かな、と。
そう、トーンカーブのことですね!
一人で勝手にこのことがわかって深夜にはしゃいじゃった。あーそういう意味だったのかー。
まとめ
「明度は等比階調で認知する」は真っぽい。
だからデザイナーも色計画においては明度は等比階調を心掛ける
というか、
これをもって、色計画を真面目に見返りしようかな、と思います
使用したsketchコード
アウトプットしたいモノの部分のコメントをはずせばおk。
float x0, x1, y0, y1; float br, brin1, brin2; int countL; void setup() { size( 600, 200); colorMode(HSB, 360, 100, 100, 100); background(0); smooth(); noLoop(); noStroke(); x0 = 0; x1 = width/10; y0 = 0; y1 = height/10; br = 100; brin1 = 0.975; // 等比階調の初期ピッチ brin2 = -5; // 等差階調の初期ピッチ countL = 1; } void draw() { while ( y0 < height){ /** * 等比と等差をあわせ比べる if (countL%2 == 1) gradR(brin1); else gradD(brin2); */ // gradR(brin1); // 等比階調のみ // gradD(brin2); // 等差階調のみ if ( x0 >= width){ println(brin1); Xupdate(); } } save("draw.png"); } void Xupdate(){ x0 = 0; x1 = width/10; y0 = y1; br = 100; /* * 等比と等差を比べる if (countL%2 == 1) brin1 -= 0.1; else brin2 -= 2; */ // brin1 -= 0.025; // 等比のみ // brin2 -= 1; // 等差のみ y1 += height/10; countL += 1; } void gradR(float brin){ while( x0 < width){ drawgrad(); br *= brin; } } void gradD(float brin){ while( x0 < width){ drawgrad(); br += brin; } } void drawgrad(){ fill(0, 0, br); rect(x0, y0, x1, y1); x0 = x1; x1 += width/10; }
基本的なことの気付きとか
Processing | |
![]()
たしかにもっと高度なこととか複雑なこととかしたいんですが、最近はどんどん単純で基礎っぽいことに傾倒していて。
再帰とか
平面をある図形でうめるって数列の問題だったんだなー、なんて。
例えば等差数列は
float a = 1, b = 3, S; // 初項, 公差, 第N項までの和 int N = 100; // 求める項数 S = a; // S(1) = a for (int i = 0; i < N; i++) { if(i != 0) { S += b; } print(S); }
たぶんこんな風に書けるんだけど、下のこういうコードはもろにそれ。
float x, y, radius; // x, y座標、 半径 float bd; // 明度差の単位 void setup(){ size( 400, 400); background(0); noLoop(); smooth(); noStroke(); radius = 20; x = radius; y = radius; bd = 0.7; } void draw() { while( y < height) { float r = random(100); // 確率変数r if (r <= 25) fill(255); else if (r <= 50) fill(255*bd); else if (r <= 75) fill(255*bd*bd); else fill(255*bd*bd*bd); ellipse(x, y, radius, radius); x += radius; if (x >= width) { x = radius; y += radius; } } save("draw.png"); }
数列の和が、数字じゃなくて平面図像におきかわったって感じ。
確率とか
シダの葉フラクタルのサンプルコード見て、ずっと悩んでいた確率の実装のやりかたをやっと知ったり。ふつうにプログラム勉強してれば何を悩むことがあろうかって問題だった。
float r = random(100); if (r <= 30) hoge(); else if (r <= 50) huga(); else …
ってればいいだけの話だったんだね。
遅延学習なんとか
たとえば色の選択だっり、図形の比率がどういう造形をつくって、それの魅力効果とか、機能性とかなら自分も今まで持った知識でやれるんだけど、プログラムに関してはいまだやっぱり「けっこう事前に諸処を全体的に知ってないとモノができない」印象を持ってしまう。最近むしろつよまってる。
プログラマの人にいわせればそんなことないらしいのだけれど。
うぅーん。
遅延学習法だと限界あるような気がしてるし、今回のってかなり初歩的なとこだと思うけど気付くのに時間かかった。
2008-05-26絵の具にエメラルドグリーンが入ってるとリッチな気分を味わえた世代
そろそろアップレットで人に見せたいのだけど
Processing, 駄文 | |
![]()
そろそろただ見せるだけじゃなくてアップレットとしてブラウザで操作体験して楽しいモノ、にしたいし、そうしたインタラクティブなモノを作っては公開したくなった。
先のサンプルコードを改変して遊ぶ - 茨城は夜の8:06 - ハチロク世代も、ただ見るよりは g, f 押して重力モードの切り替えを自分でして様子を見てるほうが楽しい。あと自分のエンコーディングのテクニック不足なのもあるけど、動画だとどうしても実際より解像度低いから自分の見せたいきれいさは体験させることができない。
ゲームはやっぱり自分でやるのが一番楽しいように。
調べてたら公開自体はめちゃ単純で、サイトのディレクトリに.jarファイルにエクスポートしたsketchを置いて
<div> <applet code="hoge" archive="hoge.jar" width="WIDTH" height="HEIGHT"></applet> </div>
これだけで公開できるっぽい。
サイトデザインとか考えてた自分なんだったんだろ。
しかし、ともかく公開するためにhtml置くスペース必要なんでどこからか借りなきゃ。どこにしようかな。
2008-05-24失われた10年を物心ついてから思春期が終わるあたりまで過ごした世代
n次関数のアニメーション
Processing, Animation, generative_script | |
![]()
ビデオキためす
vimeoのはもうちょっとだけ画質いい
まちがって消してしまいました。ちょっと直してupなおし
import processing.video.*; MovieMaker mm; float x, y, radius; float y1, y2, y3, y4; int wp1, wp2, wp3, wp4, wp5; int loopcount, limit; void setup() { size( 640, 480); background(0); frameRate(30); smooth(); radius = 100; x = -radius; wp1 = width*1/8; wp2 = width*3/8; wp3 = width*4/8; wp4 = width*5/8; wp5 = width*7/8; mm = new MovieMaker(this, width, height, "drawing.mov", 30, MovieMaker.VIDEO, MovieMaker.LOSSLESS); loopcount = 0; limit = 12; } void draw() { fill(125, 1); noStroke(); rect(0, 0, width, height); stroke(255, 1); line(0, height/2, width, height/2); line(width/2, 0, width/2, height); x += 5; if (x > width+radius) { x = -radius; loopcount += 1; } y2 = -((x-wp1)/10 * (x-wp5) /(width*0.1)); y3 = -((x-wp1)/10 *(x-wp3)/10 *(x-wp5) /(width*1.25)); y4 = -((x-wp1)/10 * (x-wp2)/10 * (x-wp4)/10 * (x-wp5) /(width*20)); if (loopcount%3 == 0) fXdraw( x, y2, radius); if (loopcount%3 == 1) fXdraw( x, y3, radius); if (loopcount%3 == 2) fXdraw( x, y4, radius); mm.addFrame(); if (loopcount >= limit) { mm.finish(); println("finished"); exit(); } } void fXdraw(float xin, float yin, float rin){ x = xin; y = yin; y = y + height/2; radius = rin; if (y < height + radius) { stroke(255, 0, 0, 100); strokeWeight(2); if (loopcount < 3) ellipse(x, y, radius, radius); else if (loopcount < 6) ellipse(x, y, (y - height/2)*1.5, (y - height/2)*1.5); else if (loopcount < 9) ellipse(x, y, (y - height/2)*2, (y - height/2)*2); else if (loopcount < 12){ y = sqrt(y*y); ellipse(x, height/2, (y - height/2)*2, (y - height/2)*2); } } }
サンプルコードを改変して遊ぶ
Processing, Animation, generative_script | |
![]()
vimeoにも上げました→BounceBalls on Vimeo
はてなの動画張り付け、vimeoにも対応して欲しいです。
BouncyBubbles \ Learning \ Processing 1.0 (BETA)
↑のサンプルコードをアレンジして重力、無重力のシュミレート切り替えたり、キー操作で録画開始、終了したり。
重力下、無重力下のモード切り替えについては、元のコードの
… float gravity = 0.03; …
を
… float gravity, nonG = 0, G = 9.8/frameRate; … void setup(){ … gravity = nonG; …
として、
void keyPressed(){ if (key == 'g' || key == 'G'){ gravity = G; println("Key Type:g ::Gravity"); } else if (key == 'f' || key == 'F'){ gravity = nonG; println("Key Type:f ::Non Gravity"); } … }
と追記すればOk。
そろそろ書くコードもけっこう長くなって、なんかここに全部貼るのも気がひけてきたり。
作例のキャプチャ
カラフルすぎるとかえって複雑さがそがれるのね
2008-05-22小学→ストII、中学→KOF、高校→ギルギア にはまってた世代
このごろのSketch
Processing, generative_script | |
![]()
しばらくn次関数曲線にハマッてた。
全部↓のファイル一つのパラメータ弄る程度でできて、しばらく面白い表現を模索してた。
でも、やってること自体はまったく初歩的で、関数定義すらしてない。
processingのsetup()もdraw()も必要としてない。
だから学習としては停滞してるんだろな。
で、それじゃあんまりだし、ということで左→右にかきこまれていくアニメーションに書きなおしてみたり。
やっぱり、同一のファイルの値をコネコネするのも結構結果が変わるし、次のアイディアにつながりはするけど、プログラミングというか、もっと上位概念での構築(構成、レイアウトとか、オブジェクト指向でもっと先々まで拡張性をもたすとか)の組立を向上させたいなら0から何度も書き直すのがよさげ。 でも書けば書くほど行長のびてコード自体も煩雑になってるような…。
それぞれのy関数のグラフをクラスにしてグラフごとに違う色を与えようとしたんだけど、12時で学校しまってやる気が尽きてしまった。後日挑む。
processing.jsが来た!! と思ったんだけど、結局公開してもらうにはHTML置くスペースいるし、それで個別にブラウザのページ開いて実行するんだったらデフォルトのJAVAアップレットでいいじゃないか! むしろ はよレン鯖でも借りてCSS+XHTMLでもやりなさいよ的結論が出てわっしょいわっしょい そんなに一度にやってられるかいな→結局うごけない
という要は勇気がないんでしょ 820users。
ちなみにProcessingのpdeファイルの呼称はsketchなんだけど、スケッチって言うと手で描く方もあるからちょいめんどくさいぞ、僕両方描くし。
anatoo2008/05/23 23:18ごいすー
VoQn2008/05/24 23:41次のエントリにちょっと追記しますー

















